So I have this Javascript object :
var obj = {
conn : null,
first : function(thisIdentity) {
"use strict";
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
this.conn = new Connection(data.user_id, "127.0.0.1:80");
}
});
},
second : function(thisIdentity) {
"use strict";
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
// using this.conn now results in UNDEFINED
}
});
}
};
Now basically value is assigned to conn variable in AJAX call of first function but when I try to use the same value in second function then it states this.conn is undefined. I just want to know how to assign value to the object's property and keep it preserved for future use? Thanks!
In the ajax success callback the this refers to a different scope than the original object.
Change you code to this:
var obj = {
conn : null,
first : function(thisIdentity) {
"use strict";
var mySelf = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
mySelf.conn = new Connection(data.user_id, "127.0.0.1:80");
}
});
},
second : function(thisIdentity) {
"use strict";
var mySelf = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
// now you can access the connection with mySelf.conn
}
});
}
};
The syntax itself is wrong. You are creating a variable or giving an expression inside an object literal. Remember this is not a function, but instead, it should be:
$.ajax ({
// computation and in success function
conn: new Connection(data.user_id, "127.0.0.1:80")
});
Updated
When you are giving such a way of definition:
success : function() {
this.conn = new Connection(data.user_id, "127.0.0.1:80");
}
Here, the this object refers to the success function and not your object. Read Understanding Scope and Context in JavaScript. Now you need to create a proxy variable for this and use it:
first : function(thisIdentity) {
"use strict";
var myObj = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
myObj.conn = new Connection(data.user_id, "127.0.0.1:80");
}
});
},
Related
I have this object:
var crudConfig = function($wizard, $formModal, $deleteModal) {
'use strict';
return {
handleOnShowFormModal : function() {
$formModal.on('show.bs.modal', function(event) {
...................
this.fillForms(data);
....................
});
return this;
},
fillForms : function(data) {
//do stuff
return this;
}
}
}
The problem appears when I call the fillForms with the param.
Uncaught TypeError: this.fillForms is not a function
As the fillForms key is an anonymous function how can I call it from inside the object? On other relative questions I only found how to refer itself if the key has a string value and the I call like this: this.fillForms .
this within the callback references the $formModal element. What you need to do is store this that refer to the object in a variable before the event listener is called and use the variable within the callback to access the object.
Just like this:
handleOnShowFormModal : function() {
var _this = this
$formModal.on('show.bs.modal', function(event) {
_this.fillForms(data);
});
return this;
},
var obj = {
conn : null,
first : function(thisIdentity) {
"use strict";
var myObj = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
myObj.conn = new Connection(data.user_id, "127.0.0.1:80");
sessionStorage.setItem('connection', JSON.stringify(myObj.conn));
}
});
},
second : function(thisIdentity) {
"use strict";
var myObj = this;
var conntn = sessionStorage.getItem('connection');
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function() {
var parsedConnection = JSON.parse(conntn);
parsedConnection.sendMsg(data.id, data.nid);
}
});
}
};
var Connection = (function() {
function Connection(uid, url) {
this.uid = uid;
this.open = false;
this.socket = new WebSocket("ws://"+url);
this.setupConnectionEvents();
},
sendMsg : function(id, nid) {
alert("Working");
},
// other functions
})();
Now basically an object is assigned to conn variable in AJAX callback function of first function and I am storing the object via sessionStorage and retrieving the object in the second function and using it in the AJAX callback but when I call the method via parsedConnection.sendMsg(data.id, data.nid); it is throwing an error that
TypeError: parsedConnection.sendMsg is not a function
I did use console.log(parsedConnection); and it shows that object is there with proper values. I just want to know how to retrieve the object and call the method on it in AJAX callback function of second. Thanks!
I have simple situation and can't understand why variable that I pass to function always undefined.
var ProjectItemView = Backbone.Marionette.ItemView.extend({
template: "#ProjectItemTemplate",
initialize: function () {
var id = this.model.get('project_id');
$.getJSON('service/api.php/projects/' + id + '/progress').done(function (data) {
this.renderProgress('4'); //<== pass here
});
},
renderProgress: function (why) {
alert(why); //<== undefined
...
},
...
});
I expect that it equals '4'. In next step I want to pass "data" but now I realize that I can't pass anything.
Since you're invoking renderProgress on the return of $.getJSON you can simply provide the function reference to the done()method of the returned jQuery Promise. Your code would look like this:
var ProjectItemView = Backbone.Marionette.ItemView.extend({
template: "#ProjectItemTemplate",
initialize: function () {
var id = this.model.get('project_id');
$.getJSON('service/api.php/projects/' + id + '/progress')
.done(this.renderProgress);
},
renderProgress: function (data) {
alert(data);
...
},
...
});
If you'll need the view context inside renderProgress (like, for example, to refer to a view property), then provide done() a version of renderProgress that's bound to the view context:
$.getJSON('service/api.php/projects/' + id + '/progress')
.done(_.bind(this.renderProgress, this));
where _.bind is an UnderscoreJS function. Read more about it here.
You loose the context in $.getJSON done callback. Try this:
var ProjectItemView = Backbone.Marionette.ItemView.extend({
template: "#ProjectItemTemplate",
initialize: function () {
var id = this.model.get('project_id');
var _this = this;
$.getJSON('service/api.php/projects/' + id + '/progress').done(function (data) {
_this.renderProgress('4'); //<== pass here
});
},
renderProgress: function (why) {
alert(why); //<== undefined
...
},
...
});
You don't have access to this inside " $.getJSON( " assign this to any variable and then call "renderProgress" method.
var currentObj = this;
$.getJSON('service/api.php/projects/' + id + '/progress').done(function (data) {
currentObj .renderProgress('4'); //<== pass here
});
because in your case this points to current object of that function and not to view object.
trying to get my head around objects, methods, closures, etc... in Javascript.
Can't see why this isn't working, some fundamental flaw in my thinking I guess. I'm expecting the val variable to be passed through to the addNote() function but it isn't. I thought that any variables declared outside of a function are available to that function, as long as they're not within another function. Is that not correct?
if(typeof(Storage) !== "undefined") {
console.log(localStorage);
var $input = $('#input'),
$submit = $('#submit'),
$list = $('#list'),
val = $input.val();
var noteApp = {
addNote : function(val) {
var item = val.wrap('<li />');
item.appendTo($list);
clearField();
},
clearField : function() {
$input.val = '';
},
delNote : function(note) {
}
};
$submit.on('click', function(){
noteApp.addNote();
});
} else {
}
I'm trying to learn how the pros manage to get their code so clean, concise and modular. I figured a note app would be a perfect start, shame I got stuck at the first hurdle...
Cheers.
There are several issues with the code in the question
defining an argument named val and not passing an argument to the function
when calling clearField() inside the object literal it's this.clearField()
You're only getting the value once, not on every click
val is a string, it has no wrap method
$input.val = ''; is not valid jQuery
I would clean it up like this
var noteApp = {
init: function() {
if (this.hasStorage) {
this.elements().events();
}
},
elements: function() {
this.input = $('#input');
this.submit = $('#submit');
this.list = $('#list');
return this;
},
events: function() {
var self = this;
this.submit.on('click', function(){
self.addNote();
});
},
hasStorage: (function() {
return typeof(Storage) !== "undefined";
})(),
addNote: function() {
this.list.append('<li>' + this.input.val() + '</li>');
this.clearField();
return this;
},
clearField: function() {
this.input.val('');
},
delNote : function(note) {
}
}
FIDDLE
Remember to call the init method
$(function() { noteApp.init(); });
In your call to addNote(), you don't pass any argument for the val, so it will be undefined:
noteApp.addNote();
// ^^ nothing
Pass the input (seems you want the jQuery object not the string value because of your val.wrap call):
noteApp.addNote($input);
When you declare the val in the function, it is scoped to that function and will only be populated if the function call passes a value for that argument. Even if you have another variable in an upper scope with the same name val, they are still differentiated. Any reference to val in the function will refer to the local val not the upper scope.
I have a javascript class declared as shown below.. My problem is the aonymous function does not see the scope of the class. I can not reference the bb_obj from within the ajax call load callback..
Is there a way to do this?
Thanks in advance..
dojo.declare("sop.quote", null,
{
bb_obj : new Object,
stage1 : function()
{
dojo.xhrPost(
{
url : 'go/module_service/transport.php',
content : this.bb_obj,
handleAs : 'xml',
load : function(xml)
{
var status = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue;
this.bb_obj.message = message;
},
error : function()
{
}
}
}
}
this inside a XHR callback function refers to the XHR object. The only way to refer to bb_obj is by directly referring to the created object, in the same scope as the function. Because objects are passed by reference, the code below works as intended.
Note to avoid confusion, I've declared the object using var bb_obj_obj={}. The bb_obj property refers to bb_obj_obj:
bb_obj_obj.message is changed
bb_obj points to bb_obj_obj, hence bb_obj.message refers to the same variable
Code:
var bb_obj_obj = {}; //new Object
dojo.declare("sop.quote", null,
{
bb_obj : bb_obj_obj,
stage1 : function()
{
dojo.xhrPost(
{
url : 'go/module_service/transport.php',
content : this.bb_obj,
handleAs : 'xml',
load : function(xml)
{
var status = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue;
bb_obj_obj.message = message; //Without `this`
},
error : function()
{
}
}
}
}
An alternative method consists of saving this in a variable, eg. $this:
...
stage1 : function()
{
var $this = this;
dojo.xhrPost({
...
load : function(xml){
var status = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue;
$this.bb_obj.message = message; //Using `$this` instead of `this`
},
...
The typical Javascript practice, in this case, is to wrap the whole thing in an an unnamed function. All local variables of this function will be accessible to every object/function declared therein. By immediately calling this unnamed function you make sure the code inside the function gets executed.
(function() {
var bb_obj = {}
dojo.declare("sop.quote", null, {
stage1 : function()
{
dojo.xhrPost(
{
url : 'go/module_service/transport.php',
content : this.bb_obj,
handleAs : 'xml',
load : function(xml)
{
var status = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue;
bb_obj.message = message;
},
error : function()
{
}
}
}
})()