retrieve value from textbox that is not on the current pagination - datatables - javascript

I am using VB.Net, MVC, Razor, javaScript and jQuery with the Datatables plugin. I am rendering a table that contains text boxes. The user is allowed to type values into these text boxes and submit the values to the database.
Everything works fine as long as the table is only one page long. In the event that the table is multiple pages, only the values that are visible are submitted. However if the user enters values on page one, moves to page two, then back to page one, the values that were typed into the text boxes are still there. This leads me to believe the values are still on the web page somewhere. I am currently using javaScript getElementsByClassName to retrieve the values.
Here is how my table is rendered:
<tbody>
#For i As Integer = 0 To Model.History.Count - 1
#<tr>
<td>#Model.History(i).Quarter</td>
#If Model.History(i).MeterUsage < 0 Then
#<td>
<input class="edit" id="#(Model.History(i).dateToRecord)" type="text" placeholder="meter usage" />
</td>
Else
#<td>#Model.History(i).MeterUsage</td>
End If
<td>#Model.History(i).KeyOperator</td>
<td>#Model.History(i).BackUpKeyOperator</td>
</tr>
Next
</tbody>
Here is my javaScript:
function submitChanges(changes) {
var changes = document.getElementsByClassName('edit');
var myChanges = {
listOfIDs: [],
listOfValues: []
};
}
Is there some way to capture the values that are entered on page 1 of the table, when the user is viewing another page of the table?

Use $() API method to get access to all elements in the table.
function submitChanges(changes) {
var changes = $('#example').DataTable().$('.edit');
var myChanges = {
listOfIDs: [],
listOfValues: []
};
}
Replace example with your actual table ID.

Related

Populating HTML table based on checkboxes

