Injecting data objects into a directive factory in AngularJS - angularjs

So I have a directive that takes in data objects as an argument into the scope. The problem is that I handle all my data in my service layer.
So this is some normal non-directive code:
angular.module('app').factory('appFactory', ['appValues', function(appValues) {
var getStuff = function() { return appValues.stuff; };
}]);
But if want to reuse the factory inside a directive and get appValues as an argument:
angular.module('app').directive('myDir', [function() {
return {
...
scope: {
values: '='
}
....
};
}]);
But this puts it on the scope and not into my data layer. So now I need to send the values object to every function call in my directive factory:
angular.module('app').factory('myDirFactory', [function() {
var getStuff = function(values) { return values.stuff; };
}]);
Is there any good pattern to solve this and keep data in the data-layer and bypass the scope/controller?
Also, the factory will be a singleton shared amongst instances of the directive? How should I solve that then? Create a new injector somehow? Submit to putting lots of data object logic into the controller (which I've been thought not to do)?

It was a while ago, and I guess that a simple soultion is simply to provide an function initialize(value) {... return {...};} and then the returned object has access to the value argument without providing it as a parameter everywhere:
angular.module('myDir').factory('myDirFactory', [function() {
var initialize = function(values) {
var getStuff = function() {
return values;
};
return {
getStuff: getstuff;
};
};
return {
initialize: initialize
};
}]);

Related

How to store controller functions in a service and call them in AngularJS

I need to execute functions of some controllers when my application ends (e.g. when closing the navigator tab) so I've thought in a service to manage the list of those functions and call them when needed. These functions changes depending on the controllers I have opened.
Here's some code
Controller 1
angular.module('myApp').component('myComponent', {
controller: function ($scope) {
var mc = this;
mc.saveData = function(objectToSave){
...
};
}
});
Controller 2
angular.module('myApp').component('anotherComponent', {
controller: function ($scope) {
var ac = this;
ac.printData = function(objects, priority){
...
};
}
});
How to store those functions (saveData & printData) considering they have different parameters, so when I need it, I can call them (myComponent.saveData & anotherComponent.printData).
The above code is not general controller but the angular1.5+ component with its own controller scope. So the methods saveData and printData can only be accessed in respective component HTML template.
So to utilise the above method anywhere in application, they should be part of some service\factory and that needs to be injected wherever you may required.
You can create service like :
angular.module('FTWApp').service('someService', function() {
this.saveData = function (objectToSave) {
// saveData method code
};
this.printData = function (objects, priority) {
// printData method code
};
});
and inject it wherever you need, like in your component:
controller: function(someService) {
// define method parameter data
someService.saveData(objectToSave);
someService.printData (objects, priority);
}
I managed to make this, creating a service for managing the methods that will be fired.
angular.module('FTWApp').service('myService',function(){
var ac = this;
ac.addMethodForOnClose = addMethodForOnClose;
ac.arrMethods = [];
function addMethodForOnClose(idModule, method){
ac.arrMethods[idModule] = {
id: idModule,
method: method
}
};
function executeMethodsOnClose(){
for(object in ac.arrayMethods){
ac.arrMethods[object].method();
}
});
Then in the controllers, just add the method needed to that array:
myService.addMethodForOnClose(id, vm.methodToLaunchOnClose);
Afterwards, capture the $window.onunload and run myService.executeMethodsOnClose()

How to pass variables within controllers in AngularJS

Hi I need to use a variable from the result scope of one controller to another controller. I can achieve this by using nested controller but in my case my controller 2 is not a child of controller 1. I somehow able to achieve my output with the following controller but still i want to know is this best practice if not how can i pass variables between various controllers.
angular.module('test',[])
.factory('PassParameter', PassParameter)
function PassParameter(){
var thisValue = {};
return {
getParameter: function () {
return thisValue;
},
setParameter: function (setValue) {
_.extend(thisValue, setValue);
},
removeParameter : function(value) {
_.omit(thisValue, value);
}
};
};
i Pass an object to setParameter function and get by its value from getParameter function.
this is the way that I'm passing info between controllers.
*Note that I'm using angular.copy so I won't lose reference, this way when "obj" is changed, you don't need to get it again.(works only on objects {})
angular.module('test').service('mySrv',
function () {
var obj = {};
this.getObj = function(){
return obj;
};
this.setObj = function(obj){
obj = angular.copy(obj);
};
});

Creating Private Methods in AngularJS Controllers

What is the way to create private methods in an AngularJS controllers?
I have currently done it like this, but I wonder whether it is the correct/preferable way:
app.controller('MyController', function($scope){
myPrivateFunction();
anotherPrivateFunction();
...
$scope.someScopeMethod = function(){
...
anotherPrivateFunction();
...
};
$scope.anotherScopeMethod = function(){
...
myPrivateFunction();
...
};
...
function myPrivateFunction(){
//
}
function anotherPrivateFunction(){
//
}
});
This is correct. Your functions will only be visible inside the scope of your controller constructor function. This is the same for factories and vanilla js where functions declared in functions will only be visible in their parent function context.
In factories it would looks like as below:
.factory('my-factory', function(){
function privareMethodA() {
}
var anotherPrivateMethod = function() {
}
return {
publicMethodA = function() {
},
publicMethodB = function() {
}
};
});
So after you inject your factory into another factory or a controller publicMethodA() and publicMethodB() will be available, but privateMethodA() and anotherPrivatemethod() won't be accessible from outside of this factory.
Accessibility of controllers are similar to your snippet.

AngularJS : Why is my factory always undefined in my controller?

My factory is undefined in my controller and I cannot figure out why. I have created a simple example to illustrate.
Here I create the app:
var ruleApp = angular
.module( "ruleApp", [
"ngRoute",
"ruleApp.NewFactory1",
"ruleApp.NewFactory2",
] );
In this dummy example I'd like to build a factory that does something simple, show an alert box. I'll show two methods of doing this (one works, one does not).
Factory 1:
angular
.module('ruleApp.NewFactory1', [])
.factory('NewFactory1', function() {
return function(msg) {
alert(msg);
};
});
Factory 2:
angular
.module('ruleApp.NewFactory2', [])
.factory('NewFactory2', function() {
var showMessageFunction = function(msg) {
alert(msg);
};
return
{
showMessage: showMessageFunction
};
});
Notice the return type of factory 1 is a function and the return type of factory 2 is an object with a property (which is of type function).
Now look at how I'd like to use both of these factories in my controller:
ruleApp.controller( "RuleController", function( $scope, NewFactory1, NewFactory2 ) {
NewFactory1("1");
NewFactory2.showMessage("2");
});
This is where the problem gets exposed. During execution, I am prompted with the alert box for NewFactory1("1");, but it fails during execution of NewFactory2.showMessage("2"); because NewFactory2 is undefined (TypeError: Cannot call method 'showMessage' of undefined).
Can you help me spot the issue? I want to be able to use factories like NewFactory2 because I want the factories to be able to do more than just one thing (i.e. have more than one single function). By the way, I'm using Angular version 1.2.1.
factory 2 should be (demo)
angular
.module('ruleApp.NewFactory2', [])
.factory('NewFactory2', function() {
var showMessageFunction = function(msg) {
alert(msg);
};
return { // <--------- do not go on a new line after return
showMessage: showMessageFunction
};
});

Share methods between custom directives

What is the most simple way to share a method between 2 directives?
I've tried using a factory and injecting that in my directives. But then I can't pass parameters to the factory. So I can get data back from my factory but I can't make the factory dynamic.
.directive('myFirstDirective', [...])
.directive('seconDirective', [...])
.factory('MenuItems', [function(){
return "testString";
}]);
By adding the factory to my code I can do in any directive:
var test = MenuItems;
But what I wan't to do is:
var test = MenuItems(myParameter); //so I can change the return in menuItems depending on myParameter
You can use a service to do that:
https://gist.github.com/anonymous/50b659c72249b58c31bf
.factory('MenuItemsService', [function(){
return {
getMenuItems : function(parameter){
if ( parameter === 'foo' ){
return ['bar', 'jar', 'tar'];
} else {
return ['asd', 'bsd', 'csd'];
}
}
};
}]);
Then in each directive you can inject the service, e.g:
MenuItemsService.getMenuItems('foo');
MenuItemsService.getMenuItems('bar');
To share data creating a service is the right thing to do.
Create a function on your service to process the data
.factory('MenuItems', function(){
var someDataToShare = ...
return {
someFunction: function(data) {
// process data here
return someDataToShare
}
}
});
call it like this:
$scope.processedData = MenuItems.someFunction($scope.someData)

Resources