2014-10-30 8 views
42

Mit der ursprünglichen Möglichkeit, Controller zu definieren, war der Zugriff auf den Bereich des übergeordneten Objekts ziemlich trivial, da der untergeordnete Bereich prototypisch von seinem übergeordneten Element erbt.Zugriff auf geerbten Bereich mit Controller als Ansatz

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> 

Die Regler-A Ansatz scheint der recommended Weg, um einen Controller zu erklären. Aber mit Controller-As funktioniert der obige Ansatz nicht mehr.

Sicher, kann ich den Umfang übergeordneten Zugriff mit pc.name von der Aussicht:

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

habe ich einige Probleme mit diesem (Potenzial für Spaghetti-Code), aber diese Frage ist über den übergeordneten Bereich von dem Zugriff auf Kinder-Controller.

Die einzige Art, wie ich diese Arbeit sehen kann, ist:

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

So, jetzt muss das Kind Controller über „pc“ wissen - außer, sollte dies (in meinem Kopf) auf die Ansicht eingeschränkt werden. Ich glaube nicht, dass ein Kind Controller wissen sollte über die Tatsache, dass eine Ansicht entschied, eine ng-controller="parentCtrl as pc" zu deklarieren.

F: Was ist der richtige Ansatz dann?

EDIT:

Klarstellung: Ich bin auf der Suche keine übergeordnete Steuerung erben. Ich möchte den freigegebenen Bereich erben/ändern. Also, wenn ich das erste Beispiel zu ändern war, sollte ich in der Lage sein, Folgendes zu tun:

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

Angulars "Controller" sind eher ein "View Helper" oder ein "View Model". Die Styleguides, die vorschlagen, 'controllerAs' zu verwenden, ermutigen Sie aktiv,' pc' direkt zu verwenden oder diese Situation zu beschönigen. Ich nehme an, Sie könnten eine Vererbungskette zwischen "parentCtrl" und "childCtrl" einrichten, z. 'childCtrl.prototype = Object.create (parentCtrl.prototype)' und dann würde 'this.name' in Ihrem' childCtrl' -Konstruktor auf den Namen des Elternteils verweisen, bevor Sie ihn schattieren. – Sacho

Antwort

60

Nach der Untersuchung, kam ich zu folgenden Erkenntnis:

-Controller-A Ansatz für die Verwendung von $scope kein Ersatz ist. Beide haben ihren Platz und können/sollten sinnvoll zusammen verwendet werden.

  1. $scope tut genau das, was der Name schon sagt: das heißt, es Ansichtsmodell Eigenschaften auf der $scope definiert. Dies funktioniert am besten für die Freigabe des Bereichs mit verschachtelten Controllern, die $scope verwenden können, um ihre eigene Logik zu steuern oder zu ändern.
  2. Controler-As definiert das gesamte Controller-Objekt als ViewModel mit einem benannten Bereich (über den Alias ​​des Controllers).Dies funktioniert am besten nur in der Ansicht (aber nicht in anderen Controllern), wenn die Ansicht entscheidet, ob sie auf ein bestimmtes Controller-ViewModel verweisen möchte.

Hier ist ein Beispiel:

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

So sagen Sie im Grunde, dass es nicht möglich ist, den Umfang eines Elternteils in einem Kind zugreifen, wenn "Controller als" verwenden? Ich halte den vom OP aufgelisteten Ansatz ($ scope. $ Parent.pc.name) für nicht durchführbar. – d512

7

Sie sollten wie tun:

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

werfen Sie einen Blick auf https://docs.angularjs.org/guide/controller

+0

Meine Absicht (Entschuldigung, wenn es nicht richtig vermittelt wurde) bestand nicht darin, einen Basis-Controller zu erben, sondern den Bereich zu erben. Ich möchte nicht wissen, welcher Eltern-Controller dort ist - ich möchte mich nur auf den Umfang verlassen (gemäß meinem ersten Beispiel). –

+0

ok so ist die einzige Möglichkeit, die ich kenne $ $ parent. $ Scope oder $ rootScope – Whisher

+0

@Whisher: es war wirklich hilfreich. Eine Frage dazu. Was ist nötig, um 'BaseController' als Basis zu verwenden? Ich kann einfach 'BaseController' richtig machen, da sowieso die Eigenschaften/Methoden vererbt werden sollen. Bitte korrigieren Sie mich, wenn ich falsch liege – jintoppy

1

Für alle, die einfach den Umfang programmatisch Eltern zuzugreifen, verwenden Sie die $scope Service, den übergeordneten Bereich finden, und den Namen verwendet Zugang für der übergeordnete Bereich ist controllerAs, z. B .:

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

Verwandte Themen