I have a html table containing data rows. I am building add/edit/delete functionality to the table using AJAX.
The format of my table row is as follows:
<tr id="281"><td class="todo-task">fdgdg</td><td>some more data</td><td>EDIT BUTTON</td></tr>
At the moment I have a working AJAX function to both add a new row and edit a row via a prepend().
In order to edit a table row, you click the edit button which pulls the values into the form and submits ... simples so far. Here's the code for the edit click and the form markup. Note the id from the edit click goes into a hidden field in the form.
$("button.edit-todo").bind("click", function(){
var task = $(this).closest('tr').children('td.todo-task').text();
var todoID = $(this).closest('tr').attr("id");
$("div#todo-form input.todo-task").val(task);
$("div#todo-form input.key").val(todoID);
});
...
<form id="mgnt-edit-todo-form" class="record-edit-form">
<input type="text" class="todo-task input" name="task">
<input class="key" name="key" type="hidden" value="279">
<button class="update uk-button uk-modal-close" type="submit">Save</button>
</form>
... and the ajax bit which binds the hidden field for the update.
$("button.update").bind("click", function(e){
var key = $(this).closest('.key').attr('value');
$.ajax({
type: "POST",
url: "update-record.php",
//etc etc etc
The problem
The first update works fine, it will prepend a table row including the id. The issue occurs when I then wish to make a further update to that same "prepended" row. Whilst the DOM shows the markup as correct the function on button.edit-todo will no longer get the id. When looking at the form markup in the DOM, the value of the hidden field is blank.
I've looked at the source in Chrome and I can see that it does not match the view in the browser/DOM. For example, the markup is all the same, but the rows have been put into a different order - it looks as though by date. (There is a date field but I have cut down the fields for this example..) I think this is causing the issue ... question is why? and how do i fix it?
Thanks
Update
Here is my markup in the DOM, looks fine to me.
To be absolutely clear the issue is occuring when clicking the edit button.
It calls the following function (now using 'on':
$("button.edit-todo").on("click", function(){
//load the data from this row
var task = $(this).closest('tr').children('td.todo-task').text();
var client = $(this).closest('tr').children('td.todo-client').text();
var due = $(this).closest('tr').children('td.todo-due').text();
var todoid = $(this).closest('tr').attr('id');
$("div#todo-form input.todo-task").val(task);
$("div#todo-form select").val(client);
$("div#todo-form input.todo-due").val(due);
$("div#todo-form input.key").val(todoid);
});
Clicking row 286 works as intended (it was present on the page load) in that the tr id is added to the hidden field in the form. Clicking row 297 (as far as I'm aware in the DOM?) does not pass the id to the hidden field...
Please help!!! Doing my head in...!
Instead of .bind use .on:
$("button.edit-todo").on("click", function(){
(...)
and
$("button.update").on("click", function(e){
(...)
Using ID for loaded data is not very comfortable way anymore. Use class instead of ID.
Also jQuery has changed "bind" to "on" method. I recommend to use "on".
For example:
$(document).on("click", ".edit-todo", function(){
var task = $(this).closest('tr').children('.todo-task').text();
var todoID = $(this).closest('tr').attr("id");
$(".todo-form .todo-task").val(task);
$(".todo-form .key").val(todoID);
});
Also, source shows the code when the document loads, not the dynamic DOM.
Related
I'm new to AJAX and a lot of JS, but I need to replace some old angular functionality on our Laravel site.
We simply have a page with a static/sticky header search bar, but no submit button. It needs to do a live filter upon search input. i.e. if I type sofa, it should hide anything from the page without the word sofa.
The Laravel blade/HTML is built with foreach loops from controller data, but more importantly, the data is stored in a JSON object called orderFormData, shown below.
I need a simple and effective live search filter to hide anything that doesn't match between the JSON and the search bar. The page is built with multiple HTML tables so I don't want to filter by the table and I think that's too complicated and convoluted. It should suffice to do it by JSON, possibly with AJAX. However, I'm a total novice here and I'm desperate for a solution.
Here's the search html:
<div class="md-input-wrapper search-form">
<form class="uk-search" id="searchProducts">
<input type="text" class="md-input label-fixed" name="srch-term" id="srch-term" autofocus placeholder="Search Products"/>
<span class="md-input-bar"></span>
</form>
</div>
Here's the JSON object and some JS that I was playing with, but it doesn't work:
<script type = "text/javascript">
var orderFormData = <?php echo json_encode ($tempdata);?>;
$(document).ready(function(){
$('#srch-term').on('keyup',function(){
var searchTerm = $(this).val().toLowerCase();
$('.uk-table tbody tr').each(function(){
var lineStr = $(this).text().toLowerCase();
if(lineStr.indexOf(searchTerm) === -1){
$(this).hide();
}else{
$(this).show();
}
});
});
});
</script>
This is just a pure JS idea, but I'm interested in AJAX as well if it will work better for this scenario. How can I properly filter items on the page by tying the search bar and JSON object?
You don't need of Ajax to do a search function with hide and show, this is simply manipulating DOM, instead ajax can calls the json from the php and with jquery you can simple loop your td on keypress and use :contains of jquery, onkeypress you call a function and in this function you do show and hide if contains "search" show otherwise hide.
Here a simple example in one of my old project #tabellaWebLog was the id of the table ricercaUser was the id of the input search and trTabellaWebLog was the id of the row where i wanted the search instead .ricUser was the class of the table column to loop the search inside the table...Bye
user = $('#ricercaUser').val();
$('#tabellaWebLog').find("#TrTabellaWebLogRiga:not(:contains('"+ user +"'))").hide();
$(".ricUser:contains('" + user + "')").parent().show();
$(".ricUser:not(:contains('" + user + "'))").parent().hide();
I have a form with a « newInput » button, which add dynamically in javascript a new input when I click to it.
When I have an error in my form, I re-load the view with the form. It’s normal, but .. Because I use dynamic javascript for adding new input, all the input added are removed when I reload..
There is something I can do ?
This is an exemple of my view.tpl :
<input type="text" placeholder="ex: cerise"
onfocus="javascript:autoComplet('jigd1', '{site_url('recettes/getIngredient')}')" value="{set_value('igd[]')}" id="jigd1" name="igd[]"/>
{form_error('igd[]')}
I add a partiel code of my js file
var cpt=1;
function addField(uriIngredient, uriLabel) {
try
{
cpt=cpt+1;
var inputIgd = document.createElement('input'),
button = document.createElement('input'),
div = document.createElement('div'),
inputIgd.setAttribute('type','text');
inputIgd.setAttribute('name','igd[]');
inputIgd.setAttribute('id','jigd'+cpt);
button.setAttribute('type','button');
button.setAttribute('onclick','javascript:supField("igd'+cpt+'")');
button.setAttribute('value','Supprimer');
div.setAttribute('id','igd'+cpt);
div.appendChild(inputIgd);
div.appendChild(button);
document.getElementById("listIgd").appendChild(div);
...
Since you are appending new input/button to dom dynamically and not saving its state by making ajax call/submitting form you cannot retain the input/button after reloading the page.
Using localStorage, to keep the information of previously added input/buttom would be preferable.
PS : since you havent added any code which you tried, its really hard to explain localStorage with specific code.
as soon as you append, add the state of the form into localStorage,
When you loading the page, look for the localStorage to check the previously added inputs
you can set the item into localStorage :
window.localStorage.setItem('key','value')
You can retrieve them like this :
window.localStorage.getItem('key')
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? :)
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";
}
I have a table that is dynamically built using DOM. It has 10 cols, and on each row i have some data that i get from a websocket, text boxes and a submit button to add each row to the database.
How can i remove a row after i submitted it?
Someone mentioned jQuery but can't figure it out how to do that.
EDIT
I'm using Chrome and had problems with all the scripts below. this is how i resolved it:
instead of $('input') I used jQuery('input') all the scripts are working fine.
thank you for your help.
Try something like this...
$('input').click(function() {
$(this).closest('td').remove();
});
Demo: http://jsfiddle.net/wdm954/32W63/
EDIT:
Here is another way to do this...
$('table form').submit(function() {
// run some ajax here to do your database work
$(this).closest('td').remove();
});
You can do like this:
$(document).ready(function(){
//Assuming all your submit buttons have the same class
$(".submit").live("click", function(e){
var buttonHnd = $(this);
$.post("your-php-file.php",
{/* the data you want to post e.g. */ name: $("#name").val()},
function(data){
buttonHnd.parent().parent().remove();
}
);
});
});
var myTableRow = ... // Find the row however you like
myTableRow.parentNode.removeChild(myTableRow);
You might also be interested in my AJAXFetch jQuery plug-in. Among other things, it lets you treat a row of a table as a form and submit all the form elements in it using AJAX, swapping it out the row with the result from the server (usually the non-form version). I use it in many of my internal applications for in-place editing of data.
You could try something like:
// Simple bottom row removal
$('#myTable tr:last').remove();
// Removing n'th (ex. 3rd) row from the table
$('#myTable tr:eq(2)').remove();
Source: JQuery HowTo
you can use jquery' remove to remove it from dom...
http://api.jquery.com/remove/