template - create component angularjs
Confundido sobre Angularjs transcluded y aislar alcances y enlaces (3)
Bien pedido, por cierto! Espero que mi respuesta sea tan elocuente ...
La respuesta tiene que ver con cómo los elementos transclusos obtienen su alcance.
Para resumir, tienes dos ámbitos:
- El alcance del controlador, que tiene
$scope.data.title
. (Agregado implícitamente por su elemento deinput
) - El alcance de la directiva, que tiene
$scope.title
.
Cuando cambia el $scope.data.title
del controlador, el $scope.data.title
directiva también cambia.
También tiene dos secciones de HTML, la transcluded y la plantilla. Lo que sucede es que el HTML transcluido está en el alcance del controlador , y el HTML de la plantilla está en el alcance de la directiva . Entonces, el HTML transcluido no sabe nada sobre el title
, y el alcance de la plantilla no sabe nada sobre data.title
Esto es exactamente a lo que se destinó la Transclusión: permitir que los elementos secundarios de una directiva mantengan su alcance principal , en este caso el alcance del controlador. Por diseño, los elementos transcriptos no saben que están en una directiva, y por lo tanto no tienen acceso al alcance de la directiva.
Las plantillas directivas, por otro lado, tendrán acceso solo al alcance de la directiva.
He cambiado un poco el código para hacer que los nombres sean un poco más claros (la misma funcionalidad, sin embargo)
Estoy luchando por comprender el alcance de los modelos y sus vinculaciones con respecto a las directivas que tienen un alcance limitado.
Entiendo que restringir el alcance de una directiva significa que controller. $ Scope y directive.scope ya no son la misma cosa. Sin embargo, estoy confundido acerca de cómo la colocación de modelos dentro de la plantilla directiva o en el html afecta el enlace de datos. Siento que me estoy perdiendo algo muy fundamental y para seguir adelante necesito entender esto.
Tome el siguiente código (violín aquí: http://jsfiddle.net/2ams6/ )
JavaScript
var app = angular.module(''app'',[]);
app.controller(''Ctrl'',function($scope){
});
app.directive(''testel'', function(){
return {
restrict: ''E'',
scope: {
title: ''@''
},
transclude: true,
template: ''<div ng-transclude>''+
''<h3>Template title: {{title}}</h3>'' +
''<h3>Template data.title:{{data.title}}</h3>'' +
''</div>''
}
});
HTML
<div ng-app=''app''>
<div ng-controller="Ctrl">
<input ng-model="data.title">
<testel title="{{data.title}}">
<h3>Transclude title:{{title}}</span></h3>
<h3>Transclude data.title:{{data.title}}</h3>
</testel>
</div>
</div>
El modelo solo actualiza {{title}}
dentro de la plantilla y {{data.title}}
en la transclusión. ¿Por qué no {{title}}
en la transclusión ni {{data.title}}
en la plantilla?
Moviendo la entrada dentro de la transclusión como tal (violín aquí: http://jsfiddle.net/eV8q8/1/ ):
<div ng-controller="Ctrl">
<testel title="{{data.title}}">
<input ng-model="data.title">
<h3>Transclude title: <span style="color:red">{{title}}</span></h3>
<h3>Transclude data.title: <span style="color:red">{{data.title}}</span></h3>
</testel>
</div>
ahora significa que solo transclude {{data:title}}
se actualiza. ¿Por qué no la plantilla {{title}}
o {{data.title}}
, ni la transclude {{title}}
?
Y, finalmente, moviendo la entrada dentro de la plantilla, así (violín aquí: http://jsfiddle.net/4ngmf/2/ ):
template: ''<div ng-transclude>'' +
''<input ng-model="data.title" />'' +
''<h3>Template title: {{title}}</h3>'' +
''<h3>Template data.title: {{data.title}}</h3>'' +
''</div>''
Ahora significa que solo la plantilla {{data.title}}
se actualiza. Nuevamente, ¿por qué no las otras 3 fijaciones?
Espero que haya algo obvio mirándome a la cara y me lo estoy perdiendo. Si logras que obtenga esto, te compraré una cerveza, o te daré algunos puntos, o alguna otra cosa similar. Muchas gracias.
Después de leer todas las respuestas presentadas, incluidos los fantásticos esquemas de Mark, esta es mi comprensión del alcance y su herencia según mi pregunta. Agradecería los comentarios sobre dónde cae este diagrama, para poder actualizarlo adecuadamente. Espero que simplemente brinde una visión diferente de lo que Mark ha presentado:
Tus violines crean tres ámbitos:
- un alcance asociado con el controlador
Ctrl
, debido ang-controller
- un alcance transcluido directivo, debido a
transclude: true
- un ámbito de aislamiento de directiva, debido al
scope: { ... }
En fiddle1, antes de escribir algo en el cuadro de texto, tenemos lo siguiente:
El alcance 003 es el alcance asociado con el controlador. Como todavía no escribimos en el cuadro de texto, no hay ninguna propiedad de data
. En el alcance aislado 004, vemos que se creó una propiedad de title
, pero está vacía. Está vacío porque el ámbito primario aún no tiene una propiedad data.title
.
Después de escribir my title
en el cuadro de texto, ahora tenemos:
El ámbito del controlador 003 ahora tiene una nueva propiedad de objeto de data
(por lo que es de color amarillo), que tiene una propiedad de title
ahora configurada en my title
. Como el title
propiedad de ámbito aislado es de enlace unidireccional al valor interpolado de data.title
, también obtiene el valor de my title
(el valor es de color amarillo porque ha cambiado).
El ámbito transcripto hereda prototípicamente del ámbito del controlador, por lo que dentro del HTML transcluido, angular puede seguir la cadena del prototipo y buscar $scope.data.title
en el ámbito primario (pero $scope.title
no existe allí).
El alcance aislado solo tiene acceso a sus propias propiedades, por lo tanto, solo el title
propiedad.
En fiddle2, antes de escribir tenemos la misma imagen que en fiddle1.
Después de escribir my title
:
Observe dónde data.title
la nueva propiedad data.title
: en el ámbito transcluido. El ámbito de aislamiento todavía está buscando data.title
en el ámbito del controlador, pero no está allí esta vez, por lo que su valor de propiedad del title
permanece vacío.
En fiddle3, antes de tipear tenemos la misma imagen que en fiddle1.
Después de escribir my title
:
Observe dónde data.title
la nueva propiedad data.title
: en el alcance aislado. Ninguno de los otros ámbitos tiene acceso al alcance aislado, por lo que la cadena de my title
no aparecerá en ningún otro lado.
Actualización para Angular v1.2:
Con el cambio eed299a Angular ahora borra el punto de transclusión antes de la transclusión, por lo que las partes Template title: ...
y Template data.title: ...
no se mostrarán a menos que modifiques la plantilla de manera que ng-transclude
sea en sí misma, tal como:
''<h3>Template title: <span style="color:red">{{title}}</span></h3>'' +
''<h3>Template data.title: <span style="color:red">{{data.title}}</span></h3>'' +
''<div ng-transclude></div>''
En la actualización a continuación para Angular v1.3, se realizó este cambio de plantilla.
Actualización para Angular v1.3 +:
Desde Angular v1.3, el alcance transcluido ahora es un elemento secundario del alcance aislado de la directiva, en lugar de ser un elemento secundario del alcance del controlador. Entonces en fiddle1, antes de escribir algo:
Las imágenes de esta actualización se dibujan con la herramienta Peri$scope , por lo que las imágenes son un poco diferentes. El @
indica que tenemos una propiedad de ámbito aislado que usa la sintaxis @
, y el fondo rosado significa que la herramienta no pudo encontrar una referencia ancestral para el mapeo (lo cual es cierto, ya que no escribimos nada en el cuadro de texto todavía) )
Después de escribir my title
en el cuadro de texto, ahora tenemos:
Las propiedades de aislamiento que usan @
binding siempre mostrarán el resultado de la cadena interpolada en el ámbito aislado después del símbolo @
. Peri $ scope también pudo encontrar este valor de cadena exacto en un ámbito ancestral, por lo que también muestra una referencia a esa propiedad.
En el violín 2, antes de escribir tenemos la misma imagen que en fiddle1.
Después de escribir my title
:
Observe dónde data.title
la nueva propiedad data.title
: en el ámbito transcluido. El ámbito de aislamiento todavía está buscando data.title
en el ámbito del controlador, pero no está allí esta vez, por lo que su valor de propiedad del title
permanece vacío.
En fiddle3, antes de tipear tenemos la misma imagen que en fiddle1.
Después de escribir my title
:
Observe dónde data.title
la nueva propiedad data.title
: en el alcance aislado. Aunque el alcance transcluido tiene acceso al ámbito aislado a través de la relación $parent
, no buscará title
o data.title
: solo se verá en el ámbito del controlador (es decir, seguirá la herencia del prototipo), y el alcance del controlador no tiene estas propiedades definidas.