Aggiorna la variabile di ambito padre in AngularJS


113

Ho due controller, uno avvolto nell'altro. Ora so che l'ambito figlio eredita le proprietà dall'ambito padre, ma esiste un modo per aggiornare la variabile dell'ambito padre? Finora non ho trovato soluzioni ovvie.

Nella mia situazione ho un controller di calendario all'interno di un modulo. Vorrei aggiornare le date di inizio e di fine dall'ambito padre (che è il modulo) in modo che il modulo abbia le date di inizio e di fine quando viene inviato.


sembra che il tuo controller del calendario dovrebbe essere una direttiva.
Giona

Risposte:


193

È necessario utilizzare un oggetto (non una primitiva) nell'ambito padre e quindi sarà possibile aggiornarlo direttamente dall'ambito figlio

Genitore:

app.controller('ctrlParent',function($scope){
    $scope.parentprimitive = "someprimitive";
    $scope.parentobj = {};
    $scope.parentobj.parentproperty = "someproperty";
});

Bambino:

app.controller('ctrlChild',function($scope){
    $scope.parentprimitive = "this will NOT modify the parent"; //new child scope variable
    $scope.parentobj.parentproperty = "this WILL modify the parent";
});

Demo funzionante : http://jsfiddle.net/sh0ber/xxNxj/

Vedi Quali sono le sfumature dell'eredità prototipica / prototipica dell'ambito in AngularJS?


1
Ottengo questo errore quando provo a implementarlo: "Impossibile impostare la proprietà" parentproperty "di undefined".
Malcr001

Puoi inserire il tuo codice? Funziona nella demo del violino. Se il controllo del calendario utilizza l'ambito isolato, non erediterà dall'ambito padre, quindi è necessario passare il valore all'ambito della direttiva.
Dan

Scusa se ho dimenticato questa domanda. L'ho accettato perché alla fine sono riuscito a farlo funzionare con l'aiuto di questa risposta.
Malcr001

Capisco che mettere {{parentobj.parentproperty}} nell'elemento div ctrlParent sia ciò che dichiara l'oggetto parentobj e imposta questo oggetto come nell'ambito di ctrlParent. È un presupposto corretto?
Stephane

1
Grazie, funziona! Dovrei assolutamente documentarmi su questo (eredità prototipica e primitive). Puoi consigliarmi una buona lettura che spieghi un po 'di più del tuo link SO?
jvannistelrooy

116

C'è un altro modo per eseguire questa operazione e per non utilizzare la $scope.$parentvariabile.

Basta preparare un metodo per modificare il valore nell'ambito padre e utilizzarlo in quello figlio. Come questo:

app.controller('ctrlParent',function($scope) {
  $scope.simpleValue = 'x';
  $scope.changeSimpleValue = function(newVal) {
    $scope.simpleValue = newVal;
  };
});

app.controller('ctrlChild',function($scope){
    $scope.changeSimpleValue('y');
});

Funziona anche e ti dà un maggiore controllo sui cambiamenti di valore.

È quindi possibile anche chiamare il metodo anche in HTML come: <a ng-click="changeSimpleValue('y')" href="#">click me!</a>.


1
Buona soluzione! questo funziona perché quando qualcosa non viene trovato nell'attuale $ scope, Angular cerca in $ parent. docs.angularjs.org/guide/scope (vedere "Gerarchie di ambito").
Elo

Mi piace questa risposta, non c'è bisogno di creare un oggetto non necessario.
grimmdude

3
Lettori futuri: tutti questi commenti di alta cinque sono un po 'fuorvianti. La creazione di due funzioni setter (che sono "oggetti non necessari") per ogni variabile è un goffo e non necessario kludge di ereditarietà e non è il modo angolare. Misko Hevery, il creatore di Angular, tiene un discorso in cui insegna "Ogni volta che hai ng-model ci deve essere un punto da qualche parte. Se non hai un punto, lo stai sbagliando." Video Misko @ 29:19
Dan

come posso applicare questa soluzione utilizzando la sintassi controllerAS?
niran

6

Funziona anche (ma non sono sicuro che segua le migliori pratiche o meno)

app.controller('ctrlParent',function($scope) {
    $scope.simpleValue = 'x';
});

app.controller('ctrlChild',function($scope){
    $scope.$parent.simpleValue = 'y';
});

1
Hai ragione, usando $ scope. $ Parent.value funzionerà nella maggior parte dei casi, tuttavia di solito non è l'idea migliore da usare estensivamente poiché può diventare difficile da gestire in progetti più grandi e complicati.
Alex Johnson

4

Quando si assegna un attributo primitivo a uno scope, è sempre locale allo scope (possibilmente creato al volo), anche se uno scope padre ha un attributo con lo stesso nome. Questa è una decisione di design e, secondo me, una buona decisione.

Se è necessario modificare alcune primitive (int, booleani, stringhe) nello scope genitore, dalla vista, è necessario che sia un attributo di un altro oggetto in quello scope, quindi l'assegnazione può leggere:

<a ng-click="viewData.myAttr = 4">Click me!</a>

e, a sua volta:

  1. ottenere l' viewDataoggetto da qualsiasi ambito in cui è definito
  2. assegna 4 al suo myAttrattributo.

4

Per accedere alle variabili dichiarate nel genitore, dovremmo usare $ parent nel controller figlio o nel file modello

Nel controller

$scope.$parent.varaiable_name

Nel modello html

ng-model="$parent.varaiable_name"
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.