vue 2.3 AJAX data binding not updating - javascript

After a successful ajax call the data rendered on the page is not updating. It is remaining empty / null.
It seems that I am missing how to connect the data returned as a front end variable and the dynamically / live rendered html elements.
Here is the relevant code snippets for context. Is it clear from this what is missing / incorrect?
Javascript
page = new Vue({
el: "#container",
data: {
option_id: null,
option_name: null
},
created:function() {
$.ajax({
type: 'POST',
contentType: 'application/json',
dataType: 'json',
url: 'ajax_methods/get_option',
success: function (ajax_data) {
self = this;
self.option_id = ajax_data.option_id;
self.option_name = ajax_data.option_name;
},
error: function (e) {
console.log(e)
}
})
}
})
HTML
<script type="text/javascript" src="https://unpkg.com/vue#2.3.3"></script>
<div id="container">
<p>{{ option_name }}</p>
<button v-on:click="send_option()"
type="button"
id="left_button"
name="left_button"
v-bind:value="option_id">
</div>
Checking AJAX success
When entering the following in the console, non null values come back as expected:
self.option_id
self.option_name

You need to capture this outside the callback.
created: function(){
const self = this;
$.ajax({
type: 'POST',
contentType: 'application/json',
dataType: 'json',
url: 'ajax_methods/get_option',
success: function (ajax_data) {
self.option_id = ajax_data.option_id;
self.option_name = ajax_data.option_name;
},
error: function (e) {
console.log(e)
}
})
}

first, if that is the exact code, then self I don't think is initialized. Use var self = this or let self = this
But mainly, you need to define self outside of the ajax call. In javascript the this keyword refers to the calling object. directly inside of the created() function, it's the Vue instance. However, this will NOT refer to the Vue instance once inside the ajax callback.
Understand JavaScript’s “this” With Clarity, and Master It
created:function() {
var self = this
$.ajax({
type: 'POST',
contentType: 'application/json',
dataType: 'json',
url: 'ajax_methods/get_option',
success: function (ajax_data) {
self.option_id = ajax_data.option_id;
self.option_name = ajax_data.option_name;
},
error: function (e) {
console.log(e)
}
})
}

Related

Setting global variable inside nested ajax calls

I have a specific requirement with nested ajax calls. I am trying to set a globally accessible variable inside success of one ajax call and this ajax call is being invoked inside success of another ajax call. Eventually the parent success method of parent ajax call utilizes the global variable to perform further operations. The problem is that the value of global variable always remains blank. It works if I make the second ajax request as async:false; but this solution defeats the very purpose of using ajax in the first place.
Let me share a small sample code to illustrate my problem:
//global variables
var xURL = "https://sampleurl.com";
var glblID = "";
//first ajax call
$.ajax({
url: url1,
data: data1,
type: "POST",
contentType: "application/json",
success: function (msg) {
//some js code here
//second ajax call
FetchID();
//more js code here
if(glblID != "")
{
window.location.href = xURL + "?id=" + glblID
}
else
{
window.location.href = xURL;
}
}
});
function FetchID()
{
$.ajax({
url: url2,
data: data2,
type: "POST",
contentType: "application/json",
success: function (data) {
glblID = data.d;
}
});
}
As of jQuery 1.5 implement the Promise interface, giving them all
the properties, methods, and behavior of a Promise
//first ajax call
$.ajax({
url: url1,
data: data1,
type: "POST",
contentType: "application/json"
}).then(function (msg) {
//second ajax call
FetchID().then((data) => {
var glblID = data.d;
if (glblID != "") {
//do something with glblID
} else {
//do something else
}
});
});
function FetchID() {
return $.ajax({
url: url2,
data: data2,
type: "POST",
contentType: "application/json"
});
}

How I do initial JavaScript Ajax initialization?

