web-dev-qa-db-fra.com

Accès à la portée héritée avec l'approche Controller As

Avec la manière originale de définir les contrôleurs , l'accès à la portée du parent était assez trivial, car la portée enfant hérite de manière prototypique de son parent.

app.controller("parentCtrl", function($scope){
   $scope.name = "Parent";
})
.controller("childCtrl", function($scope){
   $scope.childName = "child of " + $scope.name;
});

<div ng-controller="parentCtrl">
   {{name}}
   <div ng-controller="childCtrl">
      {{childName}}
   </div>
</div>

L'approche Controller-As semble être la manière recommandée de déclarer un contrôleur. Mais avec Controller-As, l'approche ci-dessus ne fonctionne plus.

Bien sûr, je peux accéder à la portée parent avec pc.name depuis la vue:

<div ng-controller="parentCtrl as pc">
   {{pc.name}}
   <div ng-controller="childCtrl as cc">
      {{cc.childName}}
   </div>
</div>

J'ai quelques problèmes avec cela (potentiel pour le code spaghetti), mais cette question concerne l'accès à la portée parent à partir du contrôleur enfant.

La seule façon dont je peux voir ce fonctionnement est:

app.controller("parentCtrl", function(){
   this.name = "parent";
})
.controller("childCtrl", function($scope){
   $scope.pc.name = "child of " + $scope.name;
   // or
   $scope.$parent.pc.name = "child of " + $scope.name;

   // there's no $scope.name
   // and no $scope.$parent.name
});

Alors maintenant, le contrôleur enfant doit connaître "pc" - sauf que cela devrait (dans mon esprit) être limité à la vue. Je ne pense pas qu'un contrôleur enfant devrait savoir qu'une vue a décidé de déclarer un ng-controller="parentCtrl as pc".

Q: Quelle est donc la bonne approche?

MODIFIER:

Clarification: je ne cherche pas à hériter d'un contrôleur parent. Je cherche à hériter/changer la portée partagée. Donc, si je modifiais le premier exemple, je devrais pouvoir faire ce qui suit:

app.controller("parentCtrl", function($scope){
   $scope.someObj = {prop: "not set"};
})
.controller("childCtrl", function($scope){
   $scope.someObj.prop = "changed";
});
44
New Dev

Après des recherches, je suis arrivé à la réalisation suivante:

L'approche Controller-As ne remplace PAS l'utilisation de $scope. Les deux ont leur place et peuvent/doivent être utilisés ensemble judicieusement.

  1. $scope fait exactement ce que son nom implique: c'est-à-dire qu'il définit les propriétés de ViewModel sur le $scope. Cela fonctionne mieux pour partager la portée avec des contrôleurs imbriqués qui peuvent utiliser le $scope pour conduire leur propre logique ou pour la changer.
  2. Controler-As définit l'objet contrôleur entier comme un ViewModel avec une étendue nommée (via l'alias du contrôleur). Cela fonctionne mieux uniquement dans la vue (mais pas dans les autres contrôleurs), si la vue décide si elle veut référencer un contrôleur spécifique ViewModel.

Voici un exemple:

var app = angular.module('myApp', []);

// Then the controllers could choose whether they want to modify the inherited scope or not:
app.controller("ParentCtrl", function($scope) {
    this.prop1 = {
      v: "prop1 from ParentCtrl"
    };
    $scope.prop1 = {
      v: "defined on the scope by ParentCtrl"
    };
  })
  .controller("Child1Ctrl", function($scope) {})
  .controller("Child2Ctrl", function($scope) {
    // here, I don't know about the "pc" alias
    this.myProp = $scope.prop1.v + ", and changed by Child2Ctrl";
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>

<body ng-app="myApp">
  <div ng-controller="ParentCtrl as pc">
     <div ng-controller="Child1Ctrl">
        <div>I know about the "pc" alias: {{pc.prop1.v}}</div>
     </div>
     <div ng-controller="Child2Ctrl as ch2">
       <div>I only care about my own ViewModel: {{ch2.myProp}}</div>
    </div>
  </div>
62
New Dev

Vous devriez faire comme:

html

<div ng-controller="ChildController as child">
    <button type="button" ng-click="child.sayMe()">Say me!</button>
</div>

js

var app = angular.module('myApp', [])
app.controller('BaseController',function() {
    this.me = 'Base';
    this.sayMe= function() {
        alert(this.me);
    }
});
app.controller('ChildController', function($scope, $controller) {
    var controller = $controller('BaseController as base', {$scope: $scope});
    angular.extend(this, controller);
    this.me = 'Child';
});

jetez un oeil à https://docs.angularjs.org/guide/controller

7
Whisher

Pour toute personne souhaitant simplement accéder à la portée parent par programmation, utilisez le service $scope, Recherchez la portée parent et accédez au nom utilisé pour le controllerAs de la portée parent, par exemple:

$scope.$parent.someName.doSomething();

1
Adam Reis