angularjs - link - sito con angular




Chiamare una funzione controller da una direttiva senza ambito isolato in AngularJS (3)

L'unico problema che ho è, come posso chiamare un metodo sull'ambito genitore se non lo faccio passare su un ambito isolato?

Ecco un jsfiddle dove NON sto usando scope isolato e il ng-hide sta funzionando bene, ma, ovviamente, la chiamata a confirmAction () non funziona e non so come farlo funzionare.

Innanzitutto un piccolo punto: in questo caso l'ambito del controller esterno non è l'ambito genitore dell'ambito della direttiva; l'ambito del controller esterno è l'ambito della direttiva. In altre parole, i nomi delle variabili utilizzati nella direttiva verranno esaminati direttamente nell'ambito del controller.

Successivamente, scrivendo attrs.confirmAction() non funziona perché attrs.confirmAction per questo pulsante,

<button ... confirm-action="doIt()">Do It</button>

è la stringa "doIt()" e non è possibile chiamare una stringa, ad esempio "doIt()"() .

La tua domanda è davvero:

Come posso chiamare una funzione quando ho il suo nome come stringa?

In JavaScript, si chiamano per lo più funzioni usando la notazione a punti, come questa:

some_obj.greet()

Ma puoi anche usare la notazione array:

some_obj['greet']

Nota come il valore dell'indice è una stringa . Quindi, nella tua direttiva puoi semplicemente fare questo:

  link: function (scope, element, attrs) {

    element.bind('click', function (e) {

      if (confirm(attrs.confirm)) {
        var func_str = attrs.confirmAction;
        var func_name = func_str.substring(0, func_str.indexOf('(')); // Or func_str.match(/[^(]+/)[0];
        func_name = func_name.trim();

        console.log(func_name); // => doIt
        scope[func_name]();
      }
    });
  }

Non riesco a trovare un modo per chiamare una funzione sull'ambito principale da una direttiva senza utilizzare l'ambito isolato. So che se utilizzo un ambito isolato, posso semplicemente usare "&" nell'isolato per accedere alla funzione sull'ambito principale, ma l'utilizzo di un ambito isolato quando non è necessario ha delle conseguenze. Considera il seguente codice HTML:

<button ng-hide="hideButton()" confirm="Are you sure?" confirm-action="doIt()">Do It</button>

In questo semplice esempio, voglio mostrare una finestra di dialogo di conferma JavaScript e chiamare solo doIt () se fanno clic su "OK" nella finestra di dialogo di conferma. Questo è semplice utilizzando un ambito isolato. La direttiva sarebbe simile a questa:

.directive('confirm', function () {
    return {
        restrict: 'A',
        scope: {
            confirm: '@',
            confirmAction: '&'
        },
        link: function (scope, element, attrs) {
            element.bind('click', function (e) {
                if (confirm(scope.confirm)) {
                    scope.confirmAction();
                }
            });
        }
    };
})

Ma il problema è che, poiché sto usando un ambito isolato, ng-hide nell'esempio sopra non esegue più l'ambito genitore , ma piuttosto l'ambito isolato (dato che l'uso di un ambito isolato su qualsiasi direttiva fa sì che tutte le direttive su quell'elemento utilizzare l'ambito isolato). Ecco un jsFiddle dell'esempio sopra dove ng-hide non funziona. (Nota che in questo violino, il pulsante dovrebbe nascondersi quando si digita "sì" nella casella di input.)

L'alternativa sarebbe quella di NON usare un ambito isolato , che in realtà è ciò che voglio veramente qui, poiché non è necessario isolare il campo di applicazione di questa direttiva. L'unico problema che ho è, come posso chiamare un metodo sull'ambito genitore se non lo faccio passare su un ambito isolato ?

Ecco un jsfiddle dove NON sto usando scope isolato e il ng-hide sta funzionando bene, ma, ovviamente, la chiamata a confirmAction () non funziona, e non so come farlo funzionare.

Si prega di notare, la risposta che sto cercando è come chiamare le funzioni sullo scope esterno SENZA usare un ambito isolato. E non mi interessa fare in modo che questa finestra di conferma funzioni in altro modo, perché il punto di questa domanda è capire come fare chiamate all'ambito esterno ed essere ancora in grado di far funzionare altre direttive contro l'ambito genitore.

In alternativa, sarei interessato a conoscere soluzioni che utilizzano un ambito isolato se altre direttive funzioneranno ancora contro l'ambito genitore , ma non penso che sia possibile.


Chiamare esplicitamente hideButton sull'ambito principale.

Ecco il violino: http://jsfiddle.net/pXej2/5/

Ed ecco l'HTML aggiornato:

<div ng-app="myModule" ng-controller="myController">
    <input ng-model="showIt"></input>
    <button ng-hide="$parent.hideButton()" confirm="Are you sure?" confirm-action="doIt()">Do It</button>
</div>

Vuoi utilizzare il servizio $ parse in AngularJS.

Quindi per il tuo esempio:

.directive('confirm', function ($parse) {
    return {
        restrict: 'A',

        // Child scope, not isolated
        scope : true,
        link: function (scope, element, attrs) {
            element.bind('click', function (e) {
                if (confirm(attrs.confirm)) {
                    scope.$apply(function(){

                        // $parse returns a getter function to be 
                        // executed against an object
                        var fn = $parse(attrs.confirmAction);

                        // In our case, we want to execute the statement in 
                        // confirmAction i.e. 'doIt()' against the scope 
                        // which this directive is bound to, because the 
                        // scope is a child scope, not an isolated scope. 
                        // The prototypical inheritance of scopes will mean 
                        // that it will eventually find a 'doIt' function 
                        // bound against a parent's scope.
                        fn(scope, {$event : e});
                    });
                }
            });
        }
    };
});

C'è una cosa da fare con l'impostazione di una proprietà usando $ parse, ma ti lascerò attraversare quel ponte quando ci arrivi.





angularjs-scope