So I am having this weird issue where angular.extend is evaluating my parameterless functions. My userData factory is extended from my applicationUserData, but the end result is that my userData object in the userData factory has actual values for needsTraining and showWelcomeText instead of them being functions. The setUserData(appbaseUserData) function still shows up as a function. Any idea why this is?
application.factory('applicationUserData', [function(){
var userData;
return {
setUserData: function(appbaseUserData){
userData = appbaseUserData;
},
needsTraining: function(){
userData.ensureUserDataInitialized();
return userData.needsTraining;
},
showWelcomeText: function(){
userData.ensureUserDataInitialized();
return userData.showWelcomeText;
}
}
}]);
appBaseModule.factory("userData", ["applicationUserData", function(applicationUserData) {
var userData = {},
userDataInitialized = false;
userData.init = function(data) {
applicationUserData.setUserData(userData);
angular.extend(userData, applicationUserData, data);
userDataInitialized = true;
};
....
return userData;
}]);
It's probably not extend that's doing this.
Here is the source for that method in GitHub
function extend(dst) {
var h = dst.$$hashKey;
forEach(arguments, function(obj){
if (obj !== dst) {
forEach(obj, function(value, key){
dst[key] = value;
});
}
});
setHashKey(dst,h);
return dst;
}
What's in data at the time you're calling it? it's possible that it has some value that it's putting in that overwrites your function.
Either way, it's not extend itself. That's a pretty simple function.
Related
I know some javascript function declarations. Like exression function, anonymous function, but I do not understand what kind of syntax of these two functions? Can anybody tell me what is the name of these two functions? I mean "manipulateData: function (input)" and "getDataById: function (id)".
Why return statement can have this syntax to return two functions? Why not return one function in one time instead of two functions? It will be great if you can give me some reference documents? Thanks.
app.service('MyService', function ($http, $q, $angularCacheFactory) {
var _dataCache = $angularCacheFactory('dataCache', {
maxAge: 3600000 // items expire after an hour
});
/**
* #class MyService
*/
return {
manipulateData: function (input) {
var output;
// do something with the data
return output;
},
getDataById: function (id) {
var deferred = $q.defer();
if (_dataCache.get(id)) {
deferred.resolve(_dataCache.get(id));
} else {
// Get the data from the server and populate cache
}
return deferred.promise;
}
};
});
These functions are just anonymous functions that happen to be values in an object. Consider this:
var object = {
add: function(x, y) {
return x + y;
}
};
object.add(1, 2); // = 3
This is the same as:
function addFunction(x, y) {
return x + y;
}
var object = {
add: addFunction
};
object.add(1, 2); // = 3
There's nothing special about these functions, as they're just normal properties of an object.
You are not returning a function in this case but an Object.
When you define a service in angularjs you have to provide its implementation in the callback (the second argument of app.service)
This callback has to return methods you want to make available to other parts of your application.
Then in a controller or in another service you will be able to write:
app.controller("MyCtrl", ["MyService", function(MyService) {
MyService.getDataById('an id');
}]);
Angular Service returns an instance of the service you bind to the app namespace, those functions in the return statement are public methods that can be worked with. Basically an Object that contains two methods manipulateData, and getDataById.
It's similar to this
function company() {
let product; // This is private
// Public Methods
return {
setLatestProduct: function(value) {
product = value;
console.log(product, ' set');
},
getLatestProduct: function() {
return product;
}
}
}
const apple = company();
console.log(apple); // { setLatestProduct: function, getLatestProduct: function }
I have this method:
wordFormDirty = (): boolean => {
var self = this;
angular.forEach(self.word.wordForms, function (wf, key) {
var wordFormNgForm = 'wordFormNgForm_' + wf.wordFormId
if (!self[wordFormNgForm].$pristine) {
return true;
}
});
return false;
};
From what I see this never returns true. Can someone give me advice as to how I can implement this so that a form that's not pristine will make the wordFormDirty() method return true.
can you try this, in this case, if I've undestand the issue, the first time there is a value true the result is set to true otherwise it remains false
wordFormDirty = (): boolean => {
var self = this;
var result = false;
angular.forEach(self.word.wordForms, function (wf, key) {
var wordFormNgForm = 'wordFormNgForm_' + wf.wordFormId
if (!self[wordFormNgForm].$pristine) {
result = true;
}
});
return result;
};
If you wish to get a result directly from walking the Array, consider using other methods than forEach. E.g.:
return Object.values(this.word.wordForms).some(
({ wordFormId }) => !this[`wordFormNgForm_${wordFormId}`].$pristine
);
I need to return an object of methods after making a call to the IndexedDB library like so.
.factory('presentationData', ['$indexedDB', 'uuid4','$q', function ($indexedDB, uuid4, $q) {
var objectStore = $indexedDB.openStore('presentations', function(store) {
return store;
});
return objectStore.then(function(objectStore) {
var functions = getDefaultDataServiceFunctions(objectStore);
functions.getAll = function (includeFlaggedForDelete) {
if (includeFlaggedForDelete) {
return objectStore.getAll();
}
return objectStore.getAll().then(function (presentations) {
return presentations.filter(function (p) {
return !(p.meta && p.meta.localStatus === 'deleted');
});
});
};
functions.getWithLocalStatus = function (status) {
var query = $indexedDB.queryBuilder().$index('localStatus').$eq(status).compile();
return objectStore.each(query);
};
return functions;
})
}])
Why does this not return an object of methods? I don't understand!!
Using this: https://github.com/bramski/angular-indexedDB
Thanks!
This is not going to work as returning the store object is ineffective. The store will be closed and operations on it will fail.
It's really unclear to me what you are actually trying to do. Just get the data? You need to return a promise which will return the data.
.service('dataFetcher', ['$indexedDB', 'uuid4','$q', function ($indexedDB, uuid4, $q) {
this.getData = function() {
promise = $q.defer();
$indexedDB.openStore('presentations', function (store) {
... do what is needed to get the answer here...
promise.resolve(data);
}
return promise.promise;
}
}
Using this service then goes something like...
.controller('MyControl', ['dataFetcher', function ($scope, dataFetcher) {
dataFetcher.getData().then( function (data) {
$scope.data = data;
});
}];
That will give you what you in fact seek. indexed-DB works on a callback mechanism. You need to use that to design your data service in a sensible way.
I'm creating a json object as the response in a node.js service; and some of its fields are calculated asynchronously and wrapped in promises.
Is there any elegant way to compose a promise that is resolved when all the attributes are resolved? (rather than doing an all on the values explicitly and replacing them).
So instead of doing something like:
function calculateResponse() {
var obj = {
a : somePromise(),
b : someOtherPromise()
};
return q.all([obj.a, obj.b]).then(function(results) {
obj.a = results[0];
obj.b = results[1];
return obj;
});
}
It'd be good to have something like:
function calculateResponse() {
var obj = {
a : somePromise(),
b : someOtherPromise()
};
return q.allFields(obj);
}
This is how I am doing it now, just in case nobody comes out with a better solution:
var allAttributesResolved = function(obj) {
var pairs = _(obj).pairs().unzip().value();
var keys = pairs[0];
var values = pairs[1];
return q.all(values).then(function(results) {
return _.zipObject(keys, results);
});
};
If using bluebird rather than q there is a method called props that does just the same.
I am trying to achieve a chainable object, but cannot figure out how I can do this within a function.
This is how I would like it to work:
$donate.ga('testing').go(value);
My object currently looks like this:
var $donate = {
ga: function (value) {
}
};
You simply need to make each function to return the instance of the object:
var $donate = {
ga: function (value) {
// logic
return this;
}
};
It's already solved here. You must simply return the object in your function.
You need to return the Object like that:
var $donate = {
ga: function (value) {
//after some computation
return this;
},
go: function(val) {
//after some computation
return this;
}
};
If you don't return this (this is a reference to the current Object), you either return undefined or something else and your method defined in your Object is simply out of scope (unknown).
you have to return this; in each sub function before closing it.
for example
Your code
var $donate = {
ga: function (value) {
//perform your code here
return this; // <--- Dont forget to use this before closing the function nest
},
go: function(val) {
//perform your code here
return this; // <--- Dont forget to use this before closing the function nest
}
};