¡Esta es una revisión vieja del documento!
En el ejemplo de directiva, acTitulo
, que acabamos de ver en el tema anterior el texto del título siempre era “Hola Mundo”, vamos a modificar la directiva para que el texto pueda ser definido por el usuario de la directiva.
La forma de modificar la directiva el simplemente la siguiente:
app.directive("acTitulo",[function() { var directiveDefinitionObject ={ restrict:"E", replace : true, template:"<h1>{{texto}}</h1>" } return directiveDefinitionObject; }]);
texto
que hay en el scope
de la directiva.
Ahora ya podemos tener distintos textos y para ello solo hay que cambiar la propiedad texto
del scope
de la directiva. Pero ahora aparece el problema ya que AngularJS nos permite muchas formas de crear ese nuevo scope
, las distintas formas son:
scope
que hay en el controladorscope
pero que hereda del scope
del controlador, tal y como pasaba con la directiva 4.6 ng-ifscope
que NO hereda del controlador.
Para establecer cual de las 3 usará nuestra directiva , se usa la propiedad scope
del objeto con la definición de la directiva.
Si la propiedad scope
del objeto con la definición de la directiva vale el valor de false
, la directiva usará como scope
exactamente el mismo scope
que tiene el controlador. Este es el funcionamiento por defecto en caso de que no pongamos nada en la propiedad scope
del objeto con la definición de la directiva.
Ahora la directiva quedaría asi:
app.directive("acTitulo",[function() { var directiveDefinitionObject ={ restrict:"E", replace : true, template:"<h1>{{texto}}</h1>", scope:false } return directiveDefinitionObject; }]);
scope
de la directiva es el mismo objeto que el scope
del controladorAhora ya podemos modificar el texto de la directiva únicamente poniendo :
app.controller("PruebaController", function($scope) { $scope.texto="Adios mundo"; });
scope
del controlador y el que use la directiva podría no ser ni consciente de dicha relación.
Hacer ésto sería algo así a usar variables globales dentro de una función. Siendo la variable global el scope
del controlador.
Si la propiedad scope
del objeto con la definición de la directiva vale el valor de true
, la directiva usará como scope
un nuevo scope
pero que ha heredado del scope
del controlador. Este es el caso como el que explicamos en Herencia de $scope.
Ahora la directiva quedaría asi:
app.directive("acTitulo",[function() { var directiveDefinitionObject ={ restrict:"E", replace : true, template:"<h1>{{texto}}</h1>", scope:true } return directiveDefinitionObject; }]);
scope
de la directiva es un nuevo scope
pero que hereda del scope
del controladorComo en el caso anterior ya podemos modificar el texto de la directiva únicamente poniendo :
app.controller("PruebaController", function($scope) { $scope.texto="Adios mundo"; });
scope
del controlador y el que use la directiva tampoco podría no ser ni consciente de dicha relación.
Sigue siendo como usar variables globales dentro de una función. Siendo la variable global el scope
del controlador.
Como ya he dicho, las dos forma anteriores no las recomiendo ya que usamos la directiva acTitulo
de la siguiente forma:
<ac-titulo></ac-titulo>
Y entonces en la página HTML aparece el texto “Adios Mundo”, ¿De donde ha aparecido el texto ese? Parece un poco raro. La forma correcta de usar la directiva debería haber sido la siguiente:
<ac-titulo texto="Adios Mundo"></ac-titulo>
Es decir , las directivas no tienen que usar variables globales como pueda ser el scope
del controlador sino que todo lo que necesiten se debe pasar como argumentos en forma de atributos en la propia directiva. Para ello debemos crear un nuevo objeto JavaScript con { }
en la propiedad scope
del objeto con la definición de la directiva.
Ahora la directiva quedaría asi:
app.directive("acTitulo",[function() { var directiveDefinitionObject ={ restrict:"E", replace : true, template:"<h1>{{texto}}</h1>", scope:{ } return directiveDefinitionObject; }]);
scope
de la directiva es un nuevo scope
que no tiene nada que ver con el scope
del controlador.
Pero ahora nos falta decirle al controlador que queremos que el contenido del atributo texto
de la directiva sea una propiedad del scope
de la directiva. Para hacerlo hay 2 formas distintas que pasamos a ver.
Simplemente tenemos que añadir un atributo al scope
cuya valor sea una arroba ”@”. De esa forma decimos que que queremos copiar el valor del atributo en el scope
.
Ahora la directiva quedaría asi:
app.directive("acTitulo",[function() { var directiveDefinitionObject ={ restrict:"E", replace : true, template:"<h1>{{texto}}</h1>", scope:{ texto:"@" } return directiveDefinitionObject; }]);
texto:”@”
lo que le hemos dicho es que el valor del atributo texto
se copie en la propiedad texto
del scope
de la directiva.Ahora ya podemos usar la directiva así:
<ac-titulo texto="Texto definido en el atributo"></ac-titulo>
Y se generará el siguiente HTML:
<h1>Texto definido en el atributo</h1>
Pero, ¿que pasa si el texto a mostrar está en una propiedad del $scope
del controlador? Por ejemplo en la propiedad mensaje
del $scope
del controlador.
app.controller("PruebaController", function($scope) { $scope.mensaje="Texto definido en el $scope del controlador"; });
Pues no hay más que usar la directiva usando las ya conocidas llaves ”{ }” de AngularJS:
<ac-titulo texto="{{mensaje}}"></ac-titulo>
Y se generará el siguiente HTML:
<h1>Texto definido en el $scope del controlador</h1>
El enlace unidireccional que acabamos de ver al usar ”@” tiene 2 problemas:
texto
del scope
de la directiva no se cambia la propiedad mensaje
del $scope
del controlador$scope
del controlador.
Pues bien, AngularJS nos permite usar el caracter ”=” para enlazar directamente una propiedad del scope
de la directiva con una propiedad del $scope
del controlador.
Lo que queremos poder hacer es lo siguiente:
<ac-titulo texto="mensaje"></ac-titulo>Queremos que lo que ponemos en el atributo
texto
sea tratado como el nombre de una propiedad del $scope
del controlador y no como el texto realmente. Es como añadir una indirección.
PAra ello la dir