How to remove Knockout.js ObservableArray-object after ajax call - ajax

I'm trying to remove an object from an ObservableArray after an ajax-call. It works with the '.pop' function, but not when I'm using the custom knockout.js '.remove'-function.
If I move the call to the '.remove' function outside the ajax-complete function, '.remove' does work. But I would really rather have it inside the '.complete'.
Can anyone spot what I'm doing wrong?
This doesn't work:
self.removeItem = function(data) {
$.ajax({
type: 'POST',
url:'/echo/js/?js=hello%20world!',
dataType: 'json',
contentType: 'application/json',
data: null
}).complete(function (item,data) {
self.Items.remove(data);
});
};
I made a jsfiddle to demonstrate: http://jsfiddle.net/6oe6dn7n/1/
My view-model looks like so:
var data = {
Name: "Test",
Items: ["One", "Two", "Three"]
};
function ViewModel(data) {
var self = this;
self.Items = ko.observableArray(ko.utils.arrayMap(data.Items,
function(item) {
return { value: ko.observable(item) };
}));
self.removeItem = function(data) {
$.ajax({
type: 'POST',
url:'/echo/js/?js=hello%20world!',
dataType: 'json',
contentType: 'application/json',
data: null
}).complete(function (item,data) {
// This doesn't affect the observableArray.
// 'self.Items.pop(data) does, however.
self.Items.remove(data);
});
};
}
And my HTML looks like so:
<div>
<table>
<tbody data-bind="template: { name: 'itemTemplate', foreach: Items }"></tbody>
</table>
</div>
<script type="text/html" id="itemTemplate">
<tr>
<td>
<input data-bind="value: value" />
Remove Item
</td>
</tr>
</script>

You have replaced "data" variable object in the context of response handler:
was:
self.removeItem = function(data) { // <- data
$.ajax({
type: 'POST',
url:'/echo/js/?js=hello%20world!',
dataType: 'json',
contentType: 'application/json',
data: null
}).complete(function (item, data) { // <- another data overrides upper data
// This doesn't affect the observableArray.
// 'self.Items.pop(data) does, however.
self.Items.remove(data); // <- what data to use???
});
};
changed:
self.removeItem = function(data) {
$.ajax({
type: 'POST',
url:'/echo/js/?js=hello%20world!',
dataType: 'json',
contentType: 'application/json',
data: null
}).complete(function (item, data1) { // another data - data1
// This doesn't affect the observableArray.
// 'self.Items.pop(data) does, however.
self.Items.remove(data);
});
};
I've updated the fiddle, it works for me - at least removes items.

You need to use the data variable that is passed into removeItem. Instead you override it, by using the textStatus variable of the complete callback. Like so:
self.removeItem = function(data) {
$.ajax({
type: 'POST',
url:'/echo/js/?js=hello%20world!',
dataType: 'json',
contentType: 'application/json',
data: null
}).complete(function (item) {
self.Items.remove(data);
});
};
The reason self.Items.pop(data) worked is because .pop doesn't actually take any parameters. So the data you passed in is never used, and the call is just popping the array. The second parameter in the complete callback method is by default a textStatus response.
From the documentation:
http://api.jquery.com/jQuery.ajax/
complete
Type: Function( jqXHR jqXHR, String textStatus )
A function to be called when the request finishes (after success and error callbacks are executed). The function gets passed two arguments: The jqXHR (in jQuery 1.4.x, XMLHTTPRequest) object and a string categorizing the status of the request ("success", "notmodified", "nocontent", "error", "timeout", "abort", or "parsererror").

Related

Passing parameter to MVC Action via Ajax always null

