/ / AngularJS ng-model no hace enlace de datos bidireccional - angularjs, enlace de datos, angularjs-scope

AngularJS ng-model no realiza enlace de datos bidireccional: angularjs, enlace de datos, angularjs-scope

Tengo una etiqueta con un cuadro de entrada como este:

  <label class="item item-input">
<input type="text" data-ng-model="description" placeholder="Add a Description!">
</label>

Como puede ver, este cuadro de entrada está vinculado al alcance "descripción"

En mi controlador tengo algo parecido a esto:

$scope.description = "";
$scope.submit = function() {
console.log($scope.description);
};

En mi HTML también tengo esta línea:

  <div ng-show="description.length <= maxChars">{{description}}</div>

La función de envío se llama cuando el usuario golpeael botón enviar después de escribir dentro del cuadro de entrada. La descripción se muestra correctamente. A medida que el usuario escribe en el cuadro de entrada, la descripción se actualiza en el HTML pero NO en el controlador.

Tengo la sensación de que tiene algo que ver conestablece la descripción en una cadena vacía, pero claramente se está actualizando en lo que respecta al HTML. Pero mantiene console.logging y cadena vacía independientemente.

Para que esto funcione, tuve que pasar la descripción directamente a la función de envío (y también actualizar la función en consecuencia):

<button class="button button-positive" data-ng-click="submit(description)">Submit</button>

Esto es completamente innecesario ya que Angular debería estar haciendo enlace de datos bidireccional automáticamente, pero no lo es.

¿Alguien tiene alguna idea?

Cualquier ayuda sería apreciada.

EDITAR:

Aquí está el HTML completo debido a la demanda popular.

<ion-view title="Moments" id="page2">
<ion-content padding="true" class="has-header">
<img src="/images/{{picture}}" height="300px" width="100%"> </img>
<div class="row">
<div ng-show="description.length > maxChars" style= "color: red">{{description}}</div>
<div ng-show="description.length <= maxChars">{{description}}</div>
</div>
<div class="row" ng-if="description">
<div ng-show="description.length > maxChars" style= "color: red">{{description.length}} / {{maxChars}}</div>
<div ng-show="description.length <= maxChars" style= "color: green">{{description.length}} / {{maxChars}}</div>
</div>
<div class="row">
<div class="col">
<label class="item item-input">
<input type="text" data-ng-model="description" placeholder="Add a Description!">
</label>
</div>
<button style="margin-right: 5px" class="col col-10 button button-positive" data-ng-click="checkDescription(description)">OK</button>
</div>
<div class="row">
<div class="col"><ion-checkbox data-ng-change="changeLocation()" data-ng-model="location">Show Location</ion-checkbox></div>
</div>
<div class="row">
<div class="button-bar">
<button class="button button-assertive" data-ng-click="cancel()">Cancel</button>
<button class="button button-positive" data-ng-click="submit(description)">Submit</button>
</div>
</div>
</ion-content>
</ion-view>

También soy consciente de que en esta pregunta el envíoLa función no toma parámetros. Así es como me gustaría que fuera. Actualmente, mi botón de envío toma un parámetro (la descripción). Esto no debería ser necesario. También tengo el mismo problema con la función "checkDescription". Esa función tampoco debería tener parámetros, pero nuevamente, me veo obligado a pasar la descripción directamente a la función. Algo que prefiero no hacer.

Respuestas

1 para la respuesta № 1

Resumen Ejecutivo:

En AngularJS, un ámbito secundario normalmente hereda prototípicamente de su ámbito primario. Una excepción a esta regla es una directiva que usa scope: { ... } - esto crea un alcance "aislado" que noheredar prototípicamente. (y directiva con transclusión) Esta construcción se usa a menudo al crear una directiva de "componente reutilizable". En las directivas, el alcance primario se usa directamente de manera predeterminada, lo que significa que todo lo que cambie en su directiva que provenga del alcance primario también cambiará en el alcance primario. Si establece scope:true (en lugar de alcance: { ... }), entonces se utilizará la herencia prototípica para esa directiva.

La herencia del alcance es normalmente directa, y a menudo ni siquiera necesita saber que está sucediendo ... hasta que lo intente Enlace de datos bidireccional (es decir, elementos de formulario, modelo ng) a un primitivo (p.ej., número, cadena, booleano) definidos en el ámbito primario desde dentro del ámbito secundario. No funciona de la forma en que la mayoría de la gente espera que funcione. Lo que sucede es que el ámbito secundario obtiene su propia propiedad que oculta / oculta la propiedad principal del mismo nombre. Esto no es algo que AngularJS está haciendo, así es como prototipo de JavaScript la herencia funciona. Los nuevos desarrolladores de AngularJS a menudo no se dan cuenta de que ng-repeat, ng-switch, ng-view, ng-include y ng-if todos crean nuevos ámbitos secundarios, por lo que el problema a menudo aparece cuando estas directivas están involucradas. (Ver este ejemplo para una ilustración rápida del problema)

Este problema con las primitivas se puede evitar fácilmente siguiendo la "mejor práctica" de siempre tiene un punto "." en tus modelos ng - Ver 3 minutos de valor. Misko demuestra el problema de unión primitivo con ng-switch.

--AngularJS Wiki - Los matices del alcance de la herencia prototípica


Traté de hacer el "." notación en mi alcance, pero cada vez que trato de hacer referencia a esto así:

$scope.moment.description = "";

Dice "No se puede leer la descripción de la propiedad" de undefined.

El código debe crear el objeto antes de asignar un valor a una propiedad:

$scope.moment = {};
$scope.moment.description = "";

//OR

$scope.moment = { description: "" };

0 para la respuesta № 2

Para realizar un seguimiento de la actualización del valor, puede usar $ watch,

scope.$watch("description", function(newValue, oldValue) {
console.log(newValue);
});