AngularJS accede all'ambito padre dal controller figlio


382

Ho impostato i miei controller usando data-ng-controller="xyzController as vm"

Ho uno scenario con controller nidificati padre / figlio. Non ho problemi ad accedere alle proprietà parent nell'html nidificato usando $parent.vm.property, ma non riesco a capire come accedere alla proprietà parent dal mio controller figlio.

Ho provato a iniettare $ scope e poi a usarlo $scope.$parent.vm.property, ma questo non funziona?

Qualcuno può offrire consigli?

Risposte:


620

Se il tuo HTML è come sotto puoi fare qualcosa del genere:

<div ng-controller="ParentCtrl">
    <div ng-controller="ChildCtrl">
    </div>
</div>

Quindi è possibile accedere all'ambito padre come segue

function ParentCtrl($scope) {
    $scope.cities = ["NY", "Amsterdam", "Barcelona"];
}

function ChildCtrl($scope) {
    $scope.parentcities = $scope.$parent.cities;
}

Se vuoi accedere a un controller genitore dal tuo punto di vista devi fare qualcosa del genere:

<div ng-controller="xyzController as vm">
   {{$parent.property}}
</div>

Vedi jsFiddle: http://jsfiddle.net/2r728/

Aggiornare

In realtà, poiché è stato definito citiesnel controller padre, il controller figlio erediterà tutte le variabili dell'ambito. Quindi teoricamente non devi chiamare $parent. L'esempio sopra può anche essere scritto come segue:

function ParentCtrl($scope) {
    $scope.cities = ["NY","Amsterdam","Barcelona"];
}

function ChildCtrl($scope) {
    $scope.parentCities = $scope.cities;
}

I documenti di AngularJS usano questo approccio, qui puoi leggere di più sul $scope.

Un altro aggiornamento

Penso che questa sia una risposta migliore al poster originale.

HTML

<div ng-app ng-controller="ParentCtrl as pc">
    <div ng-controller="ChildCtrl as cc">
        <pre>{{cc.parentCities | json}}</pre>
        <pre>{{pc.cities | json}}</pre>
    </div>
</div>

JS

function ParentCtrl() {
    var vm = this;
    vm.cities = ["NY", "Amsterdam", "Barcelona"];
}

function ChildCtrl() {
    var vm = this;
    ParentCtrl.apply(vm, arguments); // Inherit parent control

    vm.parentCities = vm.cities;
}

Se si utilizza il controller asmetodo è anche possibile accedere all'ambito padre come segue

function ChildCtrl($scope) {
    var vm = this;
    vm.parentCities = $scope.pc.cities; // note pc is a reference to the "ParentCtrl as pc"
}

Come puoi vedere ci sono molti modi diversi di accedere $scopes.

Violino aggiornato

function ParentCtrl() {
    var vm = this;
    vm.cities = ["NY", "Amsterdam", "Barcelona"];
}
    
function ChildCtrl($scope) {
    var vm = this;
    ParentCtrl.apply(vm, arguments);
    
    vm.parentCitiesByScope = $scope.pc.cities;
    vm.parentCities = vm.cities;
}
    
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.min.js"></script>
<div ng-app ng-controller="ParentCtrl as pc">
  <div ng-controller="ChildCtrl as cc">
    <pre>{{cc.parentCities | json}}</pre>
    <pre>{{cc.parentCitiesByScope | json }}</pre>
    <pre>{{pc.cities | json}}</pre>
  </div>
</div>


6
Penso che i due problemi con l'ultimo aggiornamento siano 1. L'ereditarietà dell'ambito padre può avere potenziali conflitti nello spazio dei nomi e 2. Richiede la conoscenza che l'alias del controller padre è "pc". Ciò rende più difficile il riutilizzo.
Tchen

2
Hai definito i controller come funzione CtrlName (...) {} ma come possiamo ottenerlo utilizzando la nomenclatura angolare? come: angular.module (MdlName) .controller (CtrlName, function (...) {});
Pedro Justo,

1
Cosa intendi? Un controller è solo una funzione? vale a direangular.module('app').controller('ParentCtrl', ParentCtrl);
Dieterg,

1
scusa hai ragione! Nel metodo "controller as", usando "$ scope.pc.cities;" accedere alle città dei genitori mi sembra un "passo indietro" perché se in childCtrl non abbiamo la proprietà "città" accederà automaticamente alle città dei genitori. Non c'è altro modo per risolvere questo problema?
Pedro Justo,


46

Ho appena controllato

$scope.$parent.someProperty

per me va bene.

e lo sarà

{{$parent.someProperty}}

per la vista.


hmmm, non funziona per me. Mi chiedo se abbia a che fare con il controller come sintassi vm.
zpydee,

