Vea que DEMO

<body ng-controller="MainCtrl">

    {{ obj }}

    <dir>
      <input type="text" ng-model="obj" />
    </dir>

  </body>

Por qué cuando cambio la variable de alcance obj en la directiva personalizada con ng-transclude no la cambio en MainCtrl $scope.obj.

Pero cuando tengo $scope.obj = { name : 'test' }; en MainCtrl, el enlace bidireccional funciona como esperaba.

Consulte la DEMO en funcionamiento.

<body ng-controller="MainCtrl">

    {{ obj.name }}

    <dir>
      <input type="text" ng-model="obj.name" />
    </dir>

  </body>

¿Cuál es la explicación de este comportamiento?

0
Dilyan Dimitrov 13 feb. 2015 a las 19:03

3 respuestas

La mejor respuesta

Existe un problema al acceder a las variables primitivas en el ámbito principal desde el ámbito secundario. Tiene un alcance secundario porque tener transclude: true crea un alcance nuevo.

Realmente debería leer este artículo para comprender en profundidad lo que está sucediendo. .

Lo más destacado del artículo:

La herencia del alcance es normalmente sencilla y, a menudo, ni siquiera necesita saber que está sucediendo ... hasta que pruebe el enlace de datos bidireccional (es decir, elementos de formulario, modelo ng) a una primitiva (p. Ej., Número, cadena, booleano) definido en el ámbito principal desde dentro del ámbito secundario.

Y

Este problema con las primitivas se puede evitar fácilmente siguiendo la "mejor práctica" de tener siempre un '.' en sus modelos ng.

Lo que sucede es que no se consulta el ámbito padre cuando se trata de primitivas. Es una cosa de Javascript, ni siquiera de Angular.

También he creado una Demostración del objeto que se oculta del alcance secundario. (sombreando un objeto no primitivo):

app.directive('dir', function () {
    return {
        restrict: 'E',

        scope: true,
        template: "<div><input type=\"text\" ng-model=\"obj.name\" /></div>",
        link: function(scope, element, attrs) {
          scope.obj = {name : "newname"}; 
        }

    };
});
2
Omri Aharon 13 feb. 2015 a las 16:26

Esto funciona cuando consulta el valor de obj del mismo alcance, el alcance de la directiva:

<body ng-controller="MainCtrl">

  {{ obj }}

  <dir>
    <p>
      The following text will be synched with the model:
    </p>
    <span>{{ obj }}</span>
    <br/>
    <input type="text" ng-model='obj' />
  </dir>

</body>
0
Yiling 3 mar. 2015 a las 23:21

El html transcluido genera un alcance secundario del MainCtrl cuando se escribe esta nueva propiedad (obj), el alcance secundario genera uno nuevo que sobrescribe al padre.

No se consulta la cadena de prototipos y se agrega una nueva propiedad aString a childScope. Esta nueva propiedad oculta / sombrea la propiedad parentScope con el mismo nombre.

La versión modificada funciona porque el alcance secundario (transcluido) accede primero a obj (referencia) y luego al nombre de la propiedad

Obtenga más información sobre la herencia del alcance en https://github.com/angular/angular. js / wiki / Understanding-Scopes

Y el comportamiento de transclusión y alcance en http://angular-tips.com / blog / 2014/03 / transclusion-and-scopes /

0
pdorgambide 13 feb. 2015 a las 16:43