Modificare l’Attributo Dall’interno la Direttiva

Utilizzo Di AngularJS. Ho una direttiva che voglio avere due vie di collegamento dati. La direttiva avrà un attributo chiamato “attiva”. Inizialmente, il valore di “attivare” sarà “1”.

Della direttiva funzione di collegamento, controllare se “attiva” è uguale a “1”. Se è così, non cambierà “attivare” a 0, ma fare un po ‘ di altra roba.

Poi, se voglio la direttiva di fare alcune cose di nuovo, nel controller, mi cambierà “attiva” per “1” di nuovo. Poiché la direttiva ha l’orologio, si ripete il ciclo.

Purtroppo, ogni volta che faccio questo, ho “l’Espressione ‘0’ utilizzato con la direttiva ‘testDirective’ non è cedibile!” o “Non assegnabile modello di espressione: 1 (direttiva: testDirective)”.

Qui è HTML:

<body ng-app="app">
    <test-directive activate="1"></test-directive>    
</body>

Qui è JS :

var app = angular.module('app', []);


app.directive('testDirective', function() {
    return {
        restrict: 'E',
        scope: {
            activate : '='
        },


        link: function( scope, elem, attrs, controller ) {
            var el = elem[0];

            var updateContent = function() {
                el.innerText = 'Activate=' + scope.activate;
            };

            updateContent();
            attrs.$observe( 'activate', function() {
                console.log('Activate=' + scope.activate);
                if( scope.activate == '1') {
                    scope.activate = '0'
                    updateContent();
                }
            });
        }
    }
});      

Qui è su jsFiddle : http://jsfiddle.net/justbn/mgSpY/3/

Perché non è possibile modificare il valore memorizzato nella direttiva attributo? Sto usando 2 modo vincolante.

Docs dire ” Se l’ambito principale di proprietà non esiste, sarà lanciare un NON_ASSIGNABLE_MODEL_EXPRESSION eccezione.”

NOTA: Il contenuto di aggiornamento mostra correttamente il valore di “attivare”. Tuttavia, il valore di “attivare” in “” non si aggiorna.

Tuttavia, che non ha senso per me, come il padre ambito di proprietà NON esiste.

Tutte le idee?

 

2 Replies
  1. 12

    Anche se sono d’accordo con l’uso di $watch invece di attrs.$observe che non è il motivo principale per il messaggio di errore che si sta ottenendo.

    Il problema è che si cerca di assegnare un valore a una non-espressione assegnabile – come il messaggio di errore dice : Non-assignable model expression: 1 (directive: testDirective)

    Non assegnabili espressione, in questo caso è il numero “1”

    <test-directive activate="1">

    Si riesce a passare il valore iniziale (1) alla direttiva, ma quando la direttiva tenta di aggiornare il valore dell’attributo attivare non può essere cambiato, perché è un numero.

    Così che cosa dovete fare è cambiare il tipo di una variabile, in modo da poter aggiornare il valore in un momento successivo.

    Vedere il codice qui sotto, dove ho inizializzare una variabile $campo di applicazione chiamata attiva.initialValue tramite un controller.

    E ho usato anche $watch invece di attrs.$observe.

    Ho aggiunto il $timeout solo per simulare un evento per modificare il valore attivare dopo 2 secondi.

    HTML

    <body ng-app="app" ng-controller="appCtrl">
        <test-directive activate="activate.initialValue"></test-directive>    
    </body>

    JS

    var app = angular.module('app', []);
    
    app.controller('appCtrl', function($scope){
        $scope.activate = {
            initialValue : 1
        }
    });
    
    var app = angular.module('app', []);
    
    app.controller('appCtrl', function($scope){
        $scope.activate = {
            initialValue : 2
        }
    });
    
    app.directive('testDirective', function($timeout) {
        return {
            restrict: 'E',
            scope: {
                activate : '='
            },      
            link: function(scope, elem, attrs) {
                scope.$watch('activate', function(newValue, oldValue){
                   console.log('activate has changed', newValue);
                });
    
                 $timeout(function(){ 
                        scope.activate = 0;     
                    }, 2000);
            },
            template: "{{activate}}"
        }
    });   

    Si può anche vedere che lavorano qui (http://jsfiddle.net/mgSpY/63/).

    E qui è AngularJS documentazione ufficiale su di esso (http://docs.angularjs.org/error/ngModel:nonassign)

    • dluz : “io ho dato la risposta a Michael per una soluzione di lavoro. Ma ho appena cambiato per voi. È spiegato in modo che io possa capire meglio. Grazie mille!
    • Justin: felice di aiutarti! 🙂
    • Questa è parte della risposta per me. Ho anche avuto ambito.$apply() dopo la modifica, o $guarda non innescare.
    • Ho modificato il tuo direttiva leggermente così non ci sarebbe alcun bisogno di chiamare in modo esplicito su scope.$apply()
    • Hai salvato la mia giornata !
  2. 3

    Per monitorare una proprietà del campo di applicazione, si dovrebbe utilizzare scope.$watch invece di attrs.$observe:

    link: function(scope, elem, attrs, controller) {
      var el = elem[0];
    
      var updateContent = function() {
        el.innerText = 'Activate=' + scope.activate;
      };
    
      scope.$watch('activate', function(value) {                               
        console.log('Activate=', value);
        if(value === 1) {
          scope.activate = '0'                    
        }
        updateContent();
      });
    }

    jsFiddle qui.

    Notare che ho rimosso la updateContent chiamata dalla funzione di collegamento, perché si può solo accedere in modo sicuro una proprietà del campo di applicazione all’interno di un $watch richiamata, a meno che non si può garantire che il valore associato a tale proprietà è disponibile prima che la direttiva è elaborato dal Angolare.

    $observedeve essere utilizzato solo per osservare/watch la variazione di valore di un DOM attributo che contiene l’interpolazione (per esempio, value="{{ value }}"). Check out questo QUINDI, domanda per capire meglio.

    • Michael : Grazie mille per la risposta. Sicuramente funziona correttamente ora. Non riesco esattamente a capire come utilizzare ‘ambito.attivare=0 funziona ora, ma non prima. Io sono ancora a cambiare il valore dell’attributo stesso.
    • Io aggiornare la risposta con ulteriori informazioni. Spero che le cose in chiaro su.

Lascia un commento