I have checkbox. When I select the checkbox I want it to automatically change its value in the Database to true and refresh the view and invoke a JQuery method.
I also have a checkbox and label. I want the checkbox to disappear when selected and the text in the label to change.
<h2>Tasks</h2>
<fieldset>
<legend>Tasks</legend>
<table class="table">
#foreach(var item in ViewBag.x)
{
<tr class="clr">
<td style="width:520px">
#item.User.UserName
</td>
<td>
#item.date.ToString("MM/dd/yyyy")
</td>
</tr>
<tr class="clr">
<td>
#item.Discription
</td>
<td></td>
</tr>
<tr>
<td ></td>
<td>
<div><input type="checkbox" id="ch" class="ch" /><span id="d" >Done</span></div>
</td>
</tr>
}
How would I do this in JQuery or ASP MVC?
Image example
You can listen to the change event on the check box and then make an ajax call to your server to make updates to your db and have your action method return a response. You can check this response and hide/show whatever you want.
You probably want to associate the user id with the checkbox because you need to make this update against a specific user.. You may keep the user id in html 5 data attributes in the check box. Also looks like you are hard coding the id value of checkbox and the span in the loop, which will produce the same value for multiple checkboxes. Id values should be unique. So let's remove the id property value from your markup since we are not using it now.
<div>
<input type="checkbox" data-user="#item.UserId" class="ch" />
<span class="msg">Done</span>
</div>
And your javascript code will be
$(function(){
$("input.ch").change(function(e){
var _this=$(this);
var userId=_this.data("user");
var isChecked=_this.prop("checked");
$.post("#Url.Action("Change","Home")", { isChecked :isChecked, userId:userId },
function(re){
if(re.status==="success")
{
_this.closest("div").find("span.msg").html(re.message); //update span content
_this.remove(); // remove checkbox
}
else
{
alert("Failed to update!");
}
});
});
});
I am using Url.Action helper method to generate the relative url to the action method. This code will work if you include your script inside the razor view, but if your javascript code is in an external js file, you should build the path to the app root and pass that to your external js files via some variables as explained in this answer.
Assuming you have a Change action method in your HomeController which accepts the isChecked value
[HttpPost]
public ActionResult Change(int userId, bool isChecked)
{
try
{
// to do: using userId and isChecked param value, update your db
return Json( new { status="success", message="done"});
}
catch(Exception ex)
{
//to do : Log ex
return Json( new { status="error", message="Error updating!"});
}
}
Related
I'm currently building a form and the data within it is build from a PHP Foreach loop
I'm using Javascript so that I can make the action of checking/unchecking a checkbox will make an ajax call.
The issue right now (using class names) is that when I click the checkbox and console log the data, each checkbox does trigger properly but it only console logs the first table row's data
So if my php loop builds 5 rows, each with their own values and their own checkboxes, each checkbox triggers the log but they each log only the first set of values.
What am I doing wrong here?
$(".addToLineup").click(function (e) {
var number = document.getElementsByClassName("number")[0].innerHTML;
var detail = document.getElementsByClassName("detail")[0].innerHTML;
var category = document.getElementsByClassName("category")[0].innerHTML;
updatedata.number = number;
updatedata.detail = detail;
updatedata.category = category;
console.log(updatedata);
)};
<form id="saveLineup">
#foreach($lists as $list)
<tr style="text-align:center;">
<td class="number">{{$list['GROUP']}}</td>
<td class="detail">{{$list['COVER']}}</td>
<td class="category">{{$list['CATEGORY']}}</td>
<td><input class="addToLineup" type="checkbox" <?php if ($list['LINE_UP'] == 1) echo "checked='checked'"; ?></td>
</tr>
#endforeach
</form>
I have an table created using ng-repeat and there hundreds of rows, up to 600 or 700. Each row includes a checkbox and I have a "Check All" box at the top to check all the boxes in one go. However I'm running into browser performance issues, IE11 (the clients preferred choice) in particular becomes unresponsive. After several minutes all the checkboxes appear checked but you still can't scroll or do anything so it is effectively useless.
I have created a controller array and when the checkAll box is clicked it loops through the model (the one used in ng-repeat) and adds a value to the array. I presume it's this looping through the array that is causing the slow-down but I'm not sure. Pagination has been ruled out, they want all the rows on one page.
<table>
<tbody>
<tr>
<th>Table Header</th>
<th><input type="checkbox" id="checkAllCheckBox" ng-model="vm.allChecked" ng-change="vm.tickOrUntickAllCheckBoxes()" />
</tr>
<tr ng-repeat="payment in vm.payments>
<td>{{ payment.somePaymentValue }}</td>
<td>
<input type="checkbox" class="paymentsApprovalCheckbox"
ng-checked="vm.approvedPayments.indexOf(payment.payId) > - 1"
ng-value="payment.payId" ng-model="payment.approved"
ng-click="vm.handleCheckBoxClick(payment.payId)" />
</td>
</tr>
</tbody>
</table>
Here is the angular function that checks/unchecks all
vm.tickOrUntickAllCheckBoxes = function(){
if (vm.allChecked == false) {
vm.approvedPayments = [];
} else {
vm.payments.forEach(function(payment){
vm.approvedPayments.push(payment.payId);
});
}
};
Swapping out the angular vm.tickOrUntickAllCheckBoxes() function for a plain old javascript option makes the checkAll box work almost instantaneously in IE11 however I lose access to the checked payment.payId values. I wonder is there away for angular to get them? Here is the plain javascript checkAll() function:
<script>
function checkAll(x) {
var checkBoxes = document.getElementsByClassName('paymentsApprovalCheckbox');
for (var i = 0; i < checkBoxes.length ; i++) {
checkBoxes[i].checked = (x.checked == true);
}
}
</script>
Then I update the checkAll checkbox like this:
<input type="checkbox" id="checkAllCheckBox" ng-model="vm.allChecked" onclick="checkAll(this)" />
If you check one checkbox individually then the ng-model="payment.approved" in the repeating checkboxes is updated but this does not happen if they are checked with the checkAll function. Is it possible for angular to detect the boxes checked with checkAll()? I guess this is just putting off the same old inevitable slow-down to a slightly later point in the process.
Anyone have any ideas or work-arounds? Thanks!
I would use the ng-model to the best of its abilities. In your controller:
$onInit() {
// If you need this from a REST call to populate, you'll have to
// remember to do that here;
this.model = {
all: true,
items: {}
};
}
In your loop:
<tr>
<th>Table Header</th>
<th>
<input type="checkbox"
id="checkAllCheckBox"
ng-model="vm.model.all"
ng-change="vm.tickOrUntickAllCheckBoxes()" />
</tr>
<tr ng-repeat="payment in vm.payments track by $index">
<td ng-bind="payment.somePaymentValue"></td>
<td>
<input type="checkbox"
class="paymentsApprovalCheckbox"
ng-change="vm.approvedPayments($index)"
ng-model="vm.model.items[$index]" />
</td>
</tr>
Then in your controller:
tickOrUntickAllCheckBoxes() {
const boxes = this.model.items.length;
this.model.all = !this.model.all;
// Several ways to do this, forEach, map, etc.,
this.model.items.forEach((item) => { item.checked = !this.model.all });
}
And for setting it individually:
approvedPayments(idx) {
// Sets all the item's boxes checked, or unchecked;
this.model.items[idx].checked = !this.model.items[idx].checked;
// Possible call to extended model to get payment info;
handleCheckBoxClick(idx);
}
You should be able to put all the payment information into the one approvedPayments() method rather than have two separate methods (move logic out of template and into the controller or a service). I.e., your model could look like:
this.model.items = [
// One 'option' with id, payment etc;
{
id: 73,
paymentId: 73,
somePaymentValue: 210.73,
currencyType: 'GBP',
checked: false
},
{
// Another 'option' etc...
}
]
One issue to note is the incompatibility of ngChecked with ngModel, had to look it up (which is why I haven't used ng-checked in the above).
Thank to everyone for the suggestions. The solution I came up with was to push some of the work back to the server side. Instead of just loading the payments model (in which each payment record contains a lot of info) i am now loading two additional models when the page loads, one of which is a set of key/value pairs where the keys are payId and the values are all false and another one with the same keys and all values are true. Example:
{
"1": false,
"2": false
}
These are used for the checkAll/Uncheck all - just set the vm.approvedIDs variable to the true or false one. Then, the vm.approvedIDs variable is used as the model in the ng-repeat checkbox.
I have to do a bit of extra work on the server side when the user sends the approvedIDs back to the server to get only the key/id of the 'true' entries. Here are the relevant angular controller functions:
$onInit() {
// call http to get 'data' from server
vm.payments = data.payments;
vm.paymentIDsFalse = vm.approvedIDs = data.paymentIDsFalse;
vm.paymentIDsTrue = data.paymentIDsTrue;
};
// tick/untick all boxes
vm.tickOrUntickAllCheckBoxes = function(){
if (vm.allChecked == false) {
vm.approvedPayments = vm.paymentIDsFalse;
} else {
vm.approvedPayments = vm.paymentIDsTrue;
}
};
// tick/untick one box
vm.handleCheckBoxClick = function(payId, currentValue){
vm.approvedPayments[payId] = currentValue;
};
vm.submitApprovedIds = function(){
// post vm.approvedPayments to server
};
HTML:
<table>
<tbody>
<tr>
<th>Table Header</th>
<th><input type="checkbox" id="checkAllCheckBox" ng-model="vm.allChecked" ng-change="vm.tickOrUntickAllCheckBoxes()" />
</tr>
<tr ng-repeat="payment in vm.payments>
<td>{{ payment.somePaymentValue }}</td>
<td>
<input type="checkbox" class="paymentsApprovalCheckbox"
ng-value="payment.payId"
ng-model="vm.approvedPayments[payment.payId]"
ng-click="vm.handleCheckBoxClick(payment.payId, vm.approvedPayments[payment.payId])" />
</td>
</tr>
</tbody>
</table>
It looks to me as if there must be a better way than creating these additional models but it is working pretty smoothly for now and I can move on to the next thing!
I have the following table inside my asp.net mvc view:-
#foreach (var item in Model) {
<tr id="#item.TMSServerID">
<td>
#Html.ActionLink("Edit", "Edit","Server", new { id=item.TMSServerID },null) |
#if (!item.IsAlreadyAssigned()){
#Ajax.ActionLink("Delete",
"Delete", "Server",
new { id = item.TMSServerID },
new AjaxOptions
{ Confirm = "Are You sure You want to delete (" + item.Technology.Tag.ToString() + ")",
HttpMethod = "Post",
OnSuccess = "deletionconfirmation",
OnFailure = "deletionerror"
})}
</td>
<td>
#Html.ActionLink(item.Technology.Tag,"Details","Server",new { id = item.TMSServerID},null)
</td>
<td class="hidden-phone" >
#item.status
</td>
The table allow edit,delete single item at a time. But now I want to do the following:-
Add a checkbox beside each row.
Add a Ajax delete button to delete selected items
Add a Transfer ajax button, which allow editing the selected items status.
So I am trying to achieve the following:-
How can I pass the item id + item timestamp field , using ajax button , as I need to check if the selected items has been modified by another user?
How I can remove the selected row from the html table incase the delete operation successed ?
Thanks
add a check box on each first cell of the table with ModelID as the value of each checkbox.
inside your foreach, include this:
<td>
<input type="checkbox" name="TMSServerID" value="1" />
</td>
add this into tha parameter of your controller: Int32[] idList, something like this:
public void CheckForIds(Int32[] idList)
{
//Manipulate idList
}
and in your button event, call the controller method.
You might want to take a look at this for your reference:
http://byatool.com/mvc/asp-net-mvc-how-to-handle-multiple-checkboxes-with-viewsactions-jquery-too/
I am trying to create a prepopulated form that pulls values from any selected row in a HTML table . The HTML page is populated by a JSP .
my table looks like this
<table id="data-table" id="test">
<thead>
<tr>
<th>value1</th>
<th>value2</th>
<th>value3</th>
<th>value4</th>
</tr>
</thead>
<tbody>
<tr>
<td id="class1"><%= value.valueOne() %></td>
<td id="class2"><%= value.valueTwo() %></td>
<td id="class3"><%= value.valueThree() %></td>
<td id="class4"><%= value.valueFour() %></td>
</tr>
<%
}
%>
</tbody>
</table>
I want to obtain a prepopulated form with the row values on click of a particular row . I have some js code that does this .
$(document).on("click", ".data-table .class1", function(e) {
var value = $(this).closest('tr').val();
console.log(value);
// Just to check if I get the correct value
});
unfortunately I cannot understand how to get the values for that particular row from the DOM and populate it in a form , That I want to overlay over the table . I would appreciate any pointers . I really would have written more code but I dnt know Jquery and am stuck
Your general strategy should be this:
Populate the table on the server side: done
Have the form pre-existing in the page, but hidden with css (display:none)
Register a click listener on all tr elements to:
find the values inside each td within the tr
select the corresponding form inputs
populate the inputs using jQuery's val(value) function.
unhide the form if it's hidden
With this in mind, I would change your click listener from document to something like this. (Note: I'm assuming value.valueOne() are just numbers or strings, and don't contain any html.
//target just TR elements
$('tr').click(function(){
values = [];
$(this).children().each(function(){
//add contents to the value array.
values.push($(this).html())
});
//fill in the form values
populateForm(values);
});
Populate form would completely depend on your form's HTML, but to get you started here's an idea of what it might look like:
function populateForm(values){
//set the value of the input with id of name to the value in the first td.
$('#name').val(values[0]);
//show the form (id inputForm) now that it's populated
$('#inputForm').show();
}
A couple things are wrong with your html markup and your JQuery selector. You'll never be able to execute the code you've provided...
You have two 'id' parameters in this element, <table id="data-table" id="test">... This will work with the JQuery I've fixed below, but it's malformed html either way.
In your selector, you are using the syntax for finding an element based on it's css class attribute, however your elements in your HTML have those values set as 'id' attributes. Thus, this, $(document).on("click", ".data-table .class1", function(e) {... should be written as follows, $(document).on("click", "#data-table #class1", function(e) {
Now, if you are attempting to get the values within all of the 'td' elements within a row, then all you really need to do is get the parent element of the 'td' that was clicked, and then get it's children. Then, for each child, get their values.
Like this...
$(document).on("click", "#data-table #class1", function(e) {
var elements = $(this).parent().children();
$.each(elements, function(index, el){
alert($(el).html());
});
});
I've saved a JSFiddle for you to see this in action... http://jsfiddle.net/2LjQM/
val() is used to return value of form inputs. You are using it to try to get the value of a row and row has no value.
Without seeing what your output into the TD as html, I assume it is a form control
Try
$(document).on("click", ".data-table .class1", function(e) {
var value = $(this).find(':input').val(); // `:input pseudo selector wull access any form control input,select,textarea
console.log(value);
// Just to check if I get the correct value
});
EDIT: if the TD contains text
var value = $(this).text();
Instead of scraping the DOM, you could invert the logic, and build the rows using javascript instead. Check out this jsBin to see the solution in action: http://jsbin.com/aligaZi/2/edit?js,output
Start with an empty table:
<table class="data-table" id="test">
<thead>
<tr>
<th>value1</th>
<th>value2</th>
<th>value3</th>
<th>value4</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Since you need to fill a form with the data, I'll be using a simple one as an example:
<form class="data-form">
<label>Value1<input class="value1" /></label>
<label>Value2<input class="value2" /></label>
<label>Value3<input class="value3" /></label>
<label>Value4<input class="value4" /></label>
</form>
Then, on the javascript side:
$(function() {
// Interpolate the values somehow.
// I'm not familiar with JSP syntax, but it shouldn't be too hard.
// I will use dummy data instead.
var tableData = [
{
value1: "row1-v1",
value2: "row1-v2",
value3: "row1-v3",
value4: "row1-v4"
}, {
value1: "row2-v1",
value2: "row2-v2",
value3: "row2-v3",
value4: "row2-v4"
}
];
// For each object, create an HTML row
var rows = $.map(tableData, function(rowData) {
var row = $("<tr></tr>");
row.append($('<td class="class1"></td>').html(rowData.value1));
row.append($('<td class="class2"></td>').html(rowData.value2));
row.append($('<td class="class3"></td>').html(rowData.value3));
row.append($('<td class="class4"></td>').html(rowData.value4));
// When this row is clicked, the form must be filled with this object's data
row.on("click", function() {
fillForm(rowData);
});
return row;
});
$(".data-table").append(rows);
function fillForm(rowData) {
var form = $(".data-form");
form.find("input.value1").val(rowData.value1);
form.find("input.value2").val(rowData.value2);
form.find("input.value3").val(rowData.value3);
form.find("input.value4").val(rowData.value4);
}
});
Just looking for the best practise way of doing this.
I have a table listing information and in the last column is a button with "Edit/View". When the user clicks on the button a div area appears with more information which can be edited
Code below with some fragments of jstl
<script type="text/javascript">
//Click on Edit/View on table
$('.viewCustomer').click(function()
{
.......
});
</script>
<tr class="odd">
<td>${customerBean.comName}</td>
<td>${customerBean.comCode}</td>
<td class="noRightPad"> <input type="submit" name="createBut" value="View/Edit" class="viewCustomer" /> </td>
</tr>
So my question would be:
(1) how do i pass a variable to function $('.viewCustomer').click(function()
(2) is this the best way of going about to do this. Is there a more efficient/secure/cleaner of doing this?
Cheers
Alexis
The click function will not be called by you. It is called when the button is clicked, and as such has the event object passed to it:
$('.viewCustomer').click(function(evt){
.......
});
What exactly are you wanting to pass? You can access the DOM element that you are clicking using this and $(this), so maybe it possible to reference what you want from here.
EDIT For comment
if the user clicked on the button that
was in the 4th row of the table and in
that row the another colum had
customer id 1234 i want to pass the
variable 1234.
NOTE: None of the below has been tested, but ought to suffice
Let's assume your 'customer id' column has a classname of 'customerid'. So your HTML might be:
<tr class="odd">
<td>${customerBean.comName}</td>
<td class="customerid">${customerBean.comCode}</td>
<td class="noRightPad"> <input type="submit" name="createBut" value="View/Edit" class="viewCustomer" /> </td>
</tr>
The jQuery might look something like:
$('.viewCustomer').click(function(){
var $buttonCell = $(this).parent(); //the <td> containing the button
var $buttonRow = $buttonCell.parent(); //the <tr> containing the button and your customer id
var $customerIdCell = $buttonRow.find("td.customerid");
var customerId = $customerIdCell.text();
});
The above is proken down into lines to show you how stuff is being retrieved. Using 'chaining' we can express it more concisely:
$('.viewCustomer').click(function(){
var customerId = $(this).parent().parent().find("td.customerid").text();
}
You can also search for the customerid cell as a 'sibling' of the button cell for an even more concise approach (and one less function call).
$('.viewCustomer').click(function(){
var customerId = $(this).parent().siblings("td.customerid").text();
}