How to expand and collapse table row using Bootstrap Accordion and ASP.NET MVC? - asp.net-mvc

I want to expand and collapse table row using Bootstrap Accordion.
Currently, if I click on any row, it expands and collapse. But what I want is that, if I click on second row then first row should collapse if it is expanded then and so on.
<div class=" panel-body">
<table class="table">
#foreach (var item in Model)
{
<tr>
<td class="accordion-toggle" data-toggle="collapse" data-target="#AA_#(item.Id)">
<button class="bb" type="button">
#Html.Raw(item.H)
</button>
</td>
<td>
#Html.Raw(item.E)
</td>
</tr>
<tr>
<td id="AA_#(item.Id)" class="accordion-body collapse">
<table>
<tr>
<td>
#Html.Raw(item.D)
</td>
<td>
#Html.Raw(item.B)
</td>
</tr>
</table>
</td>
</tr>
}
</table>
</div>

I researched my problem on SO and found one solution provided by #tmg on here. Many thanks to #tmg. I followed the same in my scenario and it worked for me.
<div class="panel-body">
<table class="table">
#foreach (var item in Model)
{
<tr class="accordion-toggle" data-toggle="collapse" data-target="#AA_#(item.Id)">
<td>
<button class="bb" type="button">
#Html.Raw(item.H)
</button>
</td>
<td>
#Html.Raw(item.E)
</td>
</tr>
<tr>
<td class="hiddenRow">
<div class="accordian-body collapse" id="AA_#(item.Id)">
<table>
<tr>
<td>
#Html.Raw(item.D)
</td>
<td>
#Html.Raw(item.B)
</td>
</tr>
</table>
</div>
</td>
</tr>
}
</table>
</div>
And added JQuery to collapse and toggle table row
$('.table .accordian-body').on('show.bs.collapse', function () {
$(this).closest("table")
.find(".collapse.in")
.not(this)
.collapse('toggle')
})
Added Style for hiddenRow
.hiddenRow {
padding: 0 !important;
}

Related

Table dropdown with bootstrap 5 not working

I am trying to show product items when button order detail is pressed, but its not working in any way I tried, it's possible to make it work with bootstrap 5 or I have to do it with javascript ?
Useless information for "It looks like your post is mostly code; please add some more details." : In the first foreach I am displaying information from the order, then the second foreach is retrieving product id and quantity from a different table that contain order id and the third foreach is getting product where id from the second foreach in order to display product details
<table class="table border">
<thead>
<tr>
<th class="h4" style="width: 18%">Order Number</th>
<th class="h4">Date</th>
<th class="h4">Total</th>
<th class="h4">Status</th>
<th class="h4"></th>
<td></td>
</tr>
</thead>
<tbody>
<tr>
<?php
foreach ($order as $row_order) {
$order_status = intval($row_order->status);
?>
<td class="fw-bold">{{ $row_order->id }}</td>
<td class="fw-bold">{{ $row_order->added_on }}</td>
<td class="fw-bold">{{ $row_order->order_total }} $</td>
<td class="fw-bold"><?php if($order_status == 0){ ?>
Not Paid
<?php }elseif ($order_status == 1) { ?>
Paid
<?php }elseif ($order_status == 2) { ?>
Shipped
<?php }elseif ($order_status == 3) { ?>
Delivered
<?php } ?>
</td>
<td></td>
{{-- <td><a class="btn btn-primary" href="">Order Detail</a></td> --}}
<div class="btn-group">
<td>
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
Order Detail
</button>
</td>
#foreach (\App\Models\Order_product_size_color::where('order_id', '=', $row_order->id)->get() as $order_variant)
#foreach (\App\Models\Product_size_color::where('id', '=', $order_variant->product_size_color_id)->get() as $variant)
<div class="dropdown-menu">
<td class="border-0 p-0 dropdown-item">
<tr>
<td class="border-0"><img class="rounded" src="{{ asset('storage/'. $variant->image1->product_image) }}" alt="" style="width: 80px; height: 90px;"></td>
<td class="fw-bold border-0">{{ $variant->product->product_name }}</td>
<td class="border-0">{{ $order_variant->count }} products</td>
<td class="fw-bold border-0">Size: {{ $variant->size->size_name }}</td>
<td class="fw-bold border-0">Color: {{ $variant->color->color_name }}</td>
<td class="fw-bold border-0">${{ $variant->product->price }}</td>
</tr>
</td>
</div>
#endforeach
#endforeach
</div>
<tr>
<td class="fw-bold">Delivery Address:</td>
<td class="fw-bold">{{ $row_order->address }}</td>
</tr>
</tr>
<?php }//end foreach ?>
</tbody>
</table>