I'm pulling information with ajax. I want it my document.ready function(ajax) starting first because knockout file starting first and my "var initialData" value going null. How my Ajax start first ?
Here is my F12 Source
My script:
<script type="text/javascript">
var initialData;
function functionViewModel() {
$(document).ready(function () {
$.ajax({
type: "POST",
url: "KnockoutGrid2.aspx/GonderUrunler",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
console.log(msg.d);
initialData = msg.d;
}
});
});
var fn = {
friends: ko.observableArray(initialData)
};
fn.removeUser = function (item) {
fn.friends.remove(item);
};
return fn;
};
ko.applyBindings(functionViewModel());
</script>
Update 2
The answer of #user3297291 is better than mine, because is Knockout who handles all the state of this form. Please, don't do the applybindings in the answer of the ajax request.
The user need to know that the data isn't loaded yet, and this can be handled with knockout.
Original answer
Perhaps if you move the initialization of Knockout inside the success function:
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
type: "POST",
url: "KnockoutGrid2.aspx/GonderUrunler",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
console.log(msg.d);
initialData = msg.d;
// All initialization inside the 'success' function
function functionViewModel(initialData) {
var fn = {
friends: ko.observableArray(initialData)
};
fn.removeUser = function (item) {
fn.friends.remove(item);
};
return fn;
};
ko.applyBindings(functionViewModel(initialData));
}
});
});
</script>
You could show a div with the message: "loading data...".
And when success run, hide this div.
Update 1
After your comment, I don't know why you need the return fn. I propose this solution:
<script type="text/javascript">
// Updating 'functionViewModel()' to add 'self'.
// Move functionViewModel()' outside ajax response
function functionViewModel(initialData) {
var self = this;
self.friends = ko.observableArray(initialData);
self.removeUser = function (item) {
self.friends.remove(item);
};
};
$(document).ready(function () {
$.ajax({
type: "POST",
url: "KnockoutGrid2.aspx/GonderUrunler",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
console.log(msg.d);
initialData = msg.d;
// All initialization inside the 'success' function
ko.applyBindings(functionViewModel(initialData));
}
});
});
</script>
Here I'm using self ( see Managing ‘this’ ) and don't return fn, because Knockout handles its state.
Use async:false in your code
$.ajax({
type: "POST",
url: "KnockoutGrid2.aspx/GonderUrunler",
data: "{}",
async : false,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
console.log(msg.d);
initialData = msg.d;
}
});
You do not want to wait with applyBindings until your ajax response is handled... Your document will look ugly if you let knockout wait with applying bindings and your users will have nothing to look at.
What you should do:
Apply bindings as soon as $(document).ready triggers
Make sure your viewmodels use observable properties that allow you to easily inject data later on
Make sure you define some sort of loading state to show your users the data is being downloaded
I.e.:
function functionViewModel() {
var friends = ko.observableArray([]);
var loading = ko.observable(true);
var removeUser = function(user) {
friends.remove(user);
}
// Get the data and write it to an observable property once done
$.ajax({
type: "POST",
url: "KnockoutGrid2.aspx/GonderUrunler",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
friends(JSON.parse(msg.d));
loading(false);
}
});
return {
friends: friends,
loading: loading,
removeUser: removeUser
};
};
$(document).ready(function() {
ko.applyBindings(functionViewModel());
});

Jquery Ajax success wont firing instead complete event works

I am using Angular Js with JQuery in a noodles way. See my code below.
Code
app.controller('ClassController', function ($scope) {
$scope.ShowHideNoRecords = false;
var credentials = new Object();
credentials.SourceName = "###";
credentials.SourcePassword = "###";
credentials.UserName = "###";
credentials.UserPassword = "##";
credentials.SiteId = [-99];
var locationIds = [1];
var startDate = Date.today();
var endDate = startDate;
var dto = { credentials: credentials, startDate: startDate, endDate: endDate, locationId: locationIds };
$.ajax({
type: "POST",
url: 'MbApiConnector.asmx/GetAllClasses',
data: JSON.stringify(dto),
contentType: "application/json; charset=utf-8",
dataType: "jsonp",
success: function (response) {
alert(response.d);
},
complete: function (msg) {
$scope.$apply(function () {
$scope.Classes = JSON.parse(JSON.parse(msg.responseText).d);
if ($scope.Classes.length > 0) {
$scope.checkin = function (id) {
dto = { credentials: credentials, classId: id };
$.ajax({
type: "POST",
url: 'MbApiConnector.asmx/Checkin',
data: JSON.stringify(dto),
contentType: "application/json; charset=utf-8",
dataType: "jsonp",
complete: function (msg) {
alert(msg.responseText);
}
});
}
}
else {
$scope.ShowHideNoRecords = true;
}
});
}
});
});
Everything is working fine with this code. I knew its a bad idea mixing the two but my app was already developed in Jquery Ajax and we are upgrading with Angular JS but with lesser changes. So I came up with this solution.
Anyways, my issues is that jquery ajax success function is not get called. I am able to receive data from the webservice , but inside the complete method, as you can see in the code above.
Can you explain me why its behaving so?
May be Jquery fails to parse it as the result may not be in JSON format, try to find the error using error callback function. You could try with dataType : 'json'.
error: function (err) { alert(err) }

