I'm trying to bind the AJAX callback function to a certain scope, what am I doing wrong?
here is my code:
var MainApp = {
files:{
"A":{
url:"files/a.json",
content:""
},
"B":{
url:"files/b.json",
content:""
}
},
init:function () {
this.loadFiles();
},
loadFiles:function () {
for (var i in this.files) {
var f = function (data) {
console.log("callback",this);
};
console.log("binding",this);
f.bind(this);
$.get(this.files[i].url, f);
}
}
};
$(function () {
MainApp.init();
});
f.bind(this);
Function#bind doesn't alter the original function, it returns a new function bound to the parameter. You probably meant:
f= f.bind(this);
Try using call:
that = this;
$.get(this.files[i].url, function() {
f.call(that)
});
Related
Following is my javaScript code.
var myObjfn = {
before : function(){
console.log("before");
},
loadA: function(){
console.log("loadA");
},
loadB: function(){
console.log("loadB");
},
loadC: function(){
console.log("loadC");
}
}
Whenever I call myObjfn.loadA(), it should call myObjfn.before() method before executing loadA method. Same for loadB() & loadC(). I don't want to explicitly call before() method in all loadA,loadB and loadC methods. Is there any option to achive this in javascript ?
You could do something like this. Which creates a wrapper function for each function in the object except the before function.
var myObjfn = { ... };
Object.keys(myObjfn).forEach(key => {
if (key === "before") return;
var oldFunc = myObjfn[key];
myObjfn[key] = function() {
myObjfn.before();
return oldFunc.apply(this, arguments);
};
});
myObjfn.loadA();
// "before"
// "loadA"
Inside my attemptSearch function, I use jQuery $.post to get some JSON results. I'm getting the error
Undefined is not an object
on the call
this.getSearchResults.bind(this)
I have the same set up in another web app and I don't get this error. What am I doing wrong?
var app = {
init: function() {
this.cacheDom();
this.bindEvents();
},
cacheDom: function() {
this.$search = $('#search');
},
bindEvents: function() {
this.$search.keyup(this.attemptSearch)
},
searchResults : [],
getSearchResults : function(val){
var currentSearchResult = val.query.search;
for (var i = 0; i < currentSearchResult.length; i++) {
var result = {
title: currentSearchResult[i].title,
}
console.log(this.searchResults);
this.searchResults.push(result);
}
},
attemptSearch: function(event) {
var wiki = "https://crossorigin.me/https://en.wikipedia.org/w/api.php?action=query&list=search&format=json&srsearch=";
if (event.keyCode == 13) {
$.post((wiki + $('#search').val()), this.getSearchResults.bind(this))
}
},
};
app.init();
You made sure to bind getSearchResults, but you didn't bind attemptSearch. That's almost surely the issue:
this.$search.keyup(this.attemptSearch.bind(this))
I have this object:
var Point = {
step: function () {
alert("hello");
}
};
This works:Point.step();.
How to make it work with the [ ] notation? Meaning Point["property_name"].
It is Point["step"]();. Here is the snippet:
var Point = {
step: function () {
alert("hello");
}
};
Point["step"]();
The Problem
I am picking up Typescript and just learned that lambda functions are used to (edit) set the value of this. However, I'm not sure how to pass my view model's this into a function that calls another method that I have not defined. In my case, I'm trying to call a Knockout method. See example:
Desired JavaScript:
var MyViewModel = (function () {
function MyViewModel() {
var _this = this;
...
this.someMethod = function () {
ko.utils.arrayForEach(this.array1(), function (item) {
while (item.array2().length < _this.array3.length) {
item.array2.push(12345);
}
});
};
...
Actual JavaScript:
var MyViewModel = (function () {
function MyViewModel() {
var _this = this;
...
this.someMethod = function () {
ko.utils.arrayForEach(_this.array1(), function (item) {
while (item.array2().length < this.array3.length) {
item.array2.push(12345);
}
});
};
...
TypeScript:
method = () => {
ko.utils.arrayForEach(this.array1(), function(item){
while(item.array2().length < this.array3().length){
item.array2.push(0);
}
})
}
One Solution...
One solution I've used was to manually set this.array3().length to _this.array3.length(), but that's pretty hacky and I do not like it.
How should I go about passing the right this into my inner function?
You need to use another lambda to continue the chain of this :
method = () => {
ko.utils.arrayForEach(this.array1(), (item) => { // NOTE here
while(item.array2().length < this.array3().length){
item.array2.push(0);
}
})
}
Tips on this in TypeScript : https://www.youtube.com/watch?v=tvocUcbCupA&hd=1
In a page I create an instance of a class (MyClass), this class has 2 methods. But I'd like to do 2 things :
In (1), set the value this.message
In (2), call the information method or another method of the class
Thank,
<script type="text/javascript">
$(document).ready(function () {
var myClass = new MyClass("MyParam");
$('#Target').click(function (event) {
myClass.save("Test");
});
});
</script>
function MyClass(myParam) {
this.myParam = myParam;
this.isError = false;
this.message = "";
}
// Define the class methods.
MyClass.prototype = {
save: function (action) {
**(2)**
},
information: function (action) {
**(1)**
}
};
Update1
When I execute the code below the data value in information is show as undifined
MyClass.prototype = {
click: function (action) {
var myData;
$.post(....., $("form").serialize(),
function (data) {
myData = data;
});
this.isError = this.information(myData);
},
information: function (data) {
alert(data);
return true;
}
};
Inside the save and information functions, this should be the current MyClass object.
So, inside save, this.message should work, and inside information, this.save() should work.
UPDATE:
click: function (action) {
var myData;
$.post(....., $("form").serialize(),
function (data) {
myData = data;
});
this.isError = this.information(myData);
}
$.post is an AJAX request and is ran asynchronously. Meaning that this.isError = this.information(myData); is ran before it finishes, therefore myData is undefined. You need to call this.information from inside the callback.
Inside the callback, this will no longer be your MyClass object, so we need to save a reference to it. Like this:
click: function (action) {
var that = this;
$.post(....., $("form").serialize(),
function (data) {
that.isError = that.information(data);
});
}