2013-04-05 27 views
7

Ho osservato i video di John Linquist e in un video che dà questo come esempio:Una direttiva dovrebbe parlare con un controller in Angular JS?

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

app.controller("AppCtrl", function ($scope) { 
    $scope.loadMoreTweets = function() { 
     alert("Loading tweets!"); 
    } 
} 

app.directive("enter", function() { 
    return function (scope, element, attrs) { 
     element.bind("mouseenter", function() { 
     scope.LoadMoreTweets(); 
     }) 
    } 
} 

Una cosa mi chiedo circa è se la direttiva in questo esempio parlare al controller o sarebbe essere una migliore pratica di programmazione per creare un servizio e poi far parlare la direttiva con un servizio? Immagino di non essere ancora sicuro se è prassi comune che le direttive parlino con i controllori in questo modo.

U tube video

+2

Questo è praticamente il significato dei servizi, suppongo. Solo i miei due centesimi ... – fjdumont

risposta

6

Come avrei fatto

<span enter="loadMoreTweets()">Something</span> 

JS

app.controller('AppController', function ($scope) { 
    $scope.loadMoreTweets = function() { 
     console.log("Loading tweets!"); 
    } 
}) 



app.directive("enter", function() { 
    return { 
    link: function (scope, element, attrs) { 
     element.bind("mouseenter", function() { 
      scope.$apply(attrs.enter) 
     }) 
    } 
    } 
}); 

Demo: Plunker

Un altro modo per ottenere lo stesso

app.directive("enter", function() { 
    return { 
    scope: { 
     callback: '&enter' 
    }, 
    link: function (scope, element, attrs) { 
     element.bind("mouseenter", function() { 
      scope.$apply('callback()') 
     }) 
    } 
    } 
}); 

Demo: 0.123.

+1

Penso che il tuo suggerimento sia praticamente lo stesso di quello che John ha scoperto più avanti nel video. Ma considereresti altro che mettere loadMoreTweets in un servizio piuttosto che nel controller? – Alan2

+0

IMHO: Non penso che il servizio sia la strada da percorrere qui, è necessario che la direttiva sia presa in considerazione solo per il mouseenter, che cosa deve essere fatto nell'inserire il mouse è una preoccupazione separata –

+0

che dice che il controller potrebbe delegare l'effettivo i tweet che caricano sul livello di servizio –

4

E 'pratica comune?

Sì, è prassi comune, le direttive devono spesso accedere a $ scope per variabili e chiamare metodi (come LoadMoreTweets).

Anche nel official docs hanno esempi come ..

scope.$watch(...) 

... fom all'interno di una direttiva (in cui il controller potrebbe essere fare modifiche alla variabile guardato).

È del tutto appropriato che una direttiva comunichi con un controller in questo modo.

È possibile iniettare un controller stesso (non solo l'ambito) nel metodo link di una direttiva. Esamina la sezione "Funzione di collegamento" di http://docs.angularjs.org/guide/directive.

"Il controller è condiviso tra tutte le direttive, che consente alle direttive di utilizzare i controller come canale di comunicazione."

Ma potrebbe Io uso un servizio?

Certo che si potrebbe. La domanda è: perché? Se si sta lavorando con una singola pagina (che visualizza i tweet ad esempio) e il controller ha già una variabile $scope.tweets e il metodo $scope.loadMoreTweets, si stanno complicando le cose se si tenta di inserire un servizio lì dove non è necessario.

D'altra parte i servizi sono perfetti per dati di applicazione, come il profilo utente. Se la tua direttiva ha bisogno di accedere all'utente attualmente connesso, allora ha molto senso farlo tramite il servizio.

Dalla documentazione:

servizi angolari sono single che svolgono compiti specifici comuni alle applicazioni web, come ad esempio il servizio http $ che fornisce l'accesso a basso livello per oggetto XMLHttpRequest del browser.

Se si dispone di un'attività a livello di applicazione che è più adatto per un singleton, utilizzare in ogni caso un servizio. Se hai solo bisogno di accedere/modificare $ scope da una direttiva, parla direttamente al controller o attiva un evento a cui il controller può rispondere.

+0

Ma per questo potrebbe essere usato un servizio? Mi sembra strano avere direttive che si riferiscono ai controllori. Comincerebbe a diventare confuso in una grande applicazione con molte direttive e metodi in tutti i controller che li supportano? Ho visto esempi di controller all'interno delle direttive. Ancora una volta mi sembra fonte di confusione. Perché dovrei farlo? Grazie in anticipo per il vostro consiglio su questo. – Alan2

+0

@Gemma I utilizza i servizi per _application wide_ storage, come tenere traccia dell'autenticazione dell'utente. Se una direttiva ha bisogno di accedere alle informazioni dell'utente corrente, farlo tramite il servizio ha senso. Interagendo però con la _page_ corrente della tua app, che è limitata a un certo controller e scope, mantiene l'app cleaner per avere direttive direttamente in comunicazione con il controller. Questo aiuta? – jszobody

2

Chiamare le funzioni di ambito esterno in questo modo è rischioso, perché presuppone l'ambito circostante.Cosa succederebbe se la direttiva venisse utilizzata in un contesto diverso?

Ci sono migliori [1] strategie che una direttiva riutilizzabile può utilizzare per comunicare con il mondo esterno:

  • Differire sue dipendenze ai servizi. Questo è più appropriato per le funzionalità di sistema. Immagino che non si applichi al tuo esempio.
  • Definizione di un ambito isolato contenente una proprietà &attr associata a un'espressione da un ambito esterno. La direttiva può chiamare quell'espressione come un metodo del suo ambito privato.

Come esempio di questa seconda strategia, ho modificato il tuo esempio. Guardalo in azione qui http://plnkr.co/5uOBNu

var app = angular.module('twitterApp', []); 
app.controller("AppCtrl", function ($scope) { 
    $scope.loadMoreTweets = function() { 
     alert("Loading tweets!"); 
    }; 
}); 

app.directive("specialEnter", function() { 
    return { 
     scope: { 
      onEnter: '&' 
     }, 
     link: function(scope, element, attrs) { 
      element.bind("mouseenter", function() { 
       scope.onEnter(); 
      }); 
     } 
    }; 
}); 

<div ng-controller="AppCtrl"> 
    <div special-enter on-enter="loadMoreTweets()">Hover here!</div> 
</div> 

[1] "Better" in un certo senso di evitare dipendenze hard-wired.

+0

_ puoi chiarire cosa intendi. Non sei d'accordo? Puoi mostrare in poche righe come pensi che dovrebbe essere codificato. Grazie. – Alan2

+0

Sto preparando una modifica estesa. Ma il mio disaccordo riguarda l'utilizzo generico di funzioni e dati dell'ambito esterno, come nell'esempio che hai usato. – Humberto

+0

Grazie mille. Sono molto interessato ad apprendere le tue opinioni. – Alan2

Problemi correlati