Подтвердить что ты не робот

Доступ к унаследованной области с помощью Controller As approach

С исходным способом определения контроллеров доступ к родительской области был довольно тривиальным, так как область содержимого прототипа наследует его родителя.

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>

Подход с помощью Controller-As представляется рекомендуемым, чтобы объявить контроллер. Но с помощью Controller-As вышеупомянутый подход больше не работает.

Конечно, я могу получить доступ к родительской области с помощью pc.name из представления:

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

У меня есть некоторые проблемы с этим (потенциал для кода спагетти), но этот вопрос касается доступа к родительской области с дочернего контроллера.

Единственный способ, которым я вижу это, - это:

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 no $scope.name
   // and no $scope.$parent.name
});

Итак, теперь дочерний контроллер должен знать о "pc" - за исключением того, что это должно (на мой взгляд) ограничиваться представлением. Я не думаю, что дочерний контроллер должен знать о том, что представление решило объявить ng-controller="parentCtrl as pc".

Q: Какой правильный подход?

EDIT:

Уточнение: я не хочу наследовать родительский контроллер. Я ищу для наследования/изменения общей области. Поэтому, если бы я исправил первый пример, я должен был бы сделать следующее:

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

Ответ 1

После исследования я пришел к следующему пониманию:

Подход "Controller-As" НЕ заменяет использование $scope. Оба имеют свое место и могут/должны использоваться вместе разумно.

  • $scope делает именно то, что подразумевается в названии, т.е. определяет свойства ViewModel на $scope. Это лучше всего подходит для совместного использования области с вложенными контроллерами, которые могут использовать $scope для управления собственной логикой или для ее изменения.
  • Controler-As определяет весь объект контроллера как ViewModel с именованной областью (через псевдоним контроллера). Это лучше всего работает только в представлении (но не в других контроллерах), если View решает, хочет ли он ссылаться на определенный контроллер ViewModel.

Вот пример:

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>

Ответ 2

Вам следует сделать следующее:

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';
});

взгляните на https://docs.angularjs.org/guide/controller

Ответ 3

Для тех, кто хочет просто получить доступ к родительской области программным способом, используйте службу $scope, найдите родительскую область и получите доступ к имени, используемому для родительской области controllerAs, например:

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