I need to remake this functoin 'i18n' to a factory but so i return a value instead of just setting it with this.
Thanks in advance!
services.service('i18n', function() {
var self = this;
this.setLanguage = function(language) {
$.i18n.properties({
name: 'messages',
path: 'i18n/',
mode: 'map',
language: language,
callback: function() {
self.language = language;
}
});
};
this.setLanguage('nl');
});
Try to set up your service like this:
myApp.service('LangService', function() {
var setLang = function(lang) {
// return whatever you want
}
return {
setLang: setLang
};
});
Then you can call your method setLang from anywhere:
LangService.setLang('nl');
Related
I have a factory like this:
TestFactory= function () {
var objectName=null;
return {
SetName:function(name) {
objectName = name;
},
GetName:function() {
return objectName;
},
Init:function() {
return angular.copy(this);
}
}
}
A controller like:
TestController = function($scope) {
$scope.TestClick = function () {
var tstA = TestFactory.Init();
var tstB = TestFactory.Init();
tstA.SetName('test A')
tstB.SetName('test B')
console.log('A', tstA.GetName());
console.log('B', tstB.GetName());
}
}
In the console I get Test B for both objects.
How can I make a proper instance of this object?
I would like to use the objectName value in other functions of the factory.
Take into account that in Angular, Factories are singletons, so the instance is always the same.
You can do the following:
TestFactory= function () {
var objectName={};
return {
SetName:function(property,name) {
objectName[property] = name;
},
GetName:function(property) {
return objectName[property];
},
Clear:function(property) {
delete objectName[property]
}
}
}
Then in your controller:
TestController = function($scope, TestFactory) {
$scope.TestClick = function () {
TestFactory.SetName('a','test A')
TestFactory.SetName('b','test B')
console.log('A', TestFactory.GetName('a')); // test A
console.log('B', TestFactory.GetName('b')); // test B
}
}
Couple of issues. First your returning an object rather than a function from your factory.
app.factory('TestFactory', function() {
return function() {
var objectName = null;
var setName = function(name) {
objectName = name;
};
var getName = function() {
return objectName;
};
return {
SetName: setName,
GetName: getName
};
};
});
Then you can just instantiate like this:
var tstA = new TestFactory();
var tstB = new TestFactory();
Services and factories are singletons so I think you can achieve what you want with a more appropriate use of the factory by providing an Init function that returns the common code and unique name like so:
angular.module('app')
.factory('ServiceFactory', serviceFactory);
function serviceFactory() {
return {
Init: function (name) {
return {
objectName: name,
setName: function (name) {
this.objectName = name;
},
getName: function () {
return this.objectName;
}
};
}
};
}
This leaves the possibility to use it as a factory that can initialize many types.
You basically need to create a simple getter/setter.
angular.module('app', [])
.controller('TestController', testController)
.service('serviceFactory', serviceFactory);
testController.$inject = ['serviceFactory'];
function testController(serviceFactory) {
serviceFactory.set('A', {
name: 'test A'
});
serviceFactory.set('B', {
name: 'test B'
});
console.log(serviceFactory.getAll());
console.log(serviceFactory.get('A'));
console.log(serviceFactory.get('B'));
}
function serviceFactory() {
var
_model = {
name: ""
},
_data = {};
return {
set: function(key, data) {
_data[key] = angular.extend({}, _model, data);
},
get: function(key) {
return _data[key];
},
getAll: function() {
return _data;
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<body ng-app="app" ng-controller="testController"></body>
I created a controller inside a state. We usually use this kind of notation for our angular (1.5) components and services with an angular.extend(self, {}).
My problem here is when self.criteria is being initialized, the browser call self.getAgencies() and return an exception :
Error: self.getAgencies is not a function
(function (app) {
'use strict';
app.config(function ($stateProvider) {
$stateProvider.state('app.invoice', {
url: '/invoice'
abstract: true,
template: '<ui-view></ui-view>'
})
.state('app.invoice.list', {
url: '/list?allMyParam',
template: '<invoices criteria="$ctrl.criteria"></invoices>',
controllerAs: '$ctrl',
controller: function ($location) {
var self = this;
angular.extend(self,{
criteria: {
agencies: self.getAgencies()
},
getAgencies: function () {
if ($location.search().agencies) {
return undefined;
} else {
return ['foo', 'blah'];
}
}
});
}
});
});
})(angular.module('module', []));
I put getAgencies() function over the criteria prototype initialization but it did not change anything.
I got out of it by moving getAgencies() outside of angular.extend(self, {}) like this :
var self = this;
var getAgencies = function () {
if ($location.search().agencies) {
return undefined;
} else {
return ['foo', 'blah'];
}
}
angular.extend(self, {
criteria: {
agencies: getAgencies()
}
});
My code is working so it is ok for me but I would like to understand why my self.getAgencies() is not working when this call inside a controller component works well, and make it better if I can.
I'm using angular-ui-router 0.2.18 with angular 1.5.0.
Thank you for your help.
Because when this code is reached
criteria: {
agencies: self.getAgencies()
},
the angular.extend function has not been called yet, and there is no reason why self should contain the getAgencies function.
Why not initialize the agencies afterwards?
angular.extend(self,{
criteria: { },
getAgencies: function () {
if ($location.search().agencies) {
return undefined;
} else {
return ['foo', 'blah'];
}
}
});
self.criteria.agencies = self.getAgencies();
Alternatively, you could use a getter and post-pone calling the function:
angular.extend(self,{
criteria: {
get agencies() {
if (!self._agencies) {
self._agencies = self.getAgencies();
}
return self._agencies;
}
},
getAgencies: ...
});
Here is the my question
var panel = {
_pnlHeaderContainer: $('.panelHeader'),
_pnlHeaderString:"",
//private method
_Write: function (pnlHeaderString) { return this._pnlHeaderContainer.html(pnlHeaderString); },
Clear: function () { return this._pnlBaslikContainer.html(""); },
// _fake:this,
Header: {
AddEvent:"Add Event",
Calendar: "Calendar",
}
};
what I wanna achieve is using the _Write method in Header object
something like this
Header: {
AddEvent:this._Write("Add Event"),
Calendar: "Calendar",
}
trying to run this code like this panel.Header.AddEvent; but it says me Write is not a function
I like to provide a context when creating a class
function Panel(){
var context = this;
this._pnlHeaderContainer = $('.panelHeader');
this._pnlHeaderString = "";
this._Write = function(pnlHeaderString){
return context._pnlHeaderContainer.html(pnlHeaderString);
};
this.Clear = function(){
return context._pnlBaslikContainer.html("");
};
this.Header = {
AddEvent: function(){ return context._Write("Add Event"); },
Calendar: "Calendar",
};
}
var panelObject = new Panel();
// Do whatever you want...
panelObject.Header.AddEvent();
Im new to angular and I'm having trouble saving user info from LinkedIn API to the scope in my controller without passing the scope to my custom service. I assume that is not the angular way of programming.
//html
<script type="text/javascript" src="//platform.linkedin.com/in.js">
api_key: *********
onLoad: onLinkedInLoad
</script>
// linkedIn button
<script type="in/Login">
</script>
// app.js
angular.module("linkedinTestApp",[]);
function onLinkedInLoad(){
eScope.$apply(function(){
eScope.getLinkedInData();
})
};
// main controller
var eScope;
angular.module("linkedinTestApp").
controller('mainCtrl',function($scope,linkedInService){
eScope = $scope;
$scope.getLinkedInData = function(){
linkedInService.OnLinkedInFrameworkLoad($scope);
}
})
//custom service
angular.module('linkedinTestApp')
.service('linkedInService', function() {
var scope;
this.OnLinkedInFrameworkLoad = function(s) {
scope = s;
IN.Event.on(IN, "auth", this.OnLinkedInAuth);
console.log("Test1");
}
this.OnLinkedInAuth = function() {
IN.API.Profile("me").result(function(result){
console.log(result);
var profile = {
vnaam: result.values[0].firstName,
anaam: result.values[0].lastName,
foto: result.values[0].pictureUrl,
headline: result.values[0].headline,
id: result.values[0].id
}
console.log(profile);
scope.profile = profile;
});
console.log("Test2");
}
});
Tested code. Took me 20-30 minutes to get api key and when i tested someone posted answer, but my code was tested so a post this, similar, answer. Also this is not the most elegant way to get profile in the controller, but I wanted to change as little code as possible(for similary).
angular.module("linkedinTestApp",[]);
function onLinkedInLoad(){
eScope.$apply(function(){
eScope.getLinkedInData();
})
};
// main controller
var eScope;
angular.module("linkedinTestApp").
controller('mainCtrl',function($scope,linkedInService){
eScope = $scope;
$scope.getLinkedInData = function(){
linkedInService.OnLinkedInFrameworkLoad().then(function(profile){
console.log('response ', profile);
});
}
})
//custom service
angular.module('linkedinTestApp')
.service('linkedInService', function($q) {
this.OnLinkedInFrameworkLoad = function() {
var deferred = $q.defer();
IN.Event.on(IN, "auth", function(){
deferred.resolve(OnLinkedInAuth())
});
return deferred.promise;
}
function OnLinkedInAuth() {
var deferred = $q.defer();
IN.API.Profile("me").result(function(result){
console.log(result);
var profile = {
vnaam: result.values[0].firstName,
anaam: result.values[0].lastName,
foto: result.values[0].pictureUrl,
headline: result.values[0].headline,
id: result.values[0].id
}
deferred.resolve(profile);
});
return deferred.promise;
}
});
// main controller
angular.module("linkedinTestApp").
controller('mainCtrl',function($scope,linkedInService){
$scope.getLinkedInData = function(){
linkedInService.OnLinkedInFrameworkLoad().then (function (result) {
$scope.profile = result;
});
}
})
//custom service
angular.module('linkedinTestApp')
.service('linkedInService', function() {
this.OnLinkedInFrameworkLoad = function() {
return this.OnLinkedInAuth();
}
this.OnLinkedInAuth = function() {
return IN.API.Profile("me").result(function(result){
console.log(result);
var profile = {
vnaam: result.values[0].firstName,
anaam: result.values[0].lastName,
foto: result.values[0].pictureUrl,
headline: result.values[0].headline,
id: result.values[0].id
}
console.log(profile);
return profile;
});
}
});
My suggestion:
angular.module('linkedinTestApp').service('linkedInService', function($q) {
var deferred = $q.defer();
var self = this;
this.profile = null;
this.OnLinkedInFrameworkLoad = function() {
IN.Event.on(IN, "auth", this.OnLinkedInAuth);
console.log("Test1");
} // NOT SURE IF THIS FUNCTION IS NEEDED, OR WHO CALLS IT, MAYBE YOU NEED TO JUST REPLACE IT WITH THE NEXT LINE:
// IN.Event.on(IN, "auth", this.OnLinkedInAuth);
this.OnLinkedInAuth = function() {
IN.API.Profile("me").result(function(result){
console.log(result);
deferred.resolve( {
vnaam: result.values[0].firstName,
anaam: result.values[0].lastName,
foto: result.values[0].pictureUrl,
headline: result.values[0].headline,
id: result.values[0].id
} );
});
console.log("Test2");
}
this.instance = function() {
return deferred.promise;
}
});
And use it in your controller:
$scope.linkedInService.instance().then(
function(profile) {
console.log(profile);
}
);
Of course I haven't tested it, but I hope it will work...
I've tried numerous different ways of writing a unit test for an AngularJS service that calls angular-translate, and I just can't get it to work out. Any advice would be appreciated. Here's my most promising example:
(function() {
var app = angular.module("theApp", ["pascalprecht.translate"]);
var theService = function($translate) {
var theFunction = function(data) {
return $translate("FOO", { input: data.in }).then(function(trans) {
data.out = trans;
});
};
return {
theFunction: theFunction
};
};
app.factory("theService", ["$translate", theService]);
}());
describe("theService", function() {
beforeEach(module("theApp", function($translateProvider, $provide) {
$translateProvider.useLoader('customLoader');
$provide.service('customLoader', function($q) {
return function() {
var deferred = $q.defer();
deferred.resolve({
"FOO": "foo {{input}}"
});
return deferred.promise;
};
});
}));
it("function translates input", inject(function($rootScope, theService) {
var data = { in: "bar", out: "fail" };
theService.theFunction(data);
$rootScope.$apply();
expect(data.out).toBe("foo bar");
}));
});
A JSFiddle can be found here: http://jsfiddle.net/danBhentschel/q71r874t/
Okay. I guess I figured it out on my own. I started out with the test found here:
https://github.com/angular-translate/angular-translate/blob/master/test/unit/service/translate.spec.js#L409
And I was able to slowly morph this passing test into what I wanted to do:
(function() {
var app = angular.module("theApp", ["pascalprecht.translate"]);
var theService = function($translate) {
var theFunction = function(data) {
return $translate("FOO", { input: data.in }).then(function(trans) {
data.out = trans;
});
};
return {
theFunction: theFunction
};
};
app.factory("theService", ["$translate", theService]);
}());
describe("theService", function() {
var $rootScope;
beforeEach(module("theApp", function($translateProvider, $provide) {
$translateProvider.useLoader("customLoader");
$provide.service("customLoader", function($q) {
return function() {
var deferred = $q.defer();
deferred.resolve({
"FOO": "foo {{input}}"
});
return deferred.promise;
};
});
}));
beforeEach(inject(function ($translate, _$rootScope_) {
$rootScope = _$rootScope_;
$translate.use("en_US");
$rootScope.$apply();
}));
it("function translates input", inject(function(theService) {
var data = { in: "bar", out: "fail" };
theService.theFunction(data);
$rootScope.$apply();
expect(data.out).toBe("foo bar");
}));
});
A JSFiddle with the solution can be found here: http://jsfiddle.net/danBhentschel/yLt3so14/
Please feel free to point out any stupid mistakes I made. I'm still kinda new at this.