why doesn't the handlebars template reflect change in ember property

i'm having some trouble with the handlebars template not updating every time the contents of this component's 'subAllocations' change.
it does change the first time the event is triggered ie adding or removing subAllocations, but not after that, even though i can see in the Ember debugger addon for FireFox developer tools that the computed value has changed for 'hasSubAllocations'
App.AllocationAllocationRowComponent = App.CollapsableComponent.extend({
layoutName: 'components/allocation/allocation/row',
tagName: "tr",
hasSubAllocations: Em.computed.notEmpty("allocation.subAllocations"),
updateAllocation: function (data) {
var newAllo = data.allocation;
this.set("allocation.subAllocations", Em.copy(newAllo.subAllocations));
this.sendAction("onRefreshAirSpaces", data.updatedAirSpaces);
},
actions: {
addSubAllocation: function(){
var alloc = this.get("allocation");
var self = this;
Em.$.ajax({
type: 'POST',
url: '/allocation/addSubAllocations',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(alloc),
}).then(function (data) {
self.updateAllocation(data);
});
},
subAllocationRemoved: function (subAllocation) {
var self = this;
Ember.$.ajax({
type: 'POST',
url: '/allocation/RemoveSubAllocation/',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(subAllocation),
}).then(function (data) {
self.updateAllocation(data);
});
},
},
});
from handlebars template
`<span {{bind-attr class="hasSubAllocations:hidden:"}}>content here</span>`
am i missing something?
we are not using ember data, so if you could avoid suggesting that as a solution that would be great

Ajax/PythonBottle/Jquery/JSON trouble passing params

When this AJAX request POSTS, the newUser() function says no arguments are being passed, even though i have the userInput and passInput fields filled out. The JS/JQ/AJAX:
var userInput = document.getElementById('registerUsername');
var passInput = document.getElementById('registerPassword');
var message = document.getElementById('checkUsernameMessage');
$(document).ready(function() {
$('#submitRegisterButton').click(function () {
$.ajax({
type: "POST",
url: "/newUser",
data: JSON.stringify({"username":userInput, "password":passInput}),
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
cache: false,
success: function (msg) {
$('#checkUsernameMessage').text(msg.d);
}
});
});
});
And my python bottle function newUser() :
#post('/newUser')
def newUser(username, password):
etc..
You need to nest your selectors within your dom ready call. Right now they are running before the DOM is ready, and are thus returning undefined. You can verify this by consoling the variables to see if they return any data.
The other thing, is you probably want to select the value of these inputs, and not return the DOM elements themselves: so instead, try
var userInput = document.getElementById('registerUsername').value etc.
$(document).ready(function() {
$('#submitRegisterButton').click(function () {
var userInput = document.getElementById('registerUsername').value;
var passInput = document.getElementById('registerPassword').value;
var message = document.getElementById('checkUsernameMessage').value;
$.ajax({
type: "POST",
url: "/newUser",
data: JSON.stringify({"username":userInput, "password":passInput}),
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
cache: false,
success: function (msg) {
$('#checkUsernameMessage').text(msg.d);
}
});
});
});
This should fix your issue.
With the clientside issue fixed, the python issue was:
The post request was being called as: def newUser( username, password ) where there should have been no arguments passed in, but derived from the form variable:
def newUser():
username = request.forms.get('userInput')
password = request.forms.get('passInput')
message = request.forms.get('message')

Categories

Resources