Se hai nominato il controller principale, dovresti eliminare $ parent nel modello e avere {{vm.someProperty}}
solbs

8

Quando si utilizza la assintassi, ad esempio ParentController as parentCtrl, per definire un controller, quindi per accedere alla variabile dell'ambito padre nel controller figlio utilizzare quanto segue:

var id = $scope.parentCtrl.id;

Dove si parentCtrltrova il nome del controller principale che utilizza la assintassi ed idè una variabile definita nello stesso controller.


2

Alcune volte potrebbe essere necessario aggiornare le proprietà del genitore direttamente nell'ambito del figlio. ad esempio, è necessario salvare una data e ora del controllo parent dopo le modifiche apportate da un controller figlio. ad es. codice in JSFiddle

HTML

<div ng-app>
<div ng-controller="Parent">
    event.date = {{event.date}} <br/>
    event.time = {{event.time}} <br/>
    <div ng-controller="Child">
        event.date = {{event.date}}<br/>
        event.time = {{event.time}}<br/>
        <br>
        event.date: <input ng-model='event.date'><br>
        event.time: <input ng-model='event.time'><br>
    </div>
</div>

JS

    function Parent($scope) {
       $scope.event = {
        date: '2014/01/1',
        time: '10:01 AM'
       }
    }

    function Child($scope) {

    }

1

È inoltre possibile aggirare l'ereditarietà dell'ambito e archiviare oggetti nell'ambito "globale".

Se nell'applicazione è presente un controller principale che avvolge tutti gli altri controller, è possibile installare un "hook" nell'ambito globale:

function RootCtrl($scope) {
    $scope.root = $scope;
}

Quindi, in qualsiasi controller figlio, è possibile accedere all'ambito "globale" con $scope.root. Tutto ciò che hai impostato qui sarà visibile a livello globale.

Esempio:

function RootCtrl($scope) {
  $scope.root = $scope;
}

function ChildCtrl($scope) {
  $scope.setValue = function() {
    $scope.root.someGlobalVar = 'someVal';
  }
}

function OtherChildCtrl($scope) {
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app ng-controller="RootCtrl">
  
  <p ng-controller="ChildCtrl">
    <button ng-click="setValue()">Set someGlobalVar</button>
  </p>
  
  <p ng-controller="OtherChildCtrl">
    someGlobalVar value: {{someGlobalVar}}
  </p>

</div>


Questo non si adatta davvero. È come definire variabili globali che devono essere univoche in molti file / contesti.
ZachB,

Non vedo un problema di ridimensionamento, ma chiamare la variabile scope qualcosa di diverso da "root" potrebbe essere migliore in altri contesti
Nico Westerdale,

È anche un po 'fastidioso avere uno stato in sospeso più a lungo della vita del sottoalbero del componente che ne ha bisogno.
Roboprog,

0

Credo di aver avuto un dilemma simile di recente

function parentCtrl() {
   var pc = this; // pc stands for parent control
   pc.foobar = 'SomeVal';
}

function childCtrl($scope) {

   // now how do I get the parent control 'foobar' variable?
   // I used $scope.$parent

   var parentFoobarVariableValue = $scope.$parent.pc.foobar;

   // that did it
}

La mia configurazione era un po 'diversa, ma probabilmente la stessa cosa dovrebbe ancora funzionare


0

Da un componente figlio è possibile accedere alle proprietà e ai metodi del componente padre con 'richiedi'. Ecco un esempio:

Genitore:

.component('myParent', mymodule.MyParentComponent)
...
controllerAs: 'vm',
...
var vm = this;
vm.parentProperty = 'hello from parent';

Bambino:

require: {
    myParentCtrl: '^myParent'
},
controllerAs: 'vm',
...
var vm = this;
vm.myParentCtrl.parentProperty = 'hello from child';

0

Super facile e funziona, ma non so perché ...

angular.module('testing')
  .directive('details', function () {
        return {
              templateUrl: 'components/details.template.html',
              restrict: 'E',                 
              controller: function ($scope) {
                    $scope.details=$scope.details;  <=== can see the parent details doing this                     
              }
        };
  });

-1

Forse questo è zoppo, ma puoi anche puntarli entrambi verso un oggetto esterno:

var cities = [];

function ParentCtrl() {
    var vm = this;
    vm.cities = cities;
    vm.cities[0] = 'Oakland';
}

function ChildCtrl($scope) {
    var vm = this;
    vm.cities = cities;
}

Il vantaggio qui è che le modifiche in ChildCtrl ora ripropongono i dati nel genitore.


l'introduzione di variabili globali è pericolosa.
Demenza,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.