How to implement bootstrap accordion in table in MVC?

I want to implement bootstrap accordion in my application. Currently, If I click on any rows, it gives me first #Html.Raw(item.D) and #Html.Raw(item.B).
What i want is that, if i click on 2nd row then its respective #Html.Raw(item.D) and #Html.Raw(item.B) should displayed and so on.
Please suggest me where I am going wrong.
<div class="panel-body">
<table class="table">
#foreach (var item in Model)
{
<tr class="accordion-toggle" data-toggle="collapse" data-target="#12345-cores">
<td align="left">
#Html.Raw(item.H)
</td>
<td align="right">
#Html.Raw(item.E)
</td>
</tr>
<tr>
<td class="accordion-body collapse" id="12345-cores">
<table>
<tbody>
<tr>
<td>
#Html.Raw(item.D)
</td>
<td></td>
<td>
#Html.Raw(item.B)
</td>
</tr>
</tbody>
</table>
</td>
</tr>
}
</table>
You need to specify id uniquely, to do so you need to append raw id(or something unique for each row) to id and data-target attributes,
<div class="panel-body">
<table class="table">
#foreach (var item in Model)
{
<tr class="accordion-toggle" data-toggle="collapse" data-target="#12345-cores#(item.id)">
<td align="left">
#Html.Raw(item.H)
</td>
<td align="right">
#Html.Raw(item.E)
</td>
</tr>
<tr>
<td class="accordion-body collapse" id="12345-cores#(item.id)">
<table>
<tbody>
<tr>
<td>
#Html.Raw(item.D)
</td>
<td></td>
<td>
#Html.Raw(item.B)
</td>
</tr>
</tbody>
</table>
</td>
</tr>
}
</table>
updated : data-target="#12345-cores#(item.id) & id="12345-cores#(item.id)"

Submit button is submitting the first form in the page

