Sans utiliser un service ou créer des observateurs dans le contrôleur parent, comment donner aux États enfants l'accès aux $scope
du contrôleur principal.
.state("main", {
controller:'mainController',
url:"/main",
templateUrl: "main_init.html"
})
.state("main.1", {
controller:'mainController',
parent: 'main',
url:"/1",
templateUrl: 'form_1.html'
})
.state("main.2", {
controller:'mainController',
parent: 'main',
url: "/2",
templateUrl: 'form_2.html'
})
Je ne peux pas accéder à la portée de mainController dans un état enfant - ou plutôt, je reçois une autre instance de cette portée - pas ce que je veux. Je sens que je manque quelque chose de simple. Il y a une option de configuration de données partagées dans l'objet state, mais je ne suis pas sûr si cela devrait être utilisé pour quelque chose comme ça.
I plunker de travail créé , montrant comment utiliser _$scope
_ et UI-Router.
La définition de l'état est inchangée:
_$stateProvider
// States
.state("main", {
controller:'mainController',
url:"/main",
templateUrl: "main_init.html"
})
.state("main.1", {
controller:'mainController',
parent: 'main',
url:"/1",
templateUrl: 'form_1.html'
})
.state("main.2", {
controller:'mainController',
parent: 'main',
url: "/2",
templateUrl: 'form_2.html'
})
_
Mais chaque état peut avoir un contrôleur différent. Pourquoi? parce que chaque view
de chaque état obtient new
instance de controller
défini. Ainsi, bien que nous ayons mainController
comme celui ci-dessous, nous pouvons être sûrs que si nous passons à l'état _'main.2'
_, il sera instancié deux fois.
_controller('mainController', function ($scope) {
$scope.Model = $scope.Model || {Name : "xxx"};
})
_
Mais ce que nous pouvons voir ici , c’est que nous vérifions si _$scope.Model
_ existe déjà ... et si non (État parent) nous instancions il avec nouvelle intance {Name : "xxx"}
.
Eh bien, ce que je dis, c’est que seul l’État parent initiera le _$scope.Model
_. Tous les autres obtiendront cela déjà rempli. Comment? Eh bien voici la réponse:
Gardez à l'esprit que les propriétés de portée n'héritent en aval de la chaîne d'états que si les vues de vos états sont imbriquées. L'héritage des propriétés de portée n'a rien à voir avec l'imbrication de vos états et tout ce qui a trait à l'imbrication de vos vues (modèles).
Il est tout à fait possible que vous ayez des états imbriqués dont les modèles remplissent des vues UI à divers emplacements non imbriqués de votre site. Dans ce scénario, vous ne pouvez pas vous attendre à accéder aux variables d'étendue des vues d'état parent dans les vues d'états enfants.
Donc, comme indiqué dans la documentation. Comme nos vues enfant sont imbriquées dans la vue parent, la portée est héritée.
Dans AngularJS, une portée enfant hérite normalement de sa portée parent de manière prototypique.
...Avoir un '.' dans vos modèles garantira que l’héritage prototype est en jeu.
_// So, use
<input type="text" ng-model="someObj.prop1">
// rather than
<input type="text" ng-model="prop1">.
_
Et c'est tout. Nous obtenons l'héritage de _UI-Router
_ views et de angular scopes, et parce que nous avons intelligemment utilisé un type de référence (Model
), c'est-à-dire que vous avez _'.'
_ point dans _ng-model
_ définition - nous pouvons partager des données maintenant
NOTE: avoir un point '.' dans _ng-model="Model.PropertyName
_ signifie simplement qu'il existe un objet reference
_Model {}
_ avec une propriété: PropertyName
Vérifiez le exemple de travail ici
Vous pouvez obtenir la totalité de la portée via $ rootScope . Si vous n'avez besoin que d'une partie de la portée, ui-router a une fonctionnalité données personnalisées .
Voici comment faire un formulaire en plusieurs étapes. J'avais besoin que les routes contiennent des informations sur leurs étapes dans le flux.
Tout d'abord, j'ai quelques itinéraires avec UI-router:
// Sign UP routes
.state('sign-up', {
abstract: true,
url: '/sign-up',
controller: 'SignupController',
templateUrl: 'sign-up/index.html',
})
.state('sign-up.start', {
url: '-start',
templateUrl: 'sign-up/sign-up.start.html',
data: { step: 0, title: 'Welcome to Mars!', },
})
.state('sign-up.expertise', {
url: '-expertise',
templateUrl: 'sign-up/sign-up.expertise.html',
data: { step: 1, title: 'Your Expertise'},
})
Remarquer:
data
dans chaque route.abstract
a SignupController
. C'est le seul contrôleur pour ce formulaire en plusieurs étapes. La abstract
n'est pas obligatoire, mais convient à ce cas d'utilisation.SignupController.js
angular.module('app').controller('SignupController', function($scope, $state) {
$scope.state = $state;
});
Ici nous obtenons $state
de ui-router et le plaçons sur $scope
Voici le modèle principal 'sign-up/index.html' ,:
<h2>{{state.current.data.title}}</h2>
<div>This is a multi-step-progress control {{state.current.data.step}}</div>
<form id="signUpForm" name="signUpForm" novalidate>
<div ui-view></div>
</form>
Les modèles enfants peuvent être ce qu'ils veulent.
L'idée est que vous utilisiez scope dans parent-> héritage enfant:
.state("main", {
controller:'mainController',
abstract: true,
url:"/main",
templateUrl: "main_init.html"
})
.state("main.1", {
controller:'mainController1',
parent: 'main',
url:"/1",
templateUrl: 'form_1.html'
})
.state("main.2", {
controller:'mainController2',
parent: 'main',
url: "/2",
templateUrl: 'form_2.html'
})
Alors que l'utilisation est simple, vous avez 3 contrôleurs, l'un est partagé (mainController) et chaque vue a sa propre.
Si vous utilisez des vues imbriquées, n'écrivez aucun autre contrôleur. De cette manière, ils partageront les mêmes données de contrôleur.
.state("main", {
url: "/main",
templateUrl: "templates/Ders",
controller: "DersController as DersC"
}).state("main.child1", {
url: "/child1",
templateUrl: "templates/Ders/child1"
}).state("main.child2", {
url: "/child2",
templateUrl: "templates/Ders/child2"
})
La solution la plus simple n'est-elle pas de regrouper des variables partagées dans un service auquel vous pouvez accéder dans chaque contrôleur? ...