sharing $scope between controller and factory in AngularJS - javascript

I have a variable 'file' that is being passed to a directive which i am using in the same controller. Now i want to use that same 'file' in the factory that i am creating but i'm not sure if there is an easy way to share that same variable between controller and factory.
for example...
fileCategory.directive.js:
.directive('fileCategory', function () {
return {
templateUrl: '...'
restrict: 'EA',
replace: true,
scope: {
file: '='
},
controller: 'fileCategoryController'
};
});
fileCategory.controller.js:
.controller('fileCategoryController', function($scope) {
if(!$scope.file) {
return;
} else {
console.log($scope.file);
}
fileCategory.factory.js
.factory('fileCategoryList', function () {
categories.get = function() {
if($scope.file){
return this.categories;
} else{
return;
}
};
I want to be able to use $scope.file in my factory like so...

Using $rootScope is possible here, but please don't use it in this case. Better practice is use service for storing data, and manipulate between different components. When your application will grow, it can be problem store more data in global $rootScope.
.service('CategoryService', function () {
this.file = ...
}
then implement service to controller, factory or anywhere you need
.controller('fileCategoryController', function($scope, CategoryService ) {
$scope.file = CategoryService.file
if(!CategoryService.file) {
return;
} else {
console.log($scope.file);
}

Related

Communicate between two directives Angularjs?

I am trying to communicate between two directives. I tried the service way, it didn't work. Maybe I am doing something wrong.
<list-data testing="trial" template-url="grid.html" link-passed="data.json"></list-data>
My directive and service:
app.directive('listData', function($http, serVice){
return {
restrict: 'E',
scope: {
testing: '#',
linkPassed: '#'
},
templateUrl: function(elem,attrs) {
return attrs.templateUrl || 'some/path/default.html'
},
link: function($scope){
var url = 'js/' + $scope.linkPassed;
$http.get(url).then(success, error);
function success(data){
$scope.iconUrl = data.data;
}
function error(response){
console.log(response)
}
$scope.tryingToClick = function(icon){
serVice=icon.name;
console.log(serVice)
}
}
};
});
app.directive('render', function(serVice){
return {
restrict: 'E',
template: '{{rendering}}',
link: function($scope){
$scope.rendering = serVice.name;
console.log(serVice)
}
};
});
app.factory('serVice', function(){
return{items:{}};
})
grid.html is just a simple grid layout where I am trying to show the data in grid.
<div class="col-sm-6 grid" ng-repeat="icon in iconUrl">
<p ng-click="tryingToClick(icon)">{{icon.iconUrl}}</p>
</div>
I need to pass the data when I click the function tryingToClick and the icon passes to the render directive. I cannot use $rootscope here, nor make new controllers. I will be using the logic here in a pretty big enterprise app, just that I made a very simple version of it on my localhost, just to get the logic right.
Your service doesn't look quite right. I'd use
app.factory('serVice', function() {
var settings = {};
// optionally set any defaults here
//settings.name = 'me';
return settings;
});
and you're not setting the name property of the service here:
serVice=icon.name;
It should be
serVice.name = icon.name;
given that you're looking for the name property later: $scope.rendering = serVice.name;
What do you mean by not creating more controllers? Do you mean that you can't create more on the app or that you can't use controllers within the directives?
From what I understood of your question I threw this codepen together for experimentation http://codepen.io/ihinckle/pen/JWGpQj?editors=1010
<div ng-app="directiveShare">
<directive-a an-array="[1,2,3,4,5]"></directive-a>
<directive-b></directive-b>
</div>
angular.module('directiveShare', [])
.directive('directiveA', function(){
return {
restrict: 'E',
scope: {
anArray: '<'
},
controller: function($scope, aService){
$scope.clicked = aService.setIcon;
},
template: `
<ul>
<li ng-repeat="item in anArray" ng-click="clicked(item)">item</li>
</ul>`
}
})
.directive('directiveB', function(){
return {
controller: function($scope, aService){
$scope.displayIcon = aService.getIcon;
},
template: `
<h1>{{displayIcon()}}</h1>
`
}
})
.factory('aService', function(){
var srvc = {};
srvc.setIcon = function(x){
srvc.icon = x;
};
srvc.getIcon = function(){
if(srvc.icon){
return srvc.icon;
}else {
return '';
}
};
return srvc;
});
I used getters and setters in the service and controllers on the directives to expose the functions.

Multiple views, multiple resolve but for one controller in AngularJS

I have 2 views that share the same controller. In each one of this view I used resolve to retrieve some date before displaying it. Then I inject it in my controller (so I inject two dependancy for each view).
But the problem is when I go from a view to another, the console display an error because it doesn't see the dependancy from the other view. This is my route configuration
.state('ambassade', {
url: '/mot_ambassadeur',
views: {
"#": {
templateUrl: "pages/GestionAmbassade/mot_ambassadeur.html",
controller: "GestionAmbassadeController",
resolve: {
informationsAmbassade: function(GestionAmbassadeService) {
return GestionAmbassadeService.getMotAmbassadeurService();
}
}
}
}
})
.state('personnel', {
url: '/personnel',
views: {
"#": {
templateUrl: "pages/GestionAmbassade/personnel.html",
controller: "GestionAmbassadeController",
resolve: {
personnelAmbassade: function(GestionAmbassadeService) {
return GestionAmbassadeService.getPersonnelService();
}
}
}
}
})
This is my controller, the 2 injections are informationsAmbassade and personnelAmbassade :
.controller('GestionAmbassadeController', function ($rootScope, $scope, $injector, $sce,
informationsAmbassade,
personnelAmbassade) {
$scope.getMotAmbassadeur = function () {
if (localStorage.getItem("lang") == "fr") {
$scope.motAmbassadeur = $sce.trustAsHtml(informationsAmbassade.contents[0].translation.fr_fr.contenu);
$scope.load = true;
}
$scope.photoAmbassadeur = informationsAmbassade.contents[0].content.path;
};
$scope.getPersonnel = function () {
$scope.Personnels = [];
if (localStorage.getItem("lang") == "fr") {
for (var i = 0; i < personnelAmbassade.contents.length; i++) {
//if ( angular.isDefined(res.contents[i].type) && res.contents[i].type.nom == 'personnel' )
$scope.Personnels.push({
nom: $sce.trustAsHtml(personnelAmbassade.contents[i].translation.fr_fr.contenu),
poste: $sce.trustAsHtml(personnelAmbassade.contents[i].translation.fr_fr.titre)
});
}
$scope.load = true;
}
};
So when I go to ambassade route it doesn't see the personnalAmbassade injection and vice-versa. I know I can use the two resolves for each state but this is what I'm avoiding for performance purpose. Can someone help me figure out this "issue".
You should see the inject in the controller as an Interface from more object orientated languages.
So name it something like entityService and make it so both services you are trying to inject have a method of the same name that you can call from the controller. (Or in your case 'contents' arrays)
.controller('GestionAmbassadeController', function ($rootScope, $scope, $injector, $sce,entityService) {
Then in the resolve put:
entityService: return GestionAmbassadeService.getPersonnelService();
or
entityService: return GestionAmbassadeService.getMotAmbassadeurService();
Depending on the controller instance.
Edit: It doesn't seem like a good idea to have the same controller for both states it this case. You will only be able to use one of the two defined scope functions anyway. So it would be beter to just have separate controllers.
Thank you guys. Both answers solved the problem (I tried them :D). But I think the first one is more suitable because in the second one when I have too many pages for the same controller it will be a little slower than the first answer.
But both still works. Thank you.
edit : when I said the first one I was talking about Bob Brinks answered. It moves down when he edited it.
You should create a top abstract state to resolve your datas, then you are sure to load the right dependencies (both of them) when you are in your controller.
.state('app', {
abstract:true,
template:'<div ui-view></div>',
resolve:{
informationsAmbassade: function(GestionAmbassadeService) {
return GestionAmbassadeService.getMotAmbassadeurService();
},
personnelAmbassade: function(GestionAmbassadeService) {
return GestionAmbassadeService.getPersonnelService();
}
}
}
.state('app.ambassade', {
url: '/mot_ambassadeur',
views: {
"#": {
templateUrl: "pages/GestionAmbassade/mot_ambassadeur.html",
controller: "GestionAmbassadeController"
}
}
}
})
.state('app.personnel', {
url: '/personnel',
views: {
"#": {
templateUrl: "pages/GestionAmbassade/personnel.html",
controller: "GestionAmbassadeController"
}
}
})

Controllers using same function

I have a function that two controllers will be using, and instead of both of them having the same source code for the same function, I want it in one place and just inject the controller parameters (or perhaps the controller itself this). These three may exist in three separate files/modules.
.controller('FirstCtrl', function() {
this.search = function(this) {
find(this);
};
});
.controller('SecondCtrl', function() {
this.seek = function(this) {
find(this);
};
});
var find = function(controller) {
.
.
.
};
Is this the best way? How about if I have services in my controllers like $http or $scope, and the function find would depend on these services? How do I inject these angular specific services to a plain JavaScript function not defined in an AngularJS module?
There are a few ways to do it; one may be:
.factory("findMixin", function() {
return {
find: function() {
// your implementation; `this` will be the controller
}
};
})
.controller("SomeCtrl", ["$scope", "findMixin", function($scope, findMixin) {
angular.extend(this, findMixin);
// here `this`, i.e. the controller, has received the methods from the mixin
...
})
The same principle (angular.extend) can be applied to the $scope, if you want find to be mixed into the scope.
You can add a service:
.factory('find', [ function() {
return function(controller, scope) {
// ...
};
}]);
And inject it into the controllers:
.controller('FirstCtrl', ['find', function(find) {
this.search = function(this) {
find(this);
};
}]);
.controller('SecondCtrl', ['find', function(find) {
this.seek = function(this) {
find(this);
};
}]);

How to get data from controller to Factory in angularjs

I am newbie to Angularjs World. I want to fetch some data from angularjs controller to Angularjs Factory.Controller and factory are defined in different js files.
code from Factory(File name Application.js)
var app=angular.module('myApp',[])
app.factory('autoCompleteDataService', [function(MyController) {
return {
getSource: function() {
return MyController.getFirstName();
}
}
}]);
app.directive('autoComplete', function(autoCompleteDataService) {
return {
restrict: 'A',
link: function(scope, elem, attr, ctrl) {
$(elem).autocompleteArray(autoCompleteDataService.getSource(), {
minLength: 2
});
}
}})
Controller code (File Name Controller.js)
function MyController($scope){
this.getFirstName= function ()
{
var arrayFName=[];
for(var k=0;k< $scope.MyData.length;k++)
{
arrayFName.push($scope.MyData[k].fname);
}
return arrayFName;
}
MyData is array containing some hard coded value for 'fname'
When i ran this code got error 'Error: MyController is undefined'. Is it possible to fetch data from controller if yes then how?
You should have source, or firstName, defined in the factory, and then set it from the controller. It will then be accessible from other controllers which use the factory.
var app=angular.module('myApp',[])
app.factory('autoCompleteDataService', [function () {
var _source;
return {
getSource: function () {
return _source;
},
setSource: function (source) {
_source = source;
}
}
}]);
And then subsequent controllers might be like:
app.controller('someController', ['$scope', 'autoCompleteDataService',
function ($scope, autoCompleteDataService) {
$scope.source = autoCompleteDataService.getSource();
// or even...
// $scope.getFirstName = autoCompleteDataService.getSource;
}]);

AngularJS communication between controller and directive

How to get some data from controller and use it inside directive thats not a problem.
But I stack with such situation when I need get data from directive and use it in my controller.
For exmpl:
My controller:
function MyController($scope, $location, myDirective) {
"use strict";
// here i need use scope.importantValue and create() method from directive
}
My directive:
.directive("myDirective", function() {
"use strict";
return {
restrict: 'A',
template: '<div></div>',
replace: true,
scope: {
data: '=',
},
link: function(scope, elm) {
scope.importantValue = "value";
function create() {
console.log("Directive works...");
}
};
})
How I can use variables or/and methods from directive inside my controller?
The simplest way to accomplish this is to make both your controller and directive get importantValue and create() from a service.
angular.module(/* Your module */).service('sharedData', function () {
return {
importantValue: "value",
create: function () {
console.log("Directive works...");
}
};
});
Now you can inject sharedData into your directive and controller and access importantValue and create() from either place.

Categories