Confundido sobre Angularjs transcluded y aislar scopes y enlaces

Estoy luchando por comprender el scope de los modelos y sus vinculaciones con respecto a las directivas que tienen un scope limitado.

Entiendo que restringir el scope 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: '
'+ '

Template title: {{title}}

' + '

Template data.title:{{data.title}}

' + '
' } });

HTML

 

Transclude title:{{title}}

Transclude data.title:{{data.title}}

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/ ):

 

Transclude title: {{title}}

Transclude data.title: {{data.title}}

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: '
' + '' + '

Template title: {{title}}

' + '

Template data.title: {{data.title}}

' + '
'

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.

Tus violines crean tres ámbitos:

  1. un scope asociado con el controlador Ctrl , debido a ng-controller
  2. un scope transcluido directivo, debido a transclude: true
  3. un ámbito de aislamiento de directiva, debido al scope: { ... }

En fiddle1, antes de escribir algo en el cuadro de texto, tenemos lo siguiente:

enter image description here

El scope 003 es el scope asociado con el controlador. Como todavía no escribimos en el cuadro de texto, no hay ninguna propiedad de data . En el scope 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:

enter image description here

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 scope 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 :

enter image description here

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 :

enter image description here

Observe dónde data.title la nueva propiedad data.title : en el scope aislado. Ninguno de los otros ámbitos tiene acceso al scope 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:

 '

Template title: {{title}}

' + '

Template data.title: {{data.title}}

' + '
'

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 scope transcluido ahora es un elemento secundario del scope aislado de la directiva, en lugar de ser un elemento secundario del scope del controlador. Entonces en fiddle1, antes de escribir algo:

enter image description here

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 syntax @ , 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:

enter image description here

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 :

enter image description here

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 :

enter image description here

Observe dónde data.title la nueva propiedad data.title : en el scope aislado. Aunque el scope 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 scope del controlador no tiene estas propiedades definidas.

Después de leer todas las respuestas presentadas, incluidos los fantásticos esquemas de Mark, esta es mi comprensión del scope y su herencia según mi pregunta. Agradecería los comentarios sobre dónde cae este diagtwig, para poder actualizarlo adecuadamente. Espero que simplemente brinde una visión diferente de lo que Mark ha presentado:

Herencia de alcance

Bien pedido, por cierto! Espero que mi respuesta sea tan eloquent …

La respuesta tiene que ver con cómo los elementos transclusos obtienen su scope.

Para resumir, tienes dos ámbitos:

  1. El scope del controlador, que tiene $scope.data.title . (Agregado implícitamente por su elemento de input )
  2. El scope 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 scope del controlador , y el HTML de la plantilla está en el scope de la directiva . Entonces, el HTML transcluido no sabe nada sobre el title , y el scope 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 scope principal , en este caso el scope del controlador. Por diseño, los elementos transcriptos no saben que están en una directiva, y por lo tanto no tienen acceso al scope de la directiva.

Las plantillas directivas, por otro lado, tendrán acceso solo al scope 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)

http://jsfiddle.net/yWWVs/2/