I looked at related questions to to form my ajax request but I can't figure out why this isn't working as the param is always null in the acion
I've done a console.log to check that item in 'data: { data: item }' has a value
//action
public async Task<IActionResult> DeleteMedia(string data)
{
$("#mediaTable").on('click', 'td:nth-child(7)', function () {
var item = $(this).parent().attr("id");
$("#MediaToDownload").val(item);
$.ajax({
url: '#Url.Action("DeleteMedia", "Home")',
type: 'get',
cache: false,
processData: false,
contentType: false,
data: { data: item },
success: function (data) {
location.href = data;
}
});
});
You need to send just the string, as JSON:
data: JSON.stringify(item)

Unable to pass selected checkboxes ids to controller method using ajax

I am trying to send a list of ids of checkboxes selected every time the user clicks on a checkbox. This will be used for search results to be filtered by categories. I don’t know if this is the correct way to do it but this is what I have tried so far.
This is my partial view with ajax call:
#using GAPT.Models
#model ViewModelLookUp
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("#selectedcategories").click(function () {
var array = [];
if ($(this).is(":checked")) {
array.push($(this).val());
}
else {
array.pop($(this).val());
}
$.ajax({
type: "POST",
url: '#Url.Action("SearchTours", "Home")',
dataType: "html",
traditional: true,
data: { values: array },
success: function (data) {
$('#selectedcategories').html(data);
}
});
});
});
</script>
#using (Html.BeginForm("SearchCategories", "Home", FormMethod.Post))
{
foreach (var category in Model.categories)
{
<div class="checkbox" id="#{#category.Id}">
<label>
<input type="checkbox" id="selectedcategories" name="selectedcategories" value="#{#category.Id}"/>#category.Name
</label>
</div>
}
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
And this is my controller method that I am trying to reach:
[HttpPost]
public ActionResult SearchTours(FormCollection collection)
{
// insert query here
ViewData["CategAttrTours"] = CategAttrTours;
return View(CategAttrTours);
}
The method in the controller is not being reached and I am getting this error:
Error
Do you have any idea why I keep getting this error? Is it because I am passing the data incorrectly?
I would appreciate any help. Thanks a lot.
You need to add the contentType option and stringify your data
$.ajax({
type: "POST",
url: '#Url.Action("SearchTours", "Home")',
dataType: "html",
contentType: "application/json; charset=utf-8", //add this
data: JSON.stringify({ values: array }), // modify this
data: { values: array },
success: function (data) {
$('#selectedcategories').html(data);
}
});
and change you method to (assumes category.Id is typeof int)
[HttpPost]
public ActionResult SearchTours(IEnumerable<int> values)
although your script to generate the array is unnecessary and you can just use
$.ajax({
type: "POST",
url: '#Url.Action("SearchTours", "Home")',
dataType: "html",
data: $('form').serialize(),
success: function (data) {
$('#selectedcategories').html(data);
}
});
or more simply
$.post('#Url.Action("SearchTours", "Home")', $('form').serialize(), function(data) {
$('#selectedcategories').html(data);
});
and change the method to
[HttpPost]
public ActionResult SearchTours(IEnumerable<int> selectedcategories)
Side note: You should never need to use FormCollection in MVC
remove this
dataType: "html"
traditional: true
on controller method parameter change this
(FormCollection collection)
to
List<string> values
place a break point on the controller and check the values

How do I get JSON result from jquery .ajax call in done()?

I am trying to use the newer .done() syntax for a call to .ajax(), but I don't see how to get the data returned from the server into my .done() function. Here is my code:
function checkLink(element) {
var resultImg = $(element).parent().parent().find("img");
resultImg.attr("src", "/resources/img/ajaxLoad.gif");
$.ajax({
type: 'POST',
url: '/services/Check.asmx/CheckThis',
data: '{somedata: \'' + whatever + '\'}',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: onSuccess,
error: onFailure
}).done(function () { success2(resultImg); });
}
function success2(img) {
img.attr('src', '/resources/img/buttons/check.gif');
}
function onSuccess(data) {
// The response from the function is in the attribute d
if (!data.d) {
alert('failed');
}
else {
alert('hurray!');
}
}
checkLink is called from a simple button push. Both onSuccess() and success2() are firing just fine. But... what I need is the "data" parameter from onSuccess passed to success2... or alternately, be able to pass "resultImg" to onSuccess (although I would prefer using .done instead of the deprecated method). It seems I can either pass my own parameters, or access the JSON result from the AJAX call... but not both. How do I accomplish this?
You can close over the resultImg variable:
function checkLink(element) {
var resultImg = $(element).parent().parent().find("img");
resultImg.attr("src", "/resources/img/ajaxLoad.gif");
$.ajax({
type: 'POST',
url: '/services/Check.asmx/CheckThis',
data: '{somedata: \'' + whatever + '\'}',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: onSuccess,
error: onFailure
}).done(success2);
function success2(data) {
resultImg.attr('src', '/resources/img/buttons/check.gif');
// do whatever with data
}
function onSuccess(data) {
// The response from the function is in the attribute d
if (!data.d) {
alert('failed');
}
else {
alert('hurray!');
}
}
}

How do I get data out of the "data" variable in jQuery and Django

I think it goes a little something like this:
In my view:
from django.core import serializers
And later....
data = serializers.serialize('json', MODEL.objects.filter(id=id), fields=('points'))
return HttpResponse(data)
In my jQuery:
$.ajaxSetup({
dataType: "json"
});
$('#selector .selector_detail a').click(function() {
var call_to = $(this).attr('href');
$.ajax({
url: call_to,
type: "POST",
complete: function() {
console.log('Ajax Complete')
},
success: function(data) {
points = data(fields.points)
console.log('Ajax Successful')
console.log(data);
},
error: function(xhr) {
console.log('Whoops, something went wrong. XHR Response:' + JSON.stringify(xhr));
},
});
return false;
});
I want the value of points, but I have no idea how to get it out. I can see it in the console.log when I look at the data Objects. What am I missing?
if data is a json object and the correct headers are set, you can access it's properties using a dot:
data.points
data[0].points //if points is an array
//this is not correct
data(fields.points);
I don't know what's the exact structure of 'data' but you can derive it from your console.log(data);
EDIt - if data has the structure you outlined in the comment you can access points like this:
alert(data[0].fields.points);
add dataType: 'json' to your .ajax call.
$.ajax({
url: call_to,
dataType: 'json',
type: "POST",
then its jut data.points in your success function, or perhaps data.field.points. I can't tell from your post.

how do you make ajax data key dynamic in jquery?

I'm trying to make my inline edit to be dynamic so it will just depend on some data- attributes from my markup so here's the code for now:
$(".inline-edit").editable(
function(value, settings) {
var editableField = $(this);
$.ajax({
type: 'PUT',
url: editableField.attr('data-href'),
dataType: 'html',
success: function(html) {
editableField.parents('.replaceable').replaceWith(html);
},
data: { 'regression_test_environment[name]' : value }
});
return(value);
},
{
event: 'click',
width: '80%',
height: '20',
submit : 'OK'
}
)
i want the name in regression_test_environment[name] to be editableField.attr('data-column-name') but it always fails in compiling because it keeps taking the key as a string. I tried making a variable after the editable field variable assignment and building the string as a different variable but it doesn't want to evaluate the key as a function.
Is there a way to do this? or am i stuck in creating a separate .editable call for each of my editable fields?
You may try like this:
var name = editableField.data('column-name');
var values = { };
values['regression_test_environment[' + name + ']'] = value;
$.ajax({
type: 'PUT',
url: editableField.data('href'),
dataType: 'html',
data: values,
success: function(html) {
editableField.parents('.replaceable').replaceWith(html);
}
});
Better, less confusing answer:
var data = {};
data[thisField] = $(this).text();
$.ajax({
data: data
});
Best is to pass dynamic values by serializing it :
var data = $('#formid').serialize(); // serialize all the data in the form
$.ajax({
url: 'test.php', // php script to retern json encoded string
data: data, // serialized data to send on server
...
});

Resources