I am trying to make an MVC 5 Razor web page with a table within it, Every row in this table contains a Delete button which is post action:
<table>
<thead>
<tr>
<th>Name</th>
.
.
.
<th>Actions</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model)
{
<tr>
<td>#item.Name</td>
.
.
.
<td>
#using(Html.BeginForm("Delete", "Person", FormMethod.Post))
{
#html.AntiForgetyToken()
#html.Hidden("personId", item.PersonId)
<button type="submit" class="btn">Delete</button>
}
</td>
</tr>
}
</tbody>
</table>
And in the controller:
public class PersonController : BaseController
{
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Delete(int personId)
{
// Do Something...
}
}
Now my problem is when pressing Delete button in any row of the table it always submitting the first form in the page which means the first person in the table is always being deleted no matter what submit button i press.
Any ideas to solve this issue?
Edit:
The generated page html
<div class="page-header">
<h2>Person List</h2>
</div>
<table class="row table table-striped">
<thead>
<tr class="text-primary">
<th class="text-center">#</th>
<th>Name</th>
<th>Email</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">5</td>
<td>Ismail</td>
<td>ismail#example.com</td>
<td>Active</td>
<td>
<form action="/WebApp/Person/Delete?PersonID=5" method="post">
<input name="__RequestVerificationToken" type="hidden" value="Uxhp0Bq1ATAwOXNODHmc74f12O2-dvFhQ5kletbmDkq64CEPWZlXXPKuHDoqSy4DXF6mJhYfGffc_YAn1yERxp69JCUT9IlGTKdfirvVvqE1" />
<div class="text-center">
<div class="btn-group btn-group-xs">
<a class="btn btn-default" href="/WebApp/Person/Details?PersonID=5">View</a>
<a class="btn btn-default" href="/WebApp/Person/Edit?PersonID=5">Edit</a>
<button class="btn btn-danger>Delete</button>
</div>
</div>
</form>
</td>
</tr>
<tr>
<td class="text-center">6</td>
<td>MoHaKa</td>
<td>MoHaKa#example.com</td>
<td>Active</td>
<td>
<form action="/WebApp/Person/Delete?PersonID=6" method="post">
<input name="__RequestVerificationToken" type="hidden" value="R4CUAuVpbGihZvrFxxCjCL_oJ7tgkS_Xxh67i_xCpMXpvZKR5ASUWrSCvjg52yRorF-Ypeau1oZwDi96caHyUj-gmBeHnx7NBgfJBLkLPnQ1" />
<div class="text-center">
<div class="btn-group btn-group-xs">
<a class="btn btn-default" href="/WebApp/Person/Details?PersonID=6">View</a>
<a class="btn btn-default" href="/WebApp/Person/Edit?PersonID=6">Edit</a>
<button class="btn btn-danger>Delete</button>
</div>
</div>
</form>
</td>
</tr>
</tbody>
</table>
Use this instead of your form code:
#using(Html.BeginForm("Delete", "Person", new { item.PersonId }))
{
#Html.AntiForgetyToken()
<button class="btn">Delete</button>
}
ASP.NET MVC default action behavior: primitive types are first looked in query string.
Maybe it's better to use just one form and add a cell like this instead of several forms:
<td onclick="window.location='#Url.Action("Delete", new { PersonID = item.PersonId })'" style="cursor:pointer;">
</td>

Knockout with class scoped properties

I am using Knockout and have the ViewModel bound to my data object in my ASP.Net MVC 4 project quite nicely like so:
$(document).ready(function() {
properties = #Html.Raw(Json.Encode(Model));
selectedProperty = properties[0];
viewModel = { properties: ko.mapping.fromJS(#Html.Raw(Json.Encode(Model))), selectedProperty: ko.observable()};
viewModel.setItem = function(item) {
viewModel.selectedProperty(item);
}
ko.applyBindings(viewModel);
Now I want to refactor my JavaScript so that the logic is encapsulated inside a class:
RealEstate.Search = function (properties) {
this.properties = properties;
this.selectedProperty = this.properties[0];
this.viewModel = { properties: ko.mapping.fromJS(this.properties), selectedProperty: ko.observable()};
this.viewModel.setItem = function(item) {
viewModel.selectedProperty(item);
}
ko.applyBindings(this.viewModel);
}
And I am instantiating that object in my HTML page like so:
$(document).ready(function() {
search = new RealEstate.Search(#Html.Raw(Json.Encode(Model)));
}
Now, I am getting the following error:
Error: Unable to parse bindings.
Message: ReferenceError: 'properties' is undefined;
Bindings value: foreach: properties
Here is the snipped HTML for the table bound to the ViewModel:
<div id="divDataTable" data-bind="with: properties">
<table id="dataTable" class="tablesorter">
<thead>
<tr>
<th>Address
</th>
<th>
Suburb
</th>
<th>Price
</th>
<th>Beds
</th>
<th>Baths
</th>
<th>Days Listed
</th>
</tr>
</thead>
<tbody data-bind="foreach: properties">
<tr data-bind="click: $root.setItem">
<td>
<label data-bind="text: $data.Street"></label>
<input data-bind="attr: { value : $index(), id : $index(), name : $index() }" type="hidden" />
</td>
<td data-bind="text: $data.Suburb"></td>
<td data-bind="text: $data.PriceFormatted"></td>
<td data-bind="text: $data.NumOfBedrooms"></td>
<td data-bind="text: $data.NumOfBathrooms"></td>
<td data-bind="text: $data.DaysListed"></td>
</tr>
</tbody>
</table>
</div>
</section>
<div id="divProperty">
<aside class="float-right" data-bind="with: selectedProperty">
<table>
<tr>
<td>
<label data-bind="text: $data.Street"></label>
</td>
<td>
<label data-bind="text: $data.PriceFormatted"></label>
</td>
</tr>
<tr>
<td colspan="2">
<img src="#" /></td>
</tr>
<tr>
<td>Beds:
<label data-bind="text: $data.NumOfBedrooms"></label>
</td>
<td>On OZMite:
<label data-bind="text: $data.DaysListed"></label>
</td>
</tr>
<tr>
<td>Baths:
<label data-bind="text: $data.NumOfBathrooms"></label>
</td>
<td>Year built:</td>
</tr>
</table>
</aside>
I would appreciate it if someone could shed some light on what I am doing wrong.
With the data-bind="with: properties" you are already "in the context" of the properties property inside your div.
So when you write <tbody data-bind="foreach: properties"> KO tries to find the properties property inside your properties array.
What you need is to use to reference the current binding context with the $data.
So your foreach should look like this:
<tbody data-bind="foreach: $data">
...
</todby>

Elements above JQuery accordion losing padding

I have a jquery dialog that contains a jquery accordion among other things. When I click the accordion headings to expand the different sections, the elements above the accordion lose their padding for the duration of the animation. The result is that these elements shift to the left for the duration of the animation. Below are the HTML/JS snippets in question.
Any thoughts?
HTML:
<div id="bodyDiv">
<!-- Dialog -->
<div id="patientPopup" title="Patient:" class="ui-widget">
<table style="width: 100%">
<tr>
<td class="AppointmentImage">
<img src="images/John-Petrucci-tn.jpg" alt="Patient Photo">
</td>
<td>
<b>Name:</b> Smith, Sally <b>DOB:</b> 02/15/1984 <br />
<b>SSN:</b> 999-99-9999 <b>Address:</b> 123 Main St Nashville, TN 37204
</td>
</tr>
<tr>
<td colspan="2" style="width: 100%">
<!--Accordion-->
<div id="patientSummary">
<h3>Encounters</h3>
<div>
<table class="PatientSummary">
<tr>
<th>12/03/2011</th>
<td>
Office visit - this is text for the office visit. some notes perhaps.
</td>
</tr>
<tr>
<th>10/16/2011</th>
<td>
GYN visit - this is text to fill some space.
</td>
</tr>
</table>
</div>
<h3>Alerts</h3>
<div>
<ul>
<li>Diabetic</li>
<li>Due for FluShot</li>
</ul>
</div>
<h3>Labs/Radiology</h3>
<div>
<table style="vertical-align: text-top;">
<tr>
<th>Date</th>
<th>Lab</th>
<th>Result</th>
</tr>
<tr>
<td>12/03/2011</td>
<td>Blood Panel</td>
<td>N</td>
</tr>
<tr>
<td>12/03/2011</td>
<td>Pregnancy Test</td>
<td>Y</td>
</tr>
<tr>
<td>12/03/2011</td>
<td>Blood Panel</td>
<td>N</td>
</tr>
<tr>
<td>12/03/2011</td>
<td>Pregnancy Test</td>
<td>Y</td>
</tr>
<tr>
<td>12/03/2011</td>
<td>Blood Panel</td>
<td>N</td>
</tr>
<tr>
<td>12/03/2011</td>
<td>Pregnancy Test</td>
<td>Y</td>
</tr>
</table>
</div>
</div>
</td>
</tr>
</table>
</div>
<button id="showPatient">Show Patient</button>
</div>
JavaScript:
$("#patientPopup").dialog({
autoOpen: false,
modal: true,
height: 530,
width: 600,
draggable: false,
resizable: false,
open: function () {
$("#patientSummary").accordion({
fillSpace: true,
autoHeight: true
});
}
});
$("#showPatient").button().click(
function () {
$("#patientPopup").dialog("open");
}
);
Any help would be appreciated. Thanks!
The solution was quite simple. I ended up putting the image and text in a completely separate table than the accordion.
Never determined exactly why the top elements were losing their padding though...

Resources