jQuery .click function not working only for first link - javascript

I have simple foreach loop in my razor view:
#foreach (var item in Model.materijali) {
<tr>
<td>
#Ajax.ActionLink(item.sifra_materijala,
"DetaljiMaterijala",
"NormativiMaterijala",
new { materijal = item.sifra_materijala.ToString() },
new AjaxOptions { HttpMethod = "GET" },
new { id = "mylink" })
</td>
</tr>
And a jQuery function:
<script type="text/javascript">
$(function () {
$('#mylink').click(function () {
$.post(this.href, function (json) {
var json = $.parseJSON(data.responseText);
$("#sifra_materijala").val(json.sifra_materijala.val())
alert(json.sifra_materijala);
});
return false;
});
});
</script>
This calls controller action and returns some result that I need to show on my partial view.
When I click on any href link generated by foreach loop, controller action is regularly called and executed, except on the first one, when nothing happens...
Can someone help me with this?

I've never done any dot net programming, let alone used razor views, but as I understand it, #Ajax.ActionLink generates an <a> element and the JavaScript that makes the ajax call when the link is clicked.
You have added a second ajax call, but for the first <a> element only. It applies only to the first one because even though you may have several <a> elements with id="mylink", id values are supposed to be unique. The handler you supply also has an error in it: It references data.responseText, but data is undefined.
Instead of adding your own click handler, supply an OnSuccess callback function for the ajaxOptions parameter for the #Ajax.ActionLink call. And get rid of the new { id = "mylink" } parameter.

Related

Execute DataTables ajax.reload() Async before a function

I am trying to source some data from the datatable I am working on. I have an edit button on every row and when is clicked it suppose to bring a form with the data that is already in the table for editing. I need to get real time data when the form is render however ajax.reload() doesn't load the table on time for the form be filled by the correct data and with code below only shows the form for the first employee:
let editEmployeeId;
$(document).ajaxStop(function(){
$('#employeesTable tbody').on('click', '.btn.btn-warning.small-edit-button', function(){
let thisRow = this;
tableEmployees.ajax.reload(function(){
//tableDepartments.draw();
tableDepartments.columns().search("").draw();
//tableEmployees.columns().search("").draw();
getDropdown(1,'#departmentEditDropdown', 'Departments');
var data = tableEmployees.row($(thisRow).parents('tr')).data() || tableEmployees.row($(thisRow).parents('li').attr('data-dt-row')).data();
$('#editFirstName').val(data.firstName);
$('#editLastName').val(data.lastName);
$('#departmentEditDropdown>select').val(data.department);
updateLocation('#locationEditDropdown','#departmentEditDropdown>select');
$('#departmentEditDropdown>select').trigger('change');
$('#locationEditDropdown>select').val(data.locationID);
$('#editJobTitle').val(data.jobTitle);
$('#editEmail').val(data.email);
$('#editEmployeeModal').modal("show");
});
});
I tried:
promise
settimeout
nested functions
async functions
I also try to change ajax call to set async: false and this way it works perfect but I don't think that is a good practice and I have other calls through the document and takes double of time to load the page first time.
I changed the way of calling the button with an extra class for the employees page and used the .click() method instead .on() because for some reason it was going in a loop with the last one. Now works and this is how it looks:
let editEmployeeId;
$(document).ajaxStop(function(){
$('.btn.btn-warning.small-edit-button.employees').click(function(e){
e.preventDefault();
let thisRow = tableEmployees.row($(this).parents('tr'));
let thatRow = tableEmployees.row($(this).parents('li').attr('data-dt-row'));
tableDepartments.columns().search("").draw();
tableEmployees.columns().search("").draw();
getDropdown(1,'#departmentEditDropdown', 'Departments');
tableEmployees.ajax.reload(function(){
var data = thisRow.data() || thatRow.data();
editEmployeeId = data.id;
$('#editFirstName').val(data.firstName);
$('#editLastName').val(data.lastName);
$('#departmentEditDropdown>select').val(data.department);
$('#departmentEditDropdown>select').trigger('change');
$('#editJobTitle').val(data.jobTitle);
$('#editEmail').val(data.email);
$('#editEmployeeModal').modal("show");
})
});

Avoiding multiple AJAX calls on jQuery sortable( )

I am new to jQuery. Basically I have a table which I can sort the rows. I want to save the new order in the backend, which I am able to do. However, I noticed that I am sending multiple Ajax calls depending on the number of times I sorted the table. The order is not saving properly in the backend. Here is my code. The variable order is where the new IDs are stored. I am sending it in my Django through the '/updateorder' route/
<script type="text/javascript">
$(document).ready(function(){
$("#sortable").sortable({
update: function (event, ui) {
var order = $(this).sortable('toArray');
console.log(order);
$(document).on("click", "button", function () {
$.ajax({
data: {csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value, 'order[]': order},
type: 'POST',
url: '/updateorder'
})
});
}
}).disableSelection();
$('button').on('click', function () {
var r = $("#sortable").sortable("toArray");
var a = $("#sortable").sortable("serialize", {
attribute: "id"
);
console.log(r);
});
});
</script>
How can I avoid sending multiple Ajax calls when I click on the button? Also, what is the correct way to redirect to a different page after the logic is executed? Thanks for reading!
PS: I am using python/django in the backend
The answer is in your code. You attach event handler everytime you move item. So when you sort 5 items, you attach 5 event handlers to your submit button. Then when you click the button all 5 event handlers fire ajax call at once. You should move onclick event handler outside and pass variable through function argument or public variable.

Referencing DOM within object

I have a table where each row contains some data (data-id) and a <div class = "upload">Upload</div>. The uploader needs to be passed an object which contains uploader_obj.button set as the initiating <div>, any parameters such as data-id to be sent to the server, and a bunch of other stuff which I didn't show.
The following script loops over the table, modifies the object to set button and params.id, and creates the uploader on each row.
While a separate upload button is created on each row, they each reference the same params.id which is set to the last row's value (i.e. 222). I need each to be set to the value of their specific row.
One way to fix it is to have each uploader have it's own upload_obj, but this seems like a waste of memory.
Instead, I tried to reference data-id within the uploader_obj. I can do so within onSubmit, however, haven't figured out how to use this value to set param.id. I've tried to set it within param by doing something like params: {'id':$(this.button).parent().parent().data('id')} but this is my document, and not the uploader.
So... Without making a separate uploader_obj for each row, how could I make each row's uploader sent its own param.id to the server? Thank you
PS. Sorry for the weak title. I really tried to think of a better one but couldn't.
<table>
<tr data-id="123"><td>Hello</td><td><div class="upload">Upload</div></td></tr>
<tr data-id="321"><td>Hello</td><td><div class="upload">Upload</div></td></tr>
<tr data-id="222"><td>Hello</td><td><div class="upload">Upload</div></td></tr>
</table>
var uploader_obj = {
button:null,
params: {'id':null},
onSubmit: function(id, fileName) {
var id=$(this.button).parent().parent().data('id')
console.log(id);
},
otherStuff: whatever
};
$('#myTable div.upload').each(function(i,v){
uploader_obj.button=this;
uploader_obj.params.id=$(this).parent().parent().data('id');
new qq.FileUploaderBasic(uploader_obj);
});
You're passing the same object in every iteration, just create the object from the values you have inside the loop instead:
$('#myTable div.upload').each(function(i,ele){
new qq.FileUploaderBasic({
button: ele,
params: {
id: $(ele).closest('tr').data('id')
},
onSubmit: function(id, fileName) {
var id=$(this).closest('tr').data('id')
},
otherStuff: whatever
});
});
I think the problem is that you never create a new object of "uploader_obj". So on every loop-iteration you are overwriting the values of your object.
edit:
var a = new Object();
$('#myTable div.upload').each(function(i,v){
a[i] = uploader_obj;
a[i].button=this;
a[i].params.id=$(this).parent().parent().data('id');
new qq.FileUploaderBasic(a[i]);
});
Instead of making uploader object as a global variable, if you make it local varaible to qq.FileUploaderBasic function and send button_object and data_id as a parameter, may be it will work.
you can try like
$('#myTable div.upload').each(function(i,v){
var button=this;
var id=$(this).parent().parent().data('id');
new qq.FileUploaderBasic(button,id);
});
and keep your object inside your function.

Asp net mvc and javascript response

I had a javascript that needs to do two things:
1. Send data to be updated in database
2. Update my html form place in show mode.
3. Update the row of my table to reflect updated data.
My javascript do only 1 and 2:
$(".form-commands .save").live("click", function () {
var f = $(".form-edit");
var sf = f.serialize();
$.post(this.href,
sf,
function (response) {
f.html(response);
});
// I need to do something here to update the html table row...
return false;
});
I think that a solution is to call another action that will render only the table row elements.
How can I do this?
--
The table row was created something like this:
<tr id="h62">
<td>Ford</td>
<td>Focus</td>
</tr>
where 62 is the "id" of this record.
Working code, but ugly:
$(".form-commands .save").live("click", function () {
var f = $(".form-edit");
var sf = f.serialize();
var handle = $(".form-edit #Handle")[0].value;
var itemLink = this.attributes["edititem"].value;
var row = $("#grid #h" + handle);
$.post(this.href,
sf,
function (response) {
$("#form-edit").html(response);
$.get(itemLink,
sf,
function (response) {
row.replaceWith(response);
});
});
return false;
});
You need to do something like this:
$(".form-commands .save").live("click", function (evt) {
//Capture the jQuery event object and call preventDefault() to stop the default click action
evt.preventDefault();
var f = $(".form-edit");
var sf = f.serialize();
$.post(this.href,
sf,
function (response) {
f.html(response);
});
//UPDATE THE ROWS
$('#h62 td:eq(0)').text(newVehicleMakeName);
$('#h62 td:eq(1)').text(newVehicleModelName);
});
I am not sure from your code where the vehicle data is coming from. If you are passing it back from your controller then you will need to move this line into your success callback.
Also, you should generally never return false, you should capture the jQuery event as a param and call preventDefault(). If your click handler uses return false to prevent browser navigation, it opens the possibility that the interpreter will not reach the return statement and the browser will proceed to execute the anchor tag's default behavior. This is what was causing your problem, not because you were using click vs submit. The benefit to using event.preventDefault() is that you can add this as the first line in the handler, thereby guaranteeing that the anchor's default behavior will not fire.
Well I would just reload the page or recall the ajax routine (whichever is applicable) to reload the data, there is no straightforward method to do this. In fact I was not aware of the method you used (f.html(response)), i am still skeptical about that solution :)
Well, if you really just want to update that single row:
1) You need to know to know the updated row's id in your javascript code. This value is "h62" (without quotes) in this example.
2) Give class names to your TDs, e.g.
<tr id="h62">
<td class="brand">Ford</td>
<td class="model">Focus</td>
</tr>
3) Update using jquery. Let's say you hold the id of the row in a variable named "rowId":
$('#'+rowId).find('.brand').html(response.brand);
$('#'+rowId).find('.model').html(response.model);
This will conclude the process.

Prototype Event.observe not seeing AJAX-returned HTML

I'm trying to create a CMS system based on AJAX using Prototype's library. On a page load, I have HTML, page title and additional Javascript for the page returned via JSON, and I update the HTML on the main area. I also have an event listener that listens for certain ID's to be clicked on.
The listener is working,
var TabMenu = {
selectedTab: 'main',
showTab: function(pid) { alert(pid); alert($(pid));
$(pid).addClassName('selected'); this.selectedTab = pid;
$(this.defaultTab).removeClassName('selected');
}};
After loading, I click on one of the new tabs, and the first "test" alert successfully alerts the element's ID, but the second alert ($(pid)) returns null. I can only surmise that the HTML returned by the AJAX request is not being evaluated and added to the DOM, otherwise it would alert [HTMLDivElement] instead of "null".
Here is the relevant AJAX call:
new Ajax.Request(url, {
onSuccess: function(t) {
data = t.responseText.evalJSON();
Page.update(data.html, data.title, data.js);
Page.destroyLoader();
}
});
And here is the updating function:
update: function(data, title, js) {
document.title = Global.title + title;
if (title != "") { $('HEADING').update(title); }
$('MAIN').update(data);
if (js != "") {
var nuJS = new Element('script', { type: 'text/javascript' }).update(js);
$('MAIN').insert({ top: nuJS });
}
}
Any ideas on how I can get this working?
When is the ajax request triggered? Is it triggered when you click the tab? If so the showTab function is being triggered before data has been inserted into the DOM.
If you have firebug, try using the console to select the html data, after the ajax call has finished, to see what you get. You can also use firebug's html tab to see if the data has been inserted into the DOM.
Also, even though you get the pid parameter that is set to a value, does it refer to a real id that exists in the DOM?
From your code and the comment above.
I think your plan is to load all the tabs after the page loaded immediately.
And hide all of them using the css. Wait until the user click the tab,
Show only the one that is "selected", right?
That's mean you should change:
$('MAIN').update(data);
To something like
$('MAIN').update({after: data});
So it won't overwrite the existed one.
And don't forget to move the code for document.title and eval js into showTab function.
For javascript evaluation you can insert the js into data.html and use this instead:
$('MAIN').innerHTML.evalScripts();

Categories