I'm trying to access the variable np defined from within a function block; however, I am running into some issues when I call this.items.push(plumbers). I get TypeError: Cannot call method push of undefined
myApp.factory('np', function($resource, nearbyPlumbers){
var np = function(){
this.items = [];
this.busy = false;
this.limit = 5;
this.offset = 0;
};
np.prototype.nextPage = function(){
if (this.busy) return;
this.busy = true;
var temp;
nearbyPlumbers.nearby({lat: -37.746129599999996, lng: 144.9119861}, function(data){
angular.forEach(data, function(plumber){
alert('yay');
//this.items.push(plumber);
console.log(plumber);
console.log(this.items); // <--- This wont work. How do I access this.items
});
});
};
return np;
});
np.prototype.nextPage = function () {
if (this.busy) return;
this.busy = true;
var temp;
var that = this; // add this line
nearbyPlumbers.nearby({
lat: -37.746129599999996,
lng: 144.9119861
}, function (data) {
angular.forEach(data, function (plumber) {
that.items.push(plumber); //access using "that"
console.log(plumber);
console.log(that.items);
});
});
};
I'm really curious why you're using this, since it's going to be a different this depending on what scope accessing the singleton from. That would explain the error that you're getting.
I would strongly suggest reading up on factories in Angular and then taking another look at the code. The services docs are a good place to start and this question is good as well.
Related
var generateSearchObject = function() {
var searchObj = {
/*value assigned to variable "check" should be here like "fileName":check*/
};
return searchObj;
};
var s = {
renderBreadCrumbs: function(breadCrumbs, state, node) {
$(breadCrumbs).each(function(index, value) {
//var check = "Something";
});
//return check
}
}
I tried my best to resolve this issue and reaching out to Community. I would like to access the variable which is there in $(breadCrumbs) in searchObj. Thank you.
I have the function inside service in angular module but how do I run the service on page load. I am not using any controller here
Code:
var app = angular.module("myTmoApppdl", [])
.service('populatePageObjsService', function () {
var self = this;
//digitalData is a global object
self.populatePage = function (digitalData) {
var dataPageObject = document.getElementById('metaJson').getAttribute("data-pageObject");
var jsonPageObject = JSON.parse(dataPageObject);
for (var key in jsonPageObject.page.pageInfo) {
var value = jsonPageObject.page.pageInfo[key];
if (digitalData.page.pageInfo.hasOwnProperty(key)) {
digitalData.page.pageInfo[key] = value;
}
}
console.log("Page data populated successfully: ", digitalData.page.pageInfo);
}();
});
I tried using the () after function but it didn't execute the function
Update:
var app = angular.module("myTmoApppdl", []).run(function () {
app.service('populatePageObjsService', function () {
var self = this;
self.populatePage = function (digitalData) {
var dataPageObject = document.getElementById('metaJson').getAttribute("data-pageObject");
var jsonPageObject = JSON.parse(dataPageObject);
for (var key in jsonPageObject.page.pageInfo) {
var value = jsonPageObject.page.pageInfo[key];
if (digitalData.page.pageInfo.hasOwnProperty(key)) {
digitalData.page.pageInfo[key] = value;
}
}
console.log("Page data populated successfully: ", digitalData.page.pageInfo);
};
});
});
You can call your service method in .run() block
var app = angular.module("myTmoApppdl", []);
app.run(function(populatePageObjsService){ // inject your service here
//use your service here
});
app.service('populatePageObjsService', function() {
// your service code here
});
With run module
Simple example
var app = angular.module("myTmoApppdl", [])
.run(function(populatePageObjsService) {
populatePageObjsService.init();
})
.service('populatePageObjsService', function() {
var self = this;
self.init = function() {
alert("run");
};
});
Plunker
Since an AngularJS service is singleton, you can be sure that your function will only be executed once, but you have to bear in mind that it is also lazily instantiated - Angular only instantiates a service when an application component depends on it - source.
With this in mind, if a service is somehow self-reliable (for example, fetching the user's country via an API call - since this can be executed only once at the start of the app and it's unlikely for the data to change), besides the usual service bindings, you can also put logic in there.
I've edited your code to showcase this approach.
angular
.module("myTmoApppdl", [])
// populatePageObjsService needs to be injected somewhere otherwise it won't get instantiated
.service('populatePageObjsService', function() {
//////////////
// Bindings //
//////////////
var self = this;
//digitalData is a global object
self.populatePage = function(digitalData) {
var dataPageObject = document.getElementById('metaJson').getAttribute("data-pageObject");
var jsonPageObject = JSON.parse(dataPageObject);
for (var key in jsonPageObject.page.pageInfo) {
var value = jsonPageObject.page.pageInfo[key];
if (digitalData.page.pageInfo.hasOwnProperty(key)) {
digitalData.page.pageInfo[key] = value;
}
}
console.log("Page data populated successfully: ", digitalData.page.pageInfo);
};
///////////////
// Run Block //
///////////////
// Calling the desired function.
self.populatePage(digitalData);
});
angular.element(document).ready(function () {
// your code here
});
I'm learning how to actually use JavaScript. I've run into a situation where I'm getting an error. The error is: TypeError: 'undefined' is not an object (evaluating 'this.flagged'). I've narrowed down my code to where its happening. My code looks like this:
var flagged = false;
var intervals = [];
return {
flagged: flagged,
intervals: intervals,
createInterval : function (options) {
var defer = $q.defer();
if (this.throwsError) {
defer.reject('There was an error creating the interval.');
} else {
this.intervals.push(
$interval(function() {
console.log('here 1');
console.log(this.flagged);
},
1000
));
}
}
};
The error gets thrown at the: console.log(this.flagged); I'm guessing it has to do with the fact that "this" isn't visible. Yet, if "this" isn't visible, I'm not sure how to get the value for flagged. Can someone please explain to me what I need to do to get the value for flagged?
Thank you!
When you are using this inside $interval it won't be pointing to your original object, however, you can do this:
var flagged = false;
var intervals = [];
return {
flagged: flagged,
intervals: intervals,
createInterval : function (options) {
var defer = $q.defer(),
self = this;
if (this.throwsError) {
defer.reject('There was an error creating the interval.');
} else {
this.intervals.push(
$interval(function() {
console.log('here 1');
console.log(self.flagged);
},
1000
));
}
}
};
notice var self = this;
In JavaScript,
var flagged
will be a scoped variable, i think what you need here is a global scope variable for that, simply remove var from behind it.
flagged = false;
that should do the trick.
Just getting into javascript and knockout.js. I've found a bunch of examples of what I'm trying to accomplish. And I feel like there is a small syntax error I may be overlooking. I'm trying to filter a set already returned (this.tasks) from a server via ajax/json. I have that working fine. What I would like to do, is have users be able to switch between complete and incomplete tasks.
I switched the code to just run the foreach loop on tasksFiltered. "this.done" is either true or false.
Task template
var taskModel = function(id, title, description, done){
var self = this;
this.id = ko.observable(id);
this.title = ko.observable(title);
this.description = ko.observable(description);
this.done = ko.observable(done);
this.showEdit = ko.observable(false);
this.titleUpdate = ko.observable(false);
this.descriptionUpdate = ko.observable(false);
};
Page Model
var pageModelTasks = function(){
var self = this;
this.task_title = ko.observable("");
this.task_description = ko.observable("");
this.task_title_focus = ko.observable(true);
this.tasks = ko.observableArray([]);
this.tasksFiltered = ko.computed(function() {
return ko.utils.arrayFilter(this.tasks, function(Task) {
return Task.done == true;
});
});
// CRUD functions excluded
};
this doesn't work.
Two minor corrections to your code. First, as #XGreen mentioned, you need to pass the array value, not the observableArray instance, as the first parameter of the arrayFilter function. Lastly, because Task.done is observable, you need to invoke the member to get the value. Here's the modified code:
this.tasksFiltered = ko.computed(function() {
return ko.utils.arrayFilter(this.tasks(), function(Task) {
return Task.done() === true;
});
});
The second solution has a problem with the method ko.utils.stringStartsWith.
ko.utils.stringStartsWith missing in release file.
You can use this code:
var stringStartsWith = function (string, startsWith) {
string = string || "";
if (startsWith.length > string.length)
return false;
return string.substring(0, startsWith.length) === startsWith;
};
See Issue Link
It might help you
if (myList().length > 0) {
var text= this.filter().toLowerCase();
return ko.utils.arrayFilter(myList(), function (item) {
if (item.Label.toLowerCase().indexOf(text) > -1 || item.Desc.toLowerCase().indexOf(text) > -1) {
return true;
}
else {
return false;
}
});
}
I am having an issue getting an Ajax Response to be used within an Object.
function cart(){
this.items = [];
this.addItem = function(item){
//sorts and adds items to this.items
}
this.retrieveCart = function(){
var itemArray = JSON.parse($.cookie('cartItems'));
var itemNumbers = [];
var outData = [];
for(var i in itemArray){
itemNumbers.push(i);
}
$.post('beta-category-ajax.html', {'get' : itemNumbers.join(",")},
function(data){
for(var i in data){
var currentItemNumber = data[i].I;
var quantity = itemArray[currentItemNumber];
data[i].Quantity = quantity;
outData.push(data[i]);
}
});
this.addItem(outData);
}
I want to be able to run the this.addItem(Array) while still using Ajax asynchronously
I saw this thread jQuery AJAX Handling Problem but I am not if this applies to me.
Thank you all for the help ahead of time :)
I'm not entirely clear on what you are asking, but it appears that this.addItem wouldn't work the way the code is currently written. The value of this changes in the scope of the anonymous function you're passing to $.post. Cache a reference to this in retrieveCart.
this.retrieveCart = function () {
var self = this;
...
$.post(..., function () {
...
self.addItem(outData);
});
}