javascript - examples - angularjs tutorial
El enlace bidireccional no funciona en directiva con alcance transcluido (3)
El error de sintaxis significa que ha escrito mal algo. No está relacionado con un marco / biblioteca particular. Probablemente olvidaste agregar "," o cerrar una parátesis. Compruébalo de nuevo
Tengo un cuadro de texto en un controlador que está vinculado al name
modelo. Hay una directiva dentro del controlador y hay otro cuadro de texto dentro de la directiva que está vinculado al mismo name
modelo:
<div class="border" ng-controller="editCtrl">
Controller: editCtrl <br/>
<input type="text" ng-model="name" />
<br/>
<tabs>
Directive: tabs <br/>
<input type="text" ng-model="name"/>
</tabs>
</div>
mod.directive(''tabs'', function() {
return {
restrict: ''E'',
transclude: true,
template:
''<div class="border" ng-transclude></div>'',
};
});
Cuando escribe algo en el cuadro de texto externo, se refleja en el cuadro de texto interno, pero si escribe algo en el cuadro de texto interno deja de funcionar, es decir, ambos cuadros de texto ya no reflejan el mismo valor.
Ver ejemplo en: http://jsfiddle.net/uzairfarooq/MNBLd/
También intenté usar un enlace de dos vías attr ( scope: {name: ''=''}
) pero da error de sintaxis. Y usando scope: {name: ''@''}
tiene el mismo efecto.
Cualquier ayuda sería muy apreciada.
Además de la respuesta aceptada, este artículo realmente me ayudó a comprender la herencia prototípica en scpus infantiles. Recomiendo encarecidamente a cualquiera que tenga problemas con los ámbitos que lo lea a fondo.
Creo que el problema tiene que ver con el alcance. Inicialmente, el cuadro de texto interno no tiene un name
establecido, por lo que se hereda del alcance externo. Esta es la razón por la cual escribir en la caja externa se refleja en la caja interna. Sin embargo, una vez que se escribe en el cuadro interno, el ámbito interior ahora contiene name
que significa que ya no está vinculado al name
externo, por lo que el cuadro de texto externo no se sincroniza.
La forma adecuada de corregir es almacenar modelos en el alcance, no sus valores. Lo arreglé en http://jsfiddle.net/pdgreen/5RVza/ El truco es crear un objeto modelo ( data
) y hacer referencia a valores en él.
El código incorrecto modifica el alcance en la directiva, el código correcto modifica el modelo en el alcance de la directiva. Esta sutil diferencia permite que la herencia del alcance funcione correctamente.
Creo que la forma en que Miško Hevery lo expresó fue que el alcance debería ser solo de escritura en el controlador y de solo lectura en las directivas.
actualización: referencia: https://www.youtube.com/watch?v=ZhfUv0spHCY#t=29m19s
Una directiva con transclude: true
resultados transclude: true
en la directiva que crea un nuevo alcance infantil (transcluido). Este nuevo ámbito hereda prototípicamente del alcance principal. En su caso, el alcance principal es el alcance asociado con el controlador editCtrl.
El uso de enlace de datos bidireccional en un ámbito secundario (es decir, ng-model) para vincularse a una propiedad de ámbito principal que contiene un valor primitivo (por ejemplo, name
) siempre causa problemas; bueno, debería decir que no funciona como esperado. Cuando se cambia la propiedad de ámbito en el elemento secundario (por ejemplo, escribe en el segundo cuadro de texto), el elemento secundario crea una nueva propiedad de ámbito que oculta / sombrea la propiedad de ámbito principal del mismo nombre. Si la propiedad principal contiene un valor primitivo, ese valor se copia (esencialmente) a la propiedad secundaria cuando se crea la propiedad secundaria . Los cambios futuros en el alcance del niño (por ejemplo, el segundo cuadro de texto) solo afectan la propiedad del niño.
Antes de escribir en el segundo cuadro de texto (es decir, antes de que se cambie la propiedad en el elemento secundario), el ámbito hijo / transcluido encuentra la propiedad del name
en el ámbito principal a través de herencia prototípica (línea discontinua en la imagen a continuación). Esta es la razón por la cual los dos cuadros de texto inicialmente permanecen sincronizados. A continuación, si escribe "Marcar" en el primer cuadro de texto, así es como se ven los ámbitos:
Creé un violín donde puedes examinar los dos ámbitos. Haga clic en el enlace "mostrar alcance" junto al segundo cuadro de texto antes de escribir en el segundo cuadro de texto. Esto le permitirá ver el alcance del hijo transcluido. Notará que no tiene una propiedad de name
en este punto. Borre la consola, escriba en el segundo cuadro de texto, luego haga clic en el enlace nuevamente. Notará que el ámbito hijo ahora tiene una propiedad de name
, y el valor inicial era el valor que tenía la propiedad padre ("Marcar"). Si escribió "Me gusta angular" en el segundo cuadro de texto, así es como se ven los ámbitos:
Hay dos soluciones:
- haga lo que sugiere @ pgreen2 (esta es la solución de "mejores prácticas"): use un objeto en lugar de un primitivo. Cuando se utiliza un objeto, el alcance hijo / transcluido no obtiene una nueva propiedad. Solo la herencia prototípica está en juego aquí. En la siguiente imagen, suponga que el $ edit de editCtrl tiene este objeto definido:
$scope.myObject = { name: "Mark", anotherProp: ... }
: - use $ parent en el ámbito hijo (esta es una solución frágil, y no recomendada, ya que hace suposiciones sobre la estructura HTML): use
ng-model="$parent.name"
dentro de la <input> que está dentro de las <tabulaciones> elemento. La primera imagen de arriba muestra cómo funciona esto.
Se produce un error de sintaxis cuando se usa el scope: {name: ''=''}
porque cuando se utiliza el enlace de datos bidireccional (es decir, cuando se usa ''=''), no se permite la interpolación, es decir, {{}} no se puede usar. En lugar de <tabs name="{{name}}">
use <tabs name="name">
.
Usar ''@'' funciona igual que el caso de transcluir porque ng-transclude usa el alcance transcluido, no el alcance aislado que se crea al usar el scope: { ... }
.
Para (lotes) más información sobre los ámbitos (incluidas las imágenes) ver
¿Cuáles son los matices del alcance de la herencia prototípica / prototípica en AngularJS?