2012-12-24 21 views
11

Questa è la mia app config:Impossibile accedere nell'ambito del controllore dalla direttiva

angular.module('myApp', ['myApp.directives', 'myApp.controllers', 'myApp.services']); 

Questo è il mio controller:

angular.module('myApp.controllers', []) 
    .controller('MainCtrl', function ($scope) { 
     $scope.name = 'world'; 
    }); 

Questa è la mia direttiva:

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

directives.directive("hello", function() { 
    return function (scope, elm, attrs) { 
     elm.text("hello, " + scope[attrs.name]); 
    }; 
}); 

e questo è il mio html:

<div ng-controller="MainCtrl"> 
    <h1 hello></h1> 
</div> 

Il è problema è che angolare rende la direttiva come:

ciao, non definito

Invece di:

ciao, mondo

Cosa c'è di sbagliato ?

risposta

7

Si accede scope[attrs.name] ma la direttiva non fornisce un valore per l'attributo name

ci sono 2 opzioni:

  1. cambiare la direttiva per elm.text("hello, " + scope['name']); Questo non è un modo preferito come codici rigidi per un nome proprietà di ambito

  2. Modificare il codice HTML in <h1 hello name="name"></h1>. Questo è meglio, ma sento che utilizza un attributo ridondante

vorrei suggerire di cambiare la direttiva per elm.text("hello, " + scope[attrs['hello']]);

O ancora meglio elm.text("hello, " + scope.$eval(attrs['hello']));

questo modo si ottiene il vantaggio di espressioni come pure (es: <h1 hello="name|uppercase"></h1>) demo

in questo modo il codice HTML sarebbe <h1 hello="name"></h1>

Riguardo al parametro attrs: non è altro che una mappa di stringhe tratte dagli attributi presenti sull'elemento dom.

+0

Questo non funziona. Mi viene ancora 'indefinito'. – vcardillo

+0

@vcardillo aggiungi bene plunker o fai una domanda :) –

+0

Dopo il debug, mi sono reso conto che il mio problema era che stavo usando l'attributo 'scope: {...} 'nel mio Oggetto Definizione Direttiva, creando così un nuovo ambito isolato. Stavo impedendo l'eredità prototipica. – vcardillo

3

È possibile accedere utilizzando scope. Guarda http://jsfiddle.net/rPUM5/

directives.directive("hello", function() { 
    return function (scope, elm, attrs) { 
     elm.text("hello, " + scope.name); 
    }; 
});​ 
+0

Questo è davvero interessante, grazie! Ho trovato pochissima documentazione sull'uso della sintassi del punto che hai. – vcardillo

+3

Questo è veramente sbagliato, l'oggetto 'scope' passato alla funzione di collegamento non è lo stesso' $ scope' che un controllore istanzia, è un riferimento di sola lettura all'ambito in cui la direttiva viene istanziata che dovrebbe essere espressa da 'scope' . – fiatjaf

+1

Chi ha detto che è lo stesso? E non è possibile accedere a $ scope solo scrivendo $ scope. È una violazione della convenzione. Mettere un $ prima dell'ambito non significa che sia l'oggetto dell'ambito del controllore. – Mahbub

6

Si può fare qualcosa che, al momento di scrivere questo, sembra essere senza documenti in angolare (vedi il commento di Mark Rajcok qui: http://docs.angularjs.org/api/ng.$rootScope.Scope).

Dall'interno direttiva:

scope.$parent.name 

Se fate una console.log(scope) su scope (dall'interno della direttiva), vedrete queste proprietà della direttiva.

Tutto ciò detto, non so se questa è una convenzione angolare "corretta", poiché non è documentata e non ho trovato altra documentazione migliore su come accedere al controller all'interno di una direttiva.

1

ho trovato un altro caso:

se si accede a una variabile proveniente da un corpo richiesta Ajax, allora dovete aspettare fino a quando la variabile è impostata.

es:

# in controller 
$http.get('/preview').then((response) -> 
    $scope.tabs = response.data.tabs 
    $scope.master_switch = '1' 
    console.info 'after get response in controller' 
) 

# in directive 
directive('masterSwitch', -> 
    (scope, element, attrs) -> 
    alert 'in directive!' # will show before "after get response in controller" 
    console.info scope.master_switch # is undefined 
    setTimeout(-> console.info(scope.master_switch), 50) # => 1 
Problemi correlati