angularjs - component - ng controller angular 4
Accediendo al alcance heredado con el enfoque de Controller As (3)
Deberías hacer como:
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'';
});
echa un vistazo a https://docs.angularjs.org/guide/controller
Con la forma original de definir controladores , acceder al alcance de los padres era bastante trivial, ya que el alcance del niño hereda de manera prototípica de su padre.
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>
El método Controller-As parece ser la forma recommended de declarar un controlador. Pero con Controller-As, el enfoque anterior ya no funciona.
Claro, puedo acceder al alcance principal con pc.name
desde la Vista:
<div ng-controller="parentCtrl as pc">
{{pc.name}}
<div ng-controller="childCtrl as cc">
{{cc.childName}}
</div>
</div>
Tengo algunos problemas con esto (potencial para el código de espagueti), pero esta pregunta se trata de acceder al alcance principal desde el controlador de niño.
La única forma en que puedo ver que esto funciona es:
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
});
Así que ahora, el controlador hijo necesita saber acerca de " pc
", excepto que esto debería (en mi opinión) estar restringido a la vista. No creo que un controlador secundario deba saber que una vista decidió declarar un ng-controller="parentCtrl as pc"
.
P: ¿Cuál es el enfoque correcto entonces?
EDITAR:
Aclaración: no estoy buscando heredar un controlador principal. Estoy buscando heredar / cambiar el alcance compartido. Entonces, si tuviera que enmendar el primer ejemplo, debería ser capaz de hacer lo siguiente:
app.controller("parentCtrl", function($scope){
$scope.someObj = {prop: "not set"};
})
.controller("childCtrl", function($scope){
$scope.someObj.prop = "changed";
});
Después de investigar, llegué a la siguiente conclusión:
El enfoque Controller-As NO es un sustituto del uso de
$scope
. Ambos tienen su lugar, y pueden / deben usarse juntos juiciosamente.
-
$scope
hace exactamente lo que su nombre implica: es decir, define las propiedades de ViewModel en$scope
. Esto funciona mejor para compartir el alcance con controladores anidados que pueden usar$scope
para controlar su propia lógica o modificarla. - Controler-As define todo el objeto del controlador como un ViewModel con un alcance nombrado (a través del alias del controlador). Esto funciona mejor solo en la vista (pero no en otros controladores), si la vista decide si quiere hacer referencia a un modelo de vista específico del controlador.
Aquí hay un ejemplo:
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>
Para cualquiera que quiera simplemente acceder al ámbito primario programáticamente, use el servicio $scope
, encuentre el ámbito principal y acceda al nombre utilizado para los controllerAs
del ámbito principal, por ejemplo:
$scope.$parent.someName.doSomething();