I have multiple checkboxes on a HTML page, and I would like to be able to populate a table on a second HTML page based on what checkboxes have been clicked.
As a basic example, here is a div containing 2 of the checkboxes. I would like it so that if, say, awareness_checkbox was checked, the word Awareness and it's value (0.01 CPC) would be added to a table on my second HTML page.
How would be the best way to go about doing this? My intention is to have a HTML button that links to the second page (let's call it 'page2.html') so that when it is clicked, every checkbox that has been checked on the page has it's label and associated value added to a table that will appear on the second page.
Any help would be greatly appreciated.
<div class="campaignstrategy">
<h1>1. Campaign Strategy</h1>
<input type="checkbox" name="awareness" id="awareness_checkbox" value="0.01">Awareness<br>
<input type="checkbox" name="directresponse" id="directresponse_checkbox" value="0.01">Direct Response<br>
</div>
Note
okay, so I re-did all the code and tested locally on chrome, just save both files in the same directory and then open page1.html in chrome.
Code Extracts - Page 1
Assign a custom action to the input button, this will check all checkbox input type inputs,
it will then see whether or not it is checked, if it is checked then it will add an entry into table_info variable, after checking all inputs
it will then convert the javascript object into a json string, then we convert that json into base64 encoded string.
then we browse to the page2.html file and in the url we pass a key called "table_data" and its value is the base64 encoded string.
$('#next_page_button').click(function(){
let table_info = [];
$('.campaignstrategy input[type=checkbox]').each(
function(index, value){
if($(this).is(':checked')){
table_info.push(
{
name: $(this).attr('name'),
value: $(this).attr('value'),
}
);
}
});
let base64str=btoa(JSON.stringify(table_info));
window.location = "page2.html?table_data=" + base64str;
});
Code Extracts - Page 2
when this page is loaded into the browser, the following script will check the query keys, in this case we are looking for 'table_data' key.
this will be accomplished by a helper function (see pastbin for details, left out to keep the answer short)
once we have the data, we will decode it from base64 to json, then using the json.parse function we will recreate the javascript object.
after creating the object, we will loop through the array, remember the javascript object that we decode is an array of dictionaries,
[{'name':'awareness','value':'0.01'}] as you see, it has the checkbox's name and its associcated value.
then we create the table row, and append the name and value to the table row inside a table data element, one for each name and value.
// actual code
let table_data = getUrlParameter('table_data');
let data_from_page_1 = JSON.parse(atob(table_data));
for(let i=0;i<data_from_page_1.length;i++){
let row = $("<tr></tr>");
let recordName = $("<td></td>").text(data_from_page_1[i].name);
let recordValue = $("<td></td>").text(data_from_page_1[i].value);
row.append(recordName, recordValue);
$('#output_table').append(row);
}
Examples
Page 1
Page 2
Instructions
save the contents of this to a file called page1.html Code Link For Page 1
save the contents of this to a file called page2.html Code Link For Page 2

How to get selected values of checkboxes in DataTable of different pagination pages PHP and javascript?

Basically I have a dataTable that displays all the records from the database, and a checkbox for each row within the table. My table has multiple pages. The problem was that I can only get the checkbox values of the current page selected because the system can only see checkboxes that are visible. I want to get specific checked values or all checked values from different pages and push them to the array. How can I achieve this? I can only get the checked value of current selected page in datatable atm. I have searched and tried similar problem, but it's still not working.
Below is my code
PHP code to display checkboxes
foreach($stmt as $row){echo "<tr><td>"."<input type='checkbox' name='check_list' id='checklist' value='$row['id']' style='width:20px; height: 20px'/>"}
Javascript code
function getCheckboxVals(){
var check = $('input[name="check_list"]:checked').length;
var mycheckboxes = new Array();
//IF NO CHECKBOX CHECKS
if(check == 0){
eModal.alert('PLEASE SELECT ISSUES BEFORE YOU EXPORT CONTENTS!!!');
return false;
}
//IF ONE OR MORE CHECKBOXES CHECK
if(check == 1){
$('input[name="check_list"]:checked', table.fnGetNodes()).serialize().each(function(){
mycheckboxes.push(this.value);
});
}else{
$('input[name="check_list"]:checked').each(function(){
mycheckboxes.push(this.value);
});
}
}
The issue with only being able to get the values of the check boxes on the current page comes from the use of DOM methods or querying without using the DataTables' API directly. For efficiency, the DataTable only stores the values on the current page. In order to access other values you must use access the table using:
dataTable.rows().nodes().to$().find('input[type="checkbox"]').each(function(){}
The datatable in this instance being your defined datatable.
Additionally, here is a working version of checkbox values being stored and sent to the server
For more info see the DataTable FAQs and topics on DOM.

How to update ZK Grid values from jQuery

I have three Tabs and in each tab, I have a Grid.
The data for each Grid is coming from a database, so I am using rowRenderer to populate the Grids. The following code is common for all three Grids:
<grid id="myGrid1" width="950px" sizedByContent="true" rowRenderer="com.example.renderer.MyRowRenderer">
The rows are constructed from Doublebox objects. The data is populated successfully.
The Problem:
I need to handle multiple-cell editing on the client side. The editing is done via mouse-clicking on a particular cell and entering a value.
As example let's say that the user edits first cell on the first row and the value should be
propagated to all other cells on the same row and in all three Grids (so also the two Grids which the user currently does not see, because they are in tabpanes).
I am using jQuery to do this value propagation and it works OK.
I am passing the jQuery as follows:
doublebox.setWidgetListener(Events.ON_CHANGING, jQuerySelectors);
doublebox.setWidgetListener(Events.ON_CHANGE, jQuerySelectors);
This makes it possible to change the value in 1 cell and the change is instantly (visually) seen in all other cells filtered by jQuery selectors.
The problem is that the value is visually distributed to all the cells, but when I try to save the Grid data back to the database, the background values are the old ones.
I am assuming that ZK-Grid component is not aware that jQuery changed all the cell values. Nevertheless if I manually click on a cell that already has the NEW value (enter/leave/change focus) when I save the grid the NEW value is correct in that particular cell. Maybe that's a hint how can I resolve this.
Code of how I extract the Grid values:
Grid tGrid = (Grid) event.getTarget().getFellow("myGrid1");
ListModel model = tGrid.getModel();
MyCustomRow tRow = (MyCustomRow)model.getElementAt(i);
The model for my Grid is a List of MyCustomRow:
myGrid1.setModel(new ListModelList(List<MyCustomRow> populatedList));
I have a couple of assumptions, but whatever I have tried, hasn't worked. I have in mind that jQuery events and ZK-Events are different and probably isolated in different contexts. (Although I have tried to fire events from jQuery and so on..)
Do you have any suggestions? As a whole is my approach correct or there's another way to do this? Thanks for your time in advance!
Your problem is exactly what you are expecting.
Zk has it's own event system and do not care about your jq,
cos it's jq and zk don't observ the DOM.
The ways to solve your problem.
Use the "ZK-Way":
Simply listen at server-side and chage things there.
I am not sure if not selected Tabs
are updateable, but I am sure you could update the Grid
components on the select event of the Tab.
Fire an zk-event your self:
All you need to know, is written in the zk doc.
Basically, you collect your data at client side, send
an Event to the server via zAu.send() extract the
data from the json object at serverside and update your Grids
I would prefer the first one, cos it's less work and there should not be
a notable difference in traffic.
I post the solution we came up with:
This is the javascript attached to each Doublebox in the Z-Grid
//getting the value of the clicked cell
var currVal = jq(this).val();
//getting the next cell (on the right of the clicked cell)
objCells = jq(this).parents('td').next().find('.z-doublebox');
// if there's a next cell (returned array has length) - set the value and
// fire ZK onChange Event
if (objCells.length) {
zk.Widget.$(jq(objCells).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCells).attr('id')).fireOnChange();
} else { //otherwise we assume this is the last cell of the current tab
//So we get the current row, because we want to edit the cells in the same row in the next tabs
var currRow = jq(this).parents('tr').prevAll().length;
//finding the next cell, on the same row in the hidden tab and applying the same logic
objCellsHiddenTabs = jq(this).parents('.z-tabpanel').next().find('.z-row:eq(' + currRow + ')').find('.z-doublebox');
if (objCellsHiddenTabs.length) {
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).fireOnChange();
}
}
The java code in the RowRenderer class looks something like this:
...
if (someBean != null) {
binder.bindBean("tBean", someBean);
Doublebox box = new Doublebox();
setDefaultStyle(box);
row.appendChild(box);
binder.addBinding(box, "value", "tBean.someSetter");
...
private void setDefaultStyle(Doublebox box) {
box.setFormat("#.00");
box.setConstraint("no negative,no empty");
box.setWidth("50px");
String customJS = ""; //the JS above
//this is used to visually see that you're editing multiple cells at once
String customJSNoFireOnChange = "jq(this).parents('td').nextAll().find('.z-doublebox').val(jq(this).val());";
box.setWidgetListener(Events.ON_CHANGING, customJSNoFireOnChange);
box.setWidgetListener(Events.ON_CHANGE, customJS);
}
What is interesting to notice is that ZK optimizes this fireOnChange Events and send only 1 ajax request to the server containing the updates to the necessary cells.

Click function in Django form

I have no idea how can I solve my problem. I have Django template with two models. I put these models in inlineformset_factory.
Example
DhcpConfigFormSet = inlineformset_factory(Dhcp, IPRange, extra=1)
and I displayed this form in template like this pictures
form http://sphotos-h.ak.fbcdn.net/hphotos-ak-prn1/601592_10151469446139596_1335258068_n.jpg
I want implement event, when I click on plus stick (marked field on pictures), show one more row (ip initial field, ip final field and delete check box).
I tried to do it on this way :
$(document).ready(function() {
$(".plusthick-left").click( function() {
var tr= $(".sort-table").find("tbody tr:last").length;
$(".sort-table").find("tbody tr:last").after($(".sort- table").find("tbody tr:last").clone())
});
but I have problem, because I just made copy of last row and took same attributes values?
My question is : How can I make new row, and set all attributes with values of last row increased by one.
For example:
<input type="text" id="id_ip_initial_0_ip_range">
This is field that generated form in template, and I want make field with id value like this:
<input type="text" id="id_ip_initial_1_ip_range">
How can I do it? :)

How to align form fields within a table for inline editing?

I am developing a webapp using Spring, jsp, javascript, jquery.
I display a table using datatables.
When I click on a table row I want it to change all fields to an inline edit inputs, selects etc. In addition I want to show some extra input fields in the next row and a save button.
Now I see several ways of doing this. I am not sure which one to take.
I can get a handle to selected row and then iterate over the td and transform them to input/select fields. I can then insert an extra row for the new fields and the save button.
I don't see this as a clean solution. I will have to issue a Post manually instead of using the Spring ModelAttribute binding for the form. (Can I still use ModelAttribute here?)
I can create an edit form in a jsp file which looks like:
<form:form action="" commandName="">
<td> <input ... > </td>
<td> <select ... > </td>
</tr>
<tr>
<td> <label> <input new field> </td>
<td> <button> </td>
</tr>
Note I do not have a beginning in a jsp file as I plan to reuse the tr from the existing row in the table.
This way I would be able to have a clean form and also use the update method I have already written which binds the form to a Java class. Also I do not have to bother about the alignment of input fields with the column names.
The generated html looks like
...
The problem with this approach is the placement of form element in the html causes the entire form to be cramped into one cell of the table which does not look good and messes up the whole layout. Is there a way out? Should I just replace the contents of the table with a having a colspan and then put divs inside this element and fine tune the css to ensure that the input fields align with the column names in the table?
Is there a better solution you can suggest?
In case the question is not very clear I can fill in more details.
This is what I would do (coming from a server-side development background, as I know developers love easy solutions)
Wrap the table with a single form
on Edit row (clicking row) open an ajax request that returns pure html that looks like the exact tr, only with whatever extra you want to include:
<tr><td><input type="text" name="text1" ... /></td><td>second row... </td></tr>
<tr><td colspan="2">And hey, here is more, and the save button ... </td></tr>
in jQuery replace tr with content retrieved (myTr.replace($(ajaxResponse))) or something similar
now Save button is a regular submit for the form
if you want to submit via ajax, once done, return the old html in your ajax response and replace the two trs with the old tr (you just need to hook it by giving new trs an attribute that you can find easily in jquery)
don't forget to switch off a global key to prevent double editing, users can edit one row at a time
Update: adding a second solution to dump load on client instead of server
To avoid overloading the server (though I wouldn't be worried about it until it becomes a regular habit), you can make your form fields as a template inside your HTML and use string replacement (or jQuery Templates), so instead of ajaxing to get response in step 2, you call the template, and replace the strings with attributes you save in every row... like this:
<div id="myTemplate"> // or you can use jQuery script templates
<tr><td><input type="text" name="${Name}" ... /> id is ${Id}</td><td>${SecondRow}... </td></tr>
<tr><td colspan="2">Save button here.... and may be more text ${MoreText}</td></tr>
</div>
in every row in your code add sufficient attributes or ids to know what you want to replace with, like this:
<tr data-itemid="34"><td ><input type="text" name="text1" id="findme" ... /></td><td data-moretext="here is more text">second column </td></tr>...etc
so now in your replacement script:
$("#myTemplate").html().replace("${Name}", $(thisrow).find("#findme").attr("name"))
.replace("${Id}",$(thisrow).attr("data-itemid"));
etc...
Of course after submission it has to be a to server, but in case user "cancels" you can have another readonly template
By the way, that is the way I usually go with, I use jQuery templates, and create edit and view templates, but I also repeat edit forms and I use jQuery ajax submit manually... but that... my friend, is not a simple clean and maintainable solution I'm afraid
I've been into an issue like this a year before. This is a messy problem. Either way if you traverse each td of row and convert it into text field or You can create a separate jsp file for this.
But the best in this case is to change the content of td to input field and post the data manually. because in this case you cannot wrap form tag around tr. You have to manually post the values of each input field.
P.S The very best solution is to create an edit dialog.
There is another solution, but I'm under the impression you won't like it very much... you can use a single form for the whole datatable (wrapping the whole table in a form is permitted) generate input fields for the current row and if it's updated submit the form asyncronously with javascript and restore td contents to the original html, if you name your fields such as name="field[]" you can also submit multiple rows at a time (I don't know if you'd want that though).
You can write html code such as
<form action="">
<table>
<tr><td><input type="hidden" name="row[]" value="1"/><input name="field[]"/></td></tr>
<tr><td>field value for row2</td></tr>
<tr><td><input type="hidden" name="row[]" value="3"/><input name="field[]"/></td></tr>
</table>
</form>
you can just grab the form with jquery and submit it via xmlhttprequest as I suspect you would if each row was a separate form (which is illegal), if you don't want multiple rows, just remove the [] and submit each row
and upon submitting the values you get them numbered correctly, don't know exactly how it would behave in java but in php I'd get the following:
$_GET[row][0] = 1;
$_GET[field][0] = 'value typed in row1';
$_GET[row][1] = 3;
$_GET[field][1] = 'value typed in row3';
Alternative table definition to avoid having the same name again
<form action="">
<table>
<tr><td><input name="field[1]"/></td></tr>
<tr><td>field value for row2</td></tr>
<tr><td><input name="field[3]"/></td></tr>
</table>
</form>
It's the same table as above only you set explicit indexes for each entry thus avoiding duplicate names in the response, preferrably use a unique identifier which can describe the row from the table that you're modifying in there (when possible I use the primary key) instead of the row number, just in case that wasn't clear enough.
Have you tried:
Wrap whole table in the form
have the data entries as disabled inputs with their borders hidden via CSS
when user clicks edit, enable the inputs and show the borders
You'll probably need hidden elements for each field
When user submits the form, post via ajax and set the inputs back to disabled with hidden borders
What about contenteditable?
Demo: http://jsfiddle.net/SO_AMK/XQekC/
jQuery:
var ctrlDown = false;
$(document).keydown(function(e) {
if (e.which = "ctrlKey") {
ctrlDown = true;
}
}).keyup(function(e) {
if (e.which = "ctrlKey") {
ctrlDown = false;
}
});
$('#example').dataTable();
$("#example tr").click(function() {
if ($(this).hasClass("row_selected") && ctrlDown) {
submitRow($(this));
return false; // Break out so the next if doesn't run
}
else if ($(this).hasClass("row_selected") && ctrlDown == false) {
return false; // Break out so the next if doesn't run
}
if ($(this).siblings(".row_selected").length && ctrlDown == false) {
$(this).siblings(".row_selected").each(function() {
submitRow($(this));
});
}
$(this).addClass("row_selected");
$(this).children("td").each(function() {
$(this).attr("contenteditable", true);
});
});
function submitRow(elm) {
var data = [];
$(elm).removeClass("row_selected").children("td").each(function() {
data.push($(this).text());
});
alert(data); // This will stop the keyup from firing, but you won't (I hope) really be using alerts
}​
This has everything but a submit-to-server function, it's also completely inline and has support for selecting multiple rows.
The only bug is, when it shows the data alert the focus goes off of the main window so the keyup event never fires, since you probably won't be using alerts this shouldn't be an issue. To fix it in the fiddle, press and release ctrl after the alert closes before clicking a row.
I see couple of problems
Your no. Of columns in the table & the edit columns you show are different
You might not be having complete data to edit the row so you might need to do an Ajax call and get it
If you have complete data on then you don't need point 2, let's assume you have a function f called with the clicked tr as the parameter
function f(row)
{
var newRow = yourTable.insertRow(parseInt(row.rowIndex,10)+1);
//you can place the above or below the clicked row , or you can even make the row visible false And then show the new row
Var newCell = newRow.insertCell(0);
newCell.colspan = 6;//the count if columns in your table row
NewCell.innerHTML = " put your HTML content here";
}

Categories

Resources