Dynamically added link action produces 'This request has been blocked...' error - asp.net-mvc

When I add category in controller action I return JSON object:
return Json(new { categoryName = category.Name, isPrimary = isPrim ? "1" : "-1", categoryId = categoryId }, JsonRequestBehavior.AllowGet);
In JS handler function I add item on page:
...
var totalLink = "<li style='color: #bbbbbb;'>" + result.categoryName + "<a class='removeCategoryButton' href='#lnk#'>remove</a></li>";
var lnk = '#Url.Action("RemoveCategoryFromLocation", "Location", new{locationId = Model.Location.TicketId, categoryId=-1})';
totalLink = totalLink.replace('#lnk#', lnk);
totalLink = totalLink.replace('-1', result.categoryId);
$('#otherCategories').append(totalLink);
...
When I click on remove link I call the following function:
$(function () {
$('.removeCategoryButton').click(function (event) {
event.preventDefault();
$.ajax({
url: this.href,
type: 'POST',
context: this,
success: function (result) {
if(result.categoryName == 1) {
$(this).closest('li').remove();
}
}
});
return false;
});
});
But I get the following error:
This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.
This error happens only when I add item and want to remove it as soon after add on page. If I refresh page and click on remove link it works without problem.
Just to note when I get the error from above category is removed, so call works it just from some reason pop this error.

You seem to be adding the remove links dynamically and yet you have subscribed to the .click event handler only once when the DOM is ready. So make sure you do it in a lively manner. But since the .live() method is deprecated, depending on the jQuery version that you are using you should use either .delegate() or the .on() methods.
So with the latest version of jQuery it is recommended to use .on():
$(document).on(events, selector, data, handler);
$(document).on('click', '.removeCategoryButton', function () {
$.ajax({
url: this.href,
type: 'POST',
context: this,
success: function (result) {
if(result.categoryName == 1) {
$(this).closest('li').remove();
}
}
});
return false;
});
Notice that you no longer need to wrap this in a document.ready callback.

Related

Rails / Trix Editor save changes via AJAX to server

I am using the very simple to implement Trix Editor provided from Basecamp in an "Edit View".
How would one save automatically changes, without having the user to interact through the update button?
I am thinking about something like this:
(OLD SCRIPT)
window.setInterval(function() {
localStorage["editorState"] = JSON.stringify(element.editor)
}, 5000);
What I actually want to do:
post a ajax "post" request to the rails server. something like:
$('trix-editor').on('blur', function() {
var sendname = $('#note_name').val();
var sendlink = $('#linkinput').val();
var sendnote = $('input[name="note[note]"]').val();
$.ajax({
type: "POST",
url: "/notes",
data: { note: { name: sendname, link: sendlink, note: sendnote } },
success: function(data) {
alert(data.id);
return false;
},
error: function(data) {
return false;
}
});
(There is as well the problem with authentification and devise. Only if you are loged in you should be able to send an ajax post request ..??)
Even better would be to save changes only when the user changes some data, and then wait 5s and then push the updated data via json to the server. I have no clue how to do that...
PS: would have loved to tag this question with a "trix-editor" tag, sorry have not enought rep for doing so...
If you are using plain JavaScript, use a hidden input field:
<form>
<input type="hidden" id="noticeEditorContent"/>
<trix-editor input="noticeEditorContent" id="x" style="min-height: 200px;"></trix-editor>
</form>
Now you have access to the element with the ID x.
Which means, with getElementById, you can do something like that:
var richTex = document.getElementById("x");
With this variable, you can either set an interval as you already explained, or you are using jQuery to do the job:
$('#x').on('input', function() {
localStorage["editorState"] = JSON.stringify($('#x').val());
});
Just a suggestion. You can write this code a bit nicer and cleaner.
Now it depends. Is setting an interval every 5 seconds better or writing every change to the LocalStorage?
Suggestion:
Save the input when the user deselects the field:
$('#x').on('blur', function() {
localStorage["editorState"] = JSON.stringify($('#x').val());
});
Update: Here is a working JSFiddle.
so I came up with this code which saves via ajax on 'trix-blur' (which fires when the user disselects the trix-editor). There is only the question left if this code is secure enought with devise, or if now anyone can send data to be saved?!?
I have the authentification in the notes controller like that:
before_action :authenticate_user!
and here is the javascript part (with a custom messages functionality):
$('trix-editor').on('trix-blur', function() {
var sendname = $('#note_name').val();
var sendlink = $('#linkinput').val();
var sendnote = $('input[name="note[note]"]').val();
var sendid = $('#note_id').val();
$.ajax({
type: "PUT",
url: "/notes/" + sendid,
dataType: "json",
data: { note: { name: sendname, link: sendlink, note: sendnote }, id: sendid, commit: "Update Note" },
success: function(data) {
addMessage('auto saved ...', 'msg-success');
return false;
},
error: function(data) {
alert('error');
return false;
}
});
var addMessage = function(msg, msgclass) {
$('#notifications').append('<div id="msg" class="msg '+msgclass+'">'+msg+'</div>');
setTimeout(function() {
$('#msg:last-child').addClass('msgvisible');
}, 100);
displayMessage();
};
var displayMessage = function() {
setTimeout(function() {
hideMessage();
}, 2000);
};
var hideMessage = function() {
$('#msg').addClass('msghide');
setTimeout( function() {
deleteMessage();
}, 300);
};
var deleteMessage = function() {
$('#msg').remove();
if ($('#notificatosn').find('#msg') > 1) {
displayMessage();
}
};
});
Per the Trix project page the trix-editor emits different events on specific conditions.
The trix-change event is what you need; it fires whenever the editor’s contents has changed.
So, the first line of your JavaScript code could be
$('trix-editor').on('trix-change', function() {
/* Here will be your code to save the editor's contents. */
})

Ajax call will not work without preventDefault

In an MVC page, I have the following jQuery/javascript:
$("form").submit(function (event) {
var inp = $("input"); inp.attr('value', inp.val());
var html = replaceAll(replaceAll($('html')[0].outerHTML, "<", "<"), ">", "<");
// event.preventDefault();
$.ajax({
url: "/Ajax/SetSession",
asynch: false,
dataType: "json",
cache: false,
type: "get",
data: { name: 'html', data: html.substring(0, 1024) },
error: function (xhr, status, error) {
alert("Ouch! " + xhr.responseText);
// $(this).unbind('submit').submit();
},
success: function (data) {
alert("Awesome: " + data);
// $(this).unbind('submit').submit();
},
complete: function (xhr, status) {
alert('Phew!');
$(this).unbind('submit').submit();
}
});
});
It is meant to intercept the normal submit process, capture the html of the page before it's submitted, and then continue on its way as if nothing happened.
But the problem is, with both commented out, the form re-submits, as expected, put the controller never executes the /Ajax/SetSession url. Whereas, if I uncomment them, the /Ajax/SetSession does execute but the unbind does not appear to work as the form does not seem to get resubmitted.
Not sure what's going on here. What am I missing?
Any and all clues appreciated.
event.preventDefault(); should stay uncommented since this prevents form to submit instantly. Apparently you want to control the moment at which form is submitted.
$(this).unbind does not work because inside success and error handles context is no longer form - it is an jQuery ajax context object. You can do two things here to have the behavior you want:
Set context explicitly to be the form object. This can be done via context property:
$.ajax({
...
context: this, //form here!
...
success: function (data) {
alert("Awesome: " + data);
$(this).unbind('submit').submit(); //now this refers to form
},
Refer to form using a different variable:
$("form").submit(function (event) {
var form = this;
...
$.ajax({
...
success: function (data) {
alert("Awesome: " + data);
$(form).unbind('submit').submit(); //using form variable instead of this
},

How to use ajax in mvc?

I am a very beginner to mvc and ajax both.
I have tried many examples on net but I don't understand how ajax is used practically?
I have a controller named members which has GetAllMembers Method.
GetAllMembers returns a List<Members>
Now I want to use JQuery and ajax something like :
$(document).click(function () {
$.ajax({
url: "Members/GetAllMembers",
success: function () {
},
error: function () {
alert("Failed to get the members");
}
});
});
Is my URL right?
Upon success I want to display that List in a ListBox.
How can I get it? Can anyone give me a start?
$.ajax({
type: "POST",
url: "Members/GetAllMembers", //Your required php page
data: "id="+ data, //pass your required data here
success: function(response){ //You obtain the response that you echo from your controller
$('#Listbox').html(response); //The response is being printed inside the Listbox div that should have in your html page.
},
error: function () {
alert("Failed to get the members");
}
});
Hope this will help you.. :)
$(document).click(function () {
$.ajax({
url: "Members/GetAllMembers",
success: function (result) {
// do your code here
},
error: function () {
alert("Failed to get the members");
}
});
});
So your request give response in "result" variable. So you have to easily manage result variable value in foreach loop and set value in ListBox HTML.
Follow this example:
suppose you have this html:
<p>List Box - Single Select<br>
<select id="listBox" name="listbox">
</select>
</p>
So we have this js:
var template = '<option value="$value">$name</option>';
var getAllMembers = function() {
$.ajax({
url: 'Members/GetAllMembers',
dataType: 'json', //Assuming Members/GetAllMembers returns a json
success: function(response) {
$.each(response, function(index){
var option = template.replace(/\$value/g, this.value)
.replace(/\$name/g, this.name);
$('#listBox').append(option);
});
}
});
};
EDIT: Now you only need to call getAllMembers(); function.
Hope this help.
Pablo.

Replace the Ajax.ActionLink by the same functionality with jQuery

With asp.net mvc we can do an ajax call like this:
#{
var ajaxOpts = new AjaxOptions { UpdateTargetId = "main-content", OnBegin = "fctTabLoading", OnComplete = "fctTabLoaded", InsertionMode = InsertionMode.Replace };
}
#Ajax.ActionLink("my link text", "MyAction", "MyController", new { id = Model.RequestID }, ajaxOpts)
Which produce the following html:
<a data-ajax="true" data-ajax-begin="fctTabLoading" data-ajax-complete="fctTabLoaded" data-ajax-mode="replace" data-ajax-update="#main-content" href="/MyController/MyAction/19">my link text</a>
Now I would like to execute the same ajax call but from jQuery and I don't know how to proceed!
I would like something like:
$.ajax({
type: "Post",
url: myURL,
begin: fctTabLoading,
complete: fctTabLoaded,
mode: "replace",
update: "#main-content",
cache: false,
success: function () { alert('success'); }
});
I know the above ajax script won't work because 'mode' and 'update' are not recognized. So I am blocked.
It drives me crazy :(
Why I cannot use the MVC ActionLink? Because I first need to show a jquery dialog to let the user confirm then only do the ajax call in order to refresh a specific div on my page.
Any help is greatly appreciated.
Thanks.
You could start by replacing your Ajax link with a normal link:
#Html.ActionLink(
"my link text", // linkText
"MyAction", // actionName
"MyController", // controllerName
new { id = Model.RequestID }, // routeValues
new { id = "mylink" } // htmlAttributes
)
which will produce the following markup:
my link text
and then in a separate js file unobtrusively AJAXify it:
$(function() {
$('#mylink').click(function() {
$.ajax({
url: this.href,
type: 'POST',
beforeSend: fctTabLoading, // corresponds to your OnBegin callback
complete: fctTabLoaded, // corresponds to your OnComplete callback
success: function(result) {
$('#main-content').html(result);
}
});
return false;
});
});
As you know, the Ajax.ActionLink uses jquery.unobtrusive-ajax.js to execute the ajax links.
If you look at that file, you will see that the event handlers use jquery's live event binder. This binds the event listener to the document object. So, if you wanted to confirm before this event was triggered, you could bind directly to the element like the following:
$('#YOUR_ELEMENT').click(function () {
var confirmed = confirm("CONFIRM_MESSAGE");
if (!confirmed ) {
return false;
}
return true;
});
To use jquery dialog you could do the following:
function confirmDialog () {
$('#YOUR_DIALOG').dialog(
{ buttons: { "Ok": function() { return true; },
{ "Cancel": function() {return false;}
}
});
}
and then you would set confirmed in the previous function to confirmDialog().
***The dialog options may not be exactly what you want, but this should get you going.

Previous ajax request changes the post URL for next form submit

I am making a jQuery ajax request in a asp.net mvc page:
$.ajax({
type: "POST",
url: "/Home/Go",
data: dataObj,
success: function (data) {
// update html here
}
}
});
This call is within a page, which has a form and other elements which submit to other url (lets say "/Home/Do"). Now after the ajax call returns, If I click on any other element the form still submits to url1 instead of url2
Note I tried adding a "return false" statement to click event handler where the ajax call is made. But even this did not help
The ajax call is made within the jQuery dialog:
$('#myDialog').dialog({ buttons:
[
{
text: 'Next',
click: function () { HandleNext(); return false; }
}
],
title: 'Dialog-Title'
});
function HandleNext()
{
$.ajax({
type: "POST",
url: "/Home/Go",
data: dataObj,
success: function (data) {
// update html here
}
}
});
return false;
}
Anybody faced a similar issue? any solutions?
return false in the click handler is mandatory for ALL ajax requests. The web browser will visit the url otherwise. In other words: The ajax request is made first and then a regular request.
No urls can automagically be replaced with other urls. You either do it in your javascript code, or in your action/view.

Resources