I know this is a common question, and I've read many of the solutions to it. However, none of them (as far as how I've interpreted and tested them) have worked quite right yet.
The use case, which seems like would be pretty common, is to allow the user to select one or multiple rows in the table, and then perform one of the actions in the dropdown list. So the Action method in the Controller needs to both receive the form as well as know what action to execute.
I have been able to get multiple buttons to work ("work" meaning submit a form and distinguish between which link/button was used to submit the form), and style them to look like links, but with the solutions I've tried, I haven't been able to retain the look of the dropdown list styling, so dropdowns where I need to do this would have a slightly inconsistent look compared to the default dropdowns that I can use regular href links with Action calls via #Html.ActionLink.
This is how I need the dropdown to look (default bootstrap styling with Href links):
Here is the markup where this dropdown lives:
<div class="col-sm-4 m-b-md" >
<h4 class="dashhead-subtitle">Project Members</h4>
#using (Html.BeginForm("EditProjectMembers", "Project", FormMethod.Post, new { name = "formEditMembers", id = "formEditMembers" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(item => item.ProjectModelId)
#Html.HiddenFor(item => item.CompanyModelId)
<div class="btn-toolbar-item">
<div class="btn-group">
<button class="btn btn-primary-outline">
Actions
</button>
<button data-toggle="dropdown" class="btn btn-primary-outline dropdown-toggle ">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>
Do Action 1 <!--REFERRING TO HERE-->
</li>
<li>
Do Action 2<!--AND HERE-->
</li>
</ul>
<div class="btn-toolbar-item input-with-icon">
<input type="text" class="search form-control" placeholder="Search..." />
</div>
</div>
</div>
<p></p>
<table class="table table-hover table-condensed table-responsive" data-height="5000" >
<tr>
<th>
Name
</th>
<th>
Company
</th>
<th>
Selected
</th>
</tr>
<tbody class="list">
#for (int i = 0; i < Model.ProjectMembers.Count(); i++)
{
<tr>
<td class="username">
#Html.DisplayFor(item => item.ProjectMembers[i].FirstLastName)
#Html.HiddenFor(item => item.ProjectMembers[i].CompanyName)
</td>
<td class="companyname">
#Html.DisplayFor(item => item.ProjectMembers[i].CompanyName)
#Html.HiddenFor(item => item.ProjectMembers[i].CompanyName)
</td>
<td>
#Html.CheckBoxFor(item => item.UserSelected, new { #class = "big-checkbox" })
#Html.HiddenFor(item => item.ProjectMembers[i].Id)
</td>
</tr>
}
</tbody>
</table>
}
</div>
#stephen.vakil , thanks for your suggestion, it appears to be working. Here's what I did.
The hidden element and dropdown menu snippet from above:
Hidden element:
#Html.HiddenFor(item => item.FlagFormEditMembers)
And the markup using href's to call the javascript
<ul class="dropdown-menu">
<li>
Add a New Project Member
</li>
<li>
Remove Selected Project Members
</li>
</ul>
And the function that submits the form, as well as sets the value of the hidden element that you suggested adding:
<script>
function submitFormNewMember() {
$("#FlagformEditMembers").attr({
"value": "AddNewMember"
});
$('#formEditMembers').submit();
}
function submitFormRemoveMember() {
$("#FlagformEditMembers").attr({
"value": "RemoveMembers"
});
$('#formEditMembers').submit();
}
</script>
Thanks!!!
Related
I'm stuck with my project, please help...
This is the situation: In my project I have to assign a teacher to give permission to grade students, because a group can have 2 or more teachers, but only one has to have permission to grade, so... I added a column in my table 'teachers' in the database with the name 'grade' of type boolean. And in my view I added a checkbox... How do I change the value of a checkbox without using any form or button to trigger the action and activate the checkbox in the teacher who is going to have permission to grade? And this value should also be updated in the database.
This is my view...
<!--teachers-->
<table class=" table table-sm table-striped table-bordered ">
<thead class="text-white bg-primary">
<tr>
<th>#lang('show.Identifier')</th>
<th>#lang('show.email')</th>
<th>#lang('show.grade')</th>
<th>#lang('show.delete')</th>
</tr>
</thead>
<tbody class="small text-center">
#foreach ($group->teachers as $teacher)
<tr>
<td >{{$teacher->Identifier}} </td>
<td >{{$teacher->email}} </td>
<td>
<input id="active" {{$teacher->grade == 1 ?'checked':''}} type="checkbox" name="grade" value="1">
</td>
<td>
<form method="post" action="{{url('Groups/Disenroll/'.$group->idGroup.'?idTeacher='.$teacher->idTeacher)}}">
{{csrf_field()}}
<button type="submit" class="btn btn-sm btn-outline-danger" > <i class="material-icons small" >call_split</i></button>
</form>
</td>
</tr>
#endforeach
</tbody>
</table>
And this is an image of the table, if it helps...
I think you can use something like JQuery for this.
You can firstly add a class of toggle-class to your checkbox
<input class="active toggle-class" {{$teacher->grade == 1 ?'checked':''}} type="checkbox" name="grade">
And secondly, make sure that you have a way to keep track of who's doing the grades.
Add data-id="{{ $teacher->Identifier}}" on your checkbox
<input data-id="{{ $teacher->Identifier}}" class="active toggle-class" {{$teacher->grade == 1 ?'checked':''}} type="checkbox" name="grade">
In your web.php add a new route
Route::get('/path/to/updateGrader/status', [App\Http\Controllers\MyController::class, 'updateGraderStatus']);
Add the below code to where your checkbox is located
$('.toggle-class').on('change',function(){
let status = $(this).prop('checked') == true ? true : false;
let grader_id = $(this).data('id');
$.ajax({
type:'GET',
dataType:'json',
url:'/path/to/updateGrader/status', // add your earlier created route here
data:{'grade': status, 'grader_id': grader_id},
success: function(data){
console.log('success');
}
});
});
In your Controller, MyController in our case create a new function
public function updateGraderStatus(Request $request)
{
$grader = MyModel::find($request->grader_id);
$grader->grade = $request->grade;
$grader->save();
}
Please let me know if this helps you. I didn't test it out but I think this is how you would go about it.
I have a hidden table, that is being filled by a controller action returning a model. I have been trying to use the same method I have previously to un-hide the table (via JS toggle) however, once the button is clicked, table becomes visible for a brief second, but as soon as the controller action returns the model, the table is hidden again. Below is my code:
HTML:
form with btn
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "submitForm"}))
{
<div class="row">
#*<input type="text" name="CasinoID" placeholder="Enter Casino ID" id="cIdSearch" />*#
<div>
Casino: #Html.DropDownList("CasinoID", Model.TerminalReceiptPostData.CasinoIdDDL, "Select Casino", new { id = "cIdSearch", #class = "custom-class-for-dropdown card" })
</div>
<div>
Date: <input id="datepicker" class="datepicker-base card" name="Date" placeholder="MM/DD/YYY" type="text"/>
</div>
<div>
<button type="submit" class="btn btn-sm btn-primary" id="search" onclick="toggleTable()"> Search Transactions</button>
</div>
</div>
}
hidden table:
<hr />
<div class="row hidden" id="ReceiptsMainDiv">
<div class="col-md-12" style="overflow-y:scroll">
<table class="table table-striped table-hover table-bordered" id="terminalReceipts">
<thead>
<tr>
<th>Terminal ID</th>
<th>Local Transaction Time</th>
<th>Amount</th>
<th>Receipt</th>
<td class="hidden"></td>
</tr>
</thead>
<tbody>
#foreach (var item in Model.TransactionsTests)
{
<tr id="#String.Concat("rowIndex", Model.TransactionsTests.IndexOf(item))">
<td>#item.TerminalID</td>
<td>#item.TransactionTime</td>
<td>#item.Amount</td>
#*<td>#Html.ActionLink("View Receipt", "ViewReceipt", new { id = item.Id }, new { #class = "btn btn-primary btn-sm" }) <br /></td>*#
<td class="transactionID hidden">#item.Id</td>
<td>
#if (item.ReceiptData == null)
{
<button class="btn btn-sm btn-primary viewReceipt" disabled>View Receipt</button>
}
else
{
<button class="btn btn-sm btn-primary viewReceipt" data-rowindex="#String.Concat("rowIndex", Model.TransactionsTests.IndexOf(item))">View Receipt</button>
}
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
Controller Action:
[HttpPost]
public ActionResult Index(string CasinoID, DateTime Date)
{
//var id = Int32.Parse(Request.Form["CasinoID"].ToString());
var Cid = Request.Form["CasinoID"];
Cid = GetNumbers(Cid);
var id = Int32.Parse(Cid);
var model = TRBL.GetTransactionTestsData(id, Date);
model.TerminalReceiptPostData = TRBL.GetCasinosDDL();
return View(model);
}
JS:
function toggleTable() {
$("#ReceiptsMainDiv").toggle();
}
What's a better way to get around this?? Thank you!
The Problem
It looks like what is happening is, you are hiding the div container for the table by default, and you are attempting to show the table when the "Search Transactions" button is clicked.
The problem is clicking that button, since it is your form's "submit" button, will refresh the page. This would mean your toggle code won't be called after the page refreshes. (It will be called before the page refreshes, which is why you briefly see the result).
Assuming that you are looking to hide the table unless there is something in it (e.g., hide table only when there is no data loaded), then you have a couple of options, one of which I will suggest below.
Suggested Solution
Remove your "onClick" from the submit/"Search Transactions" button
Remove your function that onClick calls
Place javascript that activates when the page is loaded
Toggle the div (
$("#ReceiptsMainDiv").toggle(); ) to "unhide" it only if data exists within the table, within the document load javascript function.
Since I don't have the model class I wouldn't be able to tell you how you would determine whether or not there is data, but:
If the model is a single set of values (say, a single "transaction"), then you probably have an Id field
Look for that Id field to be something other than its default value. If it is an int, checking for Id > 0 should be sufficient.
If the model is a collection of "transactions", look for the Count > 0 on the collection itself.
Hope this helps!
I have an inventory page that also contains a password field.
I would like to hide the password when the page is loaded, best would be to have points displayed **** and after click password is shown or a pop up.
JS
var get_cert = function () {
$http.get($scope.url.cert_list).then(
function (response) {
$scope.certs = response.data;
}
);
}
// execute get function
get_cert();
HTML
<div class="panel panel-default">
<table class="table table-striped valign_middle">
<tr class="table_header">
<td>Name</td>
<td>Pass</td>
</tr>
<tr ng-repeat="cert in certs | filter:search | orderBy:['name']">
<td>{{cert.name}}</td>
<td>
<button class="w3-btn w3-black w3-hover-green w3-ripple" ng-click="get_cert()">Show</button>
<span ng-show="get_cert()">{{cert.password}}</span>
</td>
</tr>
</table>
<button ng-show="!cert.showPw" class="w3-btn w3-black w3-hover-green w3-ripple" ng-click="cert.showPw = true">Show</button>
<span ng-show="cert.showPw">{{cert.password}}</span>
You can use ng-click to do cert.showPw = true, which will append a property called showPw (a boolean) to the object. Combined with ng-show, you can easily switch between the two.
This way you'll keep your controller free of any additional logic needed. You may include ng-click on the span which holds the password which will set showPw = false to switch it back to a button.
See my JSFiddle for full example.
Create a input
<input type="password" name="???">
Then you can change its type to "text" with
$("#idOfInout")type = 'text';
I have a dropdown menu/textbox which is used for when users are typing in something to save. Also, if it is saved it will load on the page here as well.
<tbody data-ng-repeat="(wholesalerIndex,wholesaler) in wholesalers" >
<tr >
<td >
<label class="control-label">{{wholesaler.ORDER}}</label>
</td>
<td class="col-md-3">
<div>
<input type="text" class="form-control dropdown-toggle" data-toggle="dropdown" data-ng-disabled="formReadOnly" data-ng-model="wholesaler.WHSLE_NAME" data-ng-keyup="comboWholesalerBoxOptions(wholesaler.WHSLE_NAME, 'wholeSalerNameOptions')" />
<ul>
<li data-ng-repeat="wholeSalerOption in wholeSalerNameOptions | unique: 'NAME'" style="width:100%"><a data-ng-click="changeWholesalerData(wholeSalerOption, wholesaler)">{{wholeSalerOption.NAME}}</a></li>
</ul>
</div>
</td>
<td >
<button data-ng-click="upWholesaler(wholesaler)">Up</button>
<button data-ng-click="downWholesaler(wholesaler)">Down</button>
</td>
</tr>
</tbody>
There is an order of these rows being created below and it can be moved up or down. {{wholesaler.ORDER}} is the current order of the row. I want the input dropdown to be populated with {{wholesaler.NAME}} when a button is pressed.
I can't figure out how to get it to populate. Putting it next to {{wholeSalerOption.NAME}} just makes the name add onto the end of the dropdown search results. value="wholeSalerOption.NAME" also doesn't do anything.
How do I get this field to update like other ones without interfering with its ability to do it's search?
I've got a weird bug going on in my App and hope someone might know a solution.
My Problem: I've a movie table with different rows, I use the jquery tablesorter plugin from Mottie to sort my items and filter them. Each row also has it's own Edit button, where when you click on it the the td's get editable, now the problem is that when I edit lets say the movie title, then click on the movie director to change his name, the whole row jumps down and it does that all the time until the row is at the bottom. When I remove the tablesorter function everything works correctly, but when it's active, it does this weird bug. Now I tried to just disable the tablesorter on click (following this solution), but that also didn't help me. The sorting and the filter got disabled, but it still pushed my whole row down. Here's a gif to visualize the problem:
Note: The movie title, date, director and runtime are all < p > and < input > tags, on click on the edit button the < p > tags get hidden and the < input >'s get visible. I used this method because I need to give my new data to my django model somehow, maybe thats part of the problem.
Also I have a hidden row, that shows up when I click on the Description, don't know if thats important as well.
I'd like to provide a jsfiddle, but I didn't manage to reproduce this bug in jsfiddle, it only appears in my app :/
Here's the important code of the app:
HTML
<table id="movieTable" class="table-hover tablesorter">
<thead class="table-head">
<tr>
<th data-sorter="false"></th>
<th>TITLE</th>
<th class="gen">GENRE</th>
<th>RELEASE DATE</th>
<th>DIRECTOR</th>
<th>DESCRIPTION</th>
<th>RUNTIME</th>
<th>STATUS</th>
<th>IMDB</th>
<th data-sorter="false" id="buttons-head-bottom"></th>
</tr>
</thead>
<tbody>
<td>
<a href=“/myapp/evil-dead/">
<input class="input-title hide" value="Evil Dead" form="movie1" name="title"/> <!— hidden on default —>
<p class="movie-title">Evil Dead</p>
</a>
</td>
<td>
<select class="hide input-genre-select" form="movie1" name="genre"> <!— hidden on default —>
<!— options code —>
</select>
<p class="movie-genre">Horror</p>
</td>
<td>
<input class="hide input-release" value="25.04.2013" form="movie1" name="date" size="10"/> <!— hidden on default —>
<p class="movie-release">25.04.2013</p>
</td>
<td>
<input class="hide input-director" value="Fede Alvarez" form="movie1" name="director"/> <!— hidden on default —>
<p class="movie-director">Fede Alvarez</p>
</td>
<td class="desc-pointer toggle" data-toggle="collapse" data-target=".description1"> <!— collapse and shows a hidden table row when clicked —>
Description <i class="fa fa-caret-right"></i>
</td>
<td>
<input class="hide input-runtime" value="91" form="movie1" name="runtime" maxlength="4" size="4"/> <!— hidden on default —>
<p class="movie-runtime">91 min</p>
</td>
<td>
<select class="hide input-status-select" form="movie1" name="status"> <!— hidden on default —>
<!— options code —>
</select>
<p class="movie-status">Bought and watched</p>
</td>
<td>6,5</td>
<td>
<!— edit button, is hidden when clicked on it —>
<button type="button" class="edit-btn">
<i class="fa fa-pencil-square"></i>
</button>
<!— hidden on default, shows up when clicked on edit-btn —>
<button type="submit" form="movie1" class="save-btn">
<i class="save-btn fa fa-save"></i>
</button>
<!-- delete button -->
<button id="del-btn1" type="button" class="delete-btn btn btn-default" data-toggle="modal" data-target="#deleteModal1">
<i class="fa fa-remove"></i>
</button>
</td>
</tbody>
</table>
I only provided one table row here, but every other row is build the same.
Javascript
// table sorter
$(function(){
const $table = $("#movieTable").tablesorter({
dateFormat: "ddmmyyyy",
headers: {
2: { sorter: "select" },
3: { sorter: "shortDate" },
7: { sorter: "select" },
},
widgets: ["filter"],
widgetOptions : {
filter_columnFilters: false,
}
});
$.tablesorter.filter.bindSearch( $table, $('.search') );
});
// edit button
$(".edit-btn").click(function() {
$('table')
.unbind('appendCache applyWidgetId applyWidgets sorton update updateCell')
.removeClass('tablesorter')
.find('thead th')
.unbind('click mousedown')
.removeClass('header headerSortDown headerSortUp');
const parent = $(this).parent().parent()
parent.find(".input-director, .input-runtime, .input-release, .input-title").addClass("highlight");
parent.find(".movie-title, .movie-genre, .movie-release, .movie-director, .movie-runtime, .movie-status").addClass("hide");
parent.find(".input-title, .input-genre-select, .input-release, .input-director, .input-runtime, .input-status-select").removeClass("hide");
parent.find(".edit-btn").hide();
parent.find(".save-btn").show();
$(".gen").addClass("genre-padding");
$(".title-link").bind("click", function(e) {
e.preventDefault();
})
})
If needed I can provide more code, but I hope this is enough for someone to find a solution to this bug. Like I said before, the only solution I had found was to remove the tablesorter plugin, disabling it didn't help.
Thanks to anyone who is trying!
It's not a bug, it's a feature! :D
Internally the plugin is set up to automatically resort when an update is triggered; although, I don't see it being used in the code that was shared. To get around this "feature", set the resort option to false.