J'ai deux contrôleurs Angular:
function Ctrl1($scope) {
$scope.prop1 = "First";
}
function Ctrl2($scope) {
$scope.prop2 = "Second";
$scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally
}
Je ne peux pas utiliser Ctrl1
à l'intérieur de Ctrl2
parce que ce n'est pas défini. Cependant si j'essaye de le transmettre comme si…
function Ctrl2($scope, Ctrl1) {
$scope.prop2 = "Second";
$scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally
}
Je reçois une erreur. Est-ce que quelqu'un sait comment faire ça?
Faire
Ctrl2.prototype = new Ctrl1();
Échoue également.
NOTE: Ces contrôleurs ne sont pas imbriqués l'un dans l'autre.
Une façon de partager des variables entre plusieurs contrôleurs consiste à créer un service et à l'injecter dans tout contrôleur sur lequel vous souhaitez l'utiliser.
Exemple de service simple:
angular.module('myApp', [])
.service('sharedProperties', function () {
var property = 'First';
return {
getProperty: function () {
return property;
},
setProperty: function(value) {
property = value;
}
};
});
Utilisation du service dans un contrôleur:
function Ctrl2($scope, sharedProperties) {
$scope.prop2 = "Second";
$scope.both = sharedProperties.getProperty() + $scope.prop2;
}
Ceci est très bien décrit dans ce blog (Leçon 2 et plus particulièrement).
J'ai constaté que si vous souhaitez lier ces propriétés à plusieurs contrôleurs, cela fonctionnera mieux si vous liez à la propriété d'un objet plutôt qu'à un type primitif (booléen, chaîne, nombre) pour conserver la référence liée.
Exemple: var property = { Property1: 'First' };
au lieu de var property = 'First';
.
UPDATE: Pour (espérons) clarifier les choses voici un violon qui montre un exemple de:
J'aime illustrer des choses simples par des exemples simples :)
Voici un exemple très simple de Service
:
angular.module('toDo',[])
.service('dataService', function() {
// private variable
var _dataObj = {};
// public API
this.dataObj = _dataObj;
})
.controller('One', function($scope, dataService) {
$scope.data = dataService.dataObj;
})
.controller('Two', function($scope, dataService) {
$scope.data = dataService.dataObj;
});
Et ici le jsbin
Et voici un exemple très simple Factory
:
angular.module('toDo',[])
.factory('dataService', function() {
// private variable
var _dataObj = {};
// public API
return {
dataObj: _dataObj
};
})
.controller('One', function($scope, dataService) {
$scope.data = dataService.dataObj;
})
.controller('Two', function($scope, dataService) {
$scope.data = dataService.dataObj;
});
Et ici le jsbin
Si c'est trop simple, voici un exemple plus sophistiqué
Aussi voir la réponse ici pour les commentaires relatifs aux meilleures pratiques
--- Je sais que cette réponse ne concerne pas cette question, mais je veux que les personnes qui lisent cette question et qui souhaitent gérer des services tels que des usines évitent d'avoir de la difficulté à le faire --- -
Pour cela, vous devrez utiliser un service ou une usine.
Les services sont les BEST PRACTICE pour partager des données entre des contrôleurs non imbriqués.
Une très très bonne annotation sur ce sujet à propos du partage de données concerne la façon de déclarer des objets. Je n’étais pas chanceux parce que je suis tombé dans un piège AngularJS avant de lire à ce sujet et j’étais très frustré. Alors laissez-moi vous aider à éviter ce problème.
J'ai lu dans le "ng-book: Le livre complet sur AngularJS" que les modèles AngularJS ng créés dans les contrôleurs en tant que données nues sont FAUX!
Un élément $ scope devrait être créé comme ceci:
angular.module('myApp', [])
.controller('SomeCtrl', function($scope) {
// best practice, always use a model
$scope.someModel = {
someValue: 'hello computer'
});
Et pas comme ça:
angular.module('myApp', [])
.controller('SomeCtrl', function($scope) {
// anti-pattern, bare value
$scope.someBareValue = 'hello computer';
};
});
En effet, il est recommandé (BEST PRACTICE) que le DOM (document html) contienne les appels en tant que
<div ng-model="someModel.someValue"></div> //NOTICE THE DOT.
Ceci est très utile pour les contrôleurs imbriqués si vous souhaitez que votre contrôleur enfant puisse modifier un objet à partir du contrôleur parent ....
Mais dans votre cas, vous ne voulez pas d'étendues imbriquées, mais il existe un aspect similaire pour obtenir des objets des services aux contrôleurs.
Disons que vous avez votre service 'Factory' et que dans l'espace de retour se trouve un objetA qui contient objectB qui contient objectC.
Si vous voulez que l’objetC se trouve dans votre oscilloscope à partir de votre contrôleur, c’est une erreur de dire:
$scope.neededObjectInController = Factory.objectA.objectB.objectC;
Cela ne fonctionnera pas ... Utilisez plutôt un seul point.
$scope.neededObjectInController = Factory.ObjectA;
Ensuite, dans le DOM, vous pouvez appeler objectC depuis objectA. C’est une pratique exemplaire liée aux usines, et la plus importante: cela aidera à éviter les erreurs inattendues et impossibles à capturer.
Solution sans créer de service, en utilisant $ rootScope:
Pour partager des propriétés entre plusieurs contrôleurs d'applications, vous pouvez utiliser Angular $ rootScope. C'est une autre option pour partager des données, en les mettant de manière à ce que les gens le sachent.
Le moyen privilégié de partager certaines fonctionnalités entre les contrôleurs est les services. Pour lire ou modifier une propriété globale, vous pouvez utiliser $ rootscope.
var app = angular.module('mymodule',[]);
app.controller('Ctrl1', ['$scope','$rootScope',
function($scope, $rootScope) {
$rootScope.showBanner = true;
}]);
app.controller('Ctrl2', ['$scope','$rootScope',
function($scope, $rootScope) {
$rootScope.showBanner = false;
}]);
Utilisation de $ rootScope dans un modèle (propriétés d’accès avec $ root):
<div ng-controller="Ctrl1">
<div class="banner" ng-show="$root.showBanner"> </div>
</div>
L’échantillon ci-dessus a fonctionné comme un charme. Je viens de faire une modification au cas où je devrais gérer plusieurs valeurs. J'espère que ça aide!
app.service('sharedProperties', function () {
var hashtable = {};
return {
setValue: function (key, value) {
hashtable[key] = value;
},
getValue: function (key) {
return hashtable[key];
}
}
});
J'ai tendance à utiliser des valeurs, heureux que quiconque puisse expliquer pourquoi c'est une mauvaise idée.
var myApp = angular.module('myApp', []);
myApp.value('sharedProperties', {}); //set to empty object -
Puis injecter la valeur selon un service.
Définir dans ctrl1:
myApp.controller('ctrl1', function DemoController(sharedProperties) {
sharedProperties.carModel = "Galaxy";
sharedProperties.carMake = "Ford";
});
et accès depuis ctrl2:
myApp.controller('ctrl2', function DemoController(sharedProperties) {
this.car = sharedProperties.carModel + sharedProperties.carMake;
});
J'aimerais contribuer à cette question en soulignant que la méthode recommandée pour partager des données entre contrôleurs, et même des directives, consiste à utiliser des services (usines), comme cela a déjà été souligné, mais j'aimerais également fournir une exemple de travail pratique de la façon dont cela devrait être fait.
Voici le programme de travail: http://plnkr.co/edit/Q1VdKJP2tpvqqJL1LF6?p=info
Tout d’abord, créez votre service , qui aura votre données partagées :
app.factory('SharedService', function() {
return {
sharedObject: {
value: '',
value2: ''
}
};
});
Ensuite, il suffit de l'injecter sur vos contrôleurs et de récupérer les données partagées sur votre scope:
app.controller('FirstCtrl', function($scope, SharedService) {
$scope.model = SharedService.sharedObject;
});
app.controller('SecondCtrl', function($scope, SharedService) {
$scope.model = SharedService.sharedObject;
});
app.controller('MainCtrl', function($scope, SharedService) {
$scope.model = SharedService.sharedObject;
});
Vous pouvez également le faire pour vos directives , cela fonctionne de la même manière:
app.directive('myDirective',['SharedService', function(SharedService){
return{
restrict: 'E',
link: function(scope){
scope.model = SharedService.sharedObject;
},
template: '<div><input type="text" ng-model="model.value"/></div>'
}
}]);
J'espère que cette réponse pratique et claire pourra être utile à quelqu'un.
L'exemple suivant montre comment passer des variables entre frères et soeurs contrôleurs et effectuer une action lorsque la valeur change.
Exemple de cas d'utilisation: vous avez un filtre dans une barre latérale qui modifie le contenu d'une autre vue.
angular.module('myApp', [])
.factory('MyService', function() {
// private
var value = 0;
// public
return {
getValue: function() {
return value;
},
setValue: function(val) {
value = val;
}
};
})
.controller('Ctrl1', function($scope, $rootScope, MyService) {
$scope.update = function() {
MyService.setValue($scope.value);
$rootScope.$broadcast('increment-value-event');
};
})
.controller('Ctrl2', function($scope, MyService) {
$scope.value = MyService.getValue();
$scope.$on('increment-value-event', function() {
$scope.value = MyService.getValue();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<h3>Controller 1 Scope</h3>
<div ng-controller="Ctrl1">
<input type="text" ng-model="value"/>
<button ng-click="update()">Update</button>
</div>
<hr>
<h3>Controller 2 Scope</h3>
<div ng-controller="Ctrl2">
Value: {{ value }}
</div>
</div>
Vous pouvez le faire avec des services ou des usines. Ils sont essentiellement les mêmes, à part quelques différences fondamentales. J'ai trouvé cette explication sur thinkster.io comme la plus simple à suivre. Simple, pertinent et efficace.
Ne pourriez-vous pas également faire de la propriété une partie du champ d'application Scopes?
$scope.$parent.property = somevalue;
Je ne dis pas que c'est juste, mais ça marche.
Ah, ayez un peu de ce nouveau truc comme une autre alternative. C'est un stockage local, et fonctionne où angular fonctionne. Je vous en prie. (Mais vraiment, merci le gars)
https://github.com/gsklee/ngStorage
Définissez vos valeurs par défaut:
$scope.$storage = $localStorage.$default({
prop1: 'First',
prop2: 'Second'
});
Accédez aux valeurs:
$scope.prop1 = $localStorage.prop1;
$scope.prop2 = $localStorage.prop2;
Stocker les valeurs
$localStorage.prop1 = $scope.prop1;
$localStorage.prop2 = $scope.prop2;
N'oubliez pas d'injecter ngStorage dans votre application et $ localStorage dans votre contrôleur.
Deuxième approche:
angular.module('myApp', [])
.controller('Ctrl1', ['$scope',
function($scope) {
$scope.prop1 = "First";
$scope.clickFunction = function() {
$scope.$broadcast('update_Ctrl2_controller', $scope.prop1);
};
}
])
.controller('Ctrl2', ['$scope',
function($scope) {
$scope.prop2 = "Second";
$scope.$on("update_Ctrl2_controller", function(event, prop) {
$scope.prop = prop;
$scope.both = prop + $scope.prop2;
});
}
])
Html:
<div ng-controller="Ctrl2">
<p>{{both}}</p>
</div>
<button ng-click="clickFunction()">Click</button>
Pour plus de détails voir plunker:
Il y a deux façons de faire ça
1) Utiliser le service get/set
2) $scope.$emit('key', {data: value}); //to set the value
$rootScope.$on('key', function (event, data) {}); // to get the value
Si vous ne voulez pas faire de service, vous pouvez le faire comme ça.
var scope = angular.element("#another ctrl scope element id.").scope();
scope.plean_assign = some_value;