Cómo usar “ng-model” en AngularJS con EJEMPLOS

⚡ Resumen inteligente

ng-model en AngularJS vincula un control de entrada directamente a una propiedad en $scope, keeping La vista y el modelo se sincronizaron en ambas direcciones. Las secciones siguientes tratan sobre el atributo, tres ejemplos prácticos y los errores más comunes entre los principiantes.

  • 🔗 Encuadernación bidireccional: ng-model envía la entrada del usuario a la propiedad $scope y envía automáticamente los cambios del controlador de vuelta al control.
  • 📝 Enlace de área de texto: Vincula una cadena de texto de varias líneas a un área de texto y utiliza la secuencia de escape \n para forzar saltos de línea en el valor mostrado.
  • ☑️ Estado de la casilla de verificación: Una casilla de verificación vinculada con ng-model almacena un valor booleano, de modo que si es verdadero, la casilla aparece marcada y si es falso, queda desmarcada.
  • 📋 Listas desplegables: Rellena un elemento select con ng-options y vincula el elemento elegido a una propiedad de modelo independiente.
  • ⚠️ Falla común: Al vincular un elemento select al mismo objeto que proporciona su texto de opción, se sobrescribe dicho objeto en la primera selección.
  • 🛠️ Ganchos de validación: ng-model agrega clases ng-pristine, ng-dirty, ng-valid y ng-invalid que impulsan el estilo condicional y las comprobaciones de formularios.

¿Qué es el modelo ng en AngularJS?

ng-model es una directiva en AngularJS que representa el modelo, y su propósito principal es vincular la "vista" al "modelo". Todo lo que el usuario escribe en un control se escribe directamente en una propiedad en $scopey todo lo que el controlador escribe en esa propiedad se envía directamente de vuelta al control.

Por ejemplo, supongamos que desea presentar al usuario final una página sencilla como la que se muestra a continuación, en la que se le pide que introduzca su nombre y apellido en cuadros de texto. Luego, desea asegurarse de almacenar la información que el usuario ha introducido en su modelo de datos.

Puedes usar la directiva ng-model para asignar los campos de texto "Nombre" y "Apellido" a tu modelo de datos. Esta directiva garantiza que los datos de la vista y los del modelo se mantengan sincronizados en todo momento, sin necesidad de escribir código para el manejo de eventos.

⚠️ Nota de versión: AngularJS (la rama 1.x) llegó al final de su ciclo de vida el 31 de diciembre de 2021 y ya no recibe parches de seguridad. Los ejemplos a continuación aún funcionan, pero en Angular moderno el mismo enlace bidireccional se escribe como [(ngModel)] y requiere el FormsModule.

El atributo ng-modelo

Como se explicó en la sección anterior, el atributo ng-model se utiliza para vincular los datos de su modelo con la vista que se presenta al usuario.

El atributo ng-model se utiliza para,

  1. Vincular controles como campos de entrada, áreas de texto y elementos de selección en la vista al modelo.
  2. Proporcionar un mecanismo de validación; por ejemplo, se puede agregar una validación a un cuadro de texto para que solo se puedan ingresar caracteres numéricos.
  3. Mantener el estado del control. Por estado, nos referimos a que el control y los datos se mantengan siempre sincronizados: si el valor de los datos cambia, el valor del control cambia automáticamente, y viceversa.
  4. Exponiendo ese estado como clases CSS. AngularJS añade ng-pristine, ng-dirty, ng-valid y ng-invalid a cada control que lleva un ng-model, que es lo que hace que el estilo condicional de los formularios sea sencillo.

Una vez comprendido el atributo, el siguiente paso es aplicarlo a los tres tipos de controles que encontrará con mayor frecuencia.

Cómo usar ng-modelo

1) Área de texto

La etiqueta de área de texto se utiliza para definir un control de entrada de texto de varias líneas. El área de texto puede contener una cantidad ilimitada de caracteres y el texto se representa en una fuente de ancho fijo.

Ahora veamos un ejemplo sencillo de cómo agregar la directiva ng-model a un control de área de texto. En este ejemplo, mostraremos cómo pasar una cadena de texto de varias líneas desde el controlador a la vista y asignar ese valor al control de área de texto.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <script src="https://code.angularjs.org/1.8.3/angular.js"></script>
</head>
<body>
<h1>Guru99 Global Event</h1>

<div ng-app="DemoApp" ng-controller="DemoCtrl">
    <form>
        Topic Description:<br><br>
        <textarea rows="4" cols="50" ng-model="pDescription"></textarea>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', []);
    app.controller('DemoCtrl', function($scope) {
        $scope.pDescription = "This topic looks at how Angular JS works \nModels in Angular JS";
    });
</script>
</body>
</html>

Code Explicación:

  1. El directiva de modelo ng adjunta la variable miembro llamada “pDescriptión” al control “área de texto”. El “pDescriptLa variable "ion" contiene el texto que se pasa al control del área de texto. rows="4" y cols="50" Los atributos simplemente ajustan el tamaño del control para que el texto de varias líneas se muestre correctamente.
  2. La variable miembro “pDescriptA "ión" se le asigna un valor multilínea. \n La secuencia de escape dentro de la cadena es lo que fuerza al texto a pasar a una segunda línea cuando el área de texto lo renderiza.

Salida:

A partir de la salida, queda claro que el texto multilínea asignado en el controlador se muestra en el control del área de texto, dividido en dos líneas exactamente donde \n se sienta

2) Elementos de entrada

La directiva ng-model también funciona con elementos de entrada comunes. A continuación, enlazamos un cuadro de texto y dos casillas de verificación simultáneamente, para que pueda ver cómo ng-model maneja un valor de cadena y un valor booleano uno al lado del otro.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <script src="https://code.angularjs.org/1.8.3/angular.js"></script>
</head>
<body>
<h1>Guru99 Global Event</h1>

<div ng-app="DemoApp" ng-controller="DemoCtrl">
    <form>
        Topic Description:<br><br>
        Name : <input type="text" ng-model="pname"><br>
        Topic :<br>
        <input type="checkbox" ng-model="Topic.Controller">Controller<br>
        <input type="checkbox" ng-model="Topic.Models">Models
    </form>
</div>

<script>
    var app = angular.module('DemoApp', []);
    app.controller('DemoCtrl', function($scope) {
        $scope.pname = "Guru99";

        $scope.Topic = {
            Controller: true,
            Models: false
        };
    });
</script>
</body>
</html>

Code Explicación:

  1. La directiva ng-model adjunta la variable miembro “pname” al control de entrada de texto y las propiedades Topic.Controller y Topic.Models a los dos controles de casilla de verificación.
  2. En el controlador, a “pname” se le asigna la cadena “Guru99”, y al objeto “Topic” se le asignan dos miembros booleanos. Una casilla de verificación vinculada con ng-model siempre lee y escribe un booleano, por eso true marca la casilla y false Lo deja claro.

Salida:

Desde la salida,

  • Se puede ver claramente que el valor asignado a la pname La variable es “Guru99 ".
  • Dado que el primer valor límite es true, la casilla de verificación está marcada para la casilla de verificación "Controlador". Del mismo modo, dado que el segundo valor es falseLa casilla de verificación "Modelos" no está marcada.

3) Seleccionar elemento del menú desplegable

La directiva ng-model también se puede aplicar al elemento select, de modo que el elemento que el usuario elige se almacene en el modelo.

Aquí tendremos un campo de texto que contiene el nombre “Guru99”, y una lista desplegable con dos elementos, “Controlador” y “Modelos”.

⚠️ Corrección: La captura de pantalla anterior muestra el listado original, que vinculaba el elemento select al mismo Topics objeto que proporcionó el texto de la opción. En el momento en que un usuario elige una opción, AngularJS sobrescribe Topics con la cadena seleccionada y ambas opciones desaparecen. El listado corregido a continuación mantiene la lista en una propiedad y la selección en otra, y utiliza ng-options para elaborar la lista.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <script src="https://code.angularjs.org/1.8.3/angular.js"></script>
</head>
<body>
<h1>Guru99 Global Event</h1>

<div ng-app="DemoApp" ng-controller="DemoCtrl">
    <form>
        Topic Description:<br><br>
        Name : <input type="text" ng-model="pName"><br>
        Topic :<br>
        <!-- Topics holds the list; selectedTopic holds the choice -->
        <select ng-model="selectedTopic" ng-options="t for t in Topics"></select>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', []);
    app.controller('DemoCtrl', function($scope) {
        $scope.pName = "Guru99";

        $scope.Topics = ["Controller", "Models"];
        $scope.selectedTopic = $scope.Topics[0];
    });
</script>
</body>
</html>

Code Explicación:

  1. La entrada de texto está vinculada a pNamey el elemento select está vinculado a selectedTopic. Debido a que la selección tiene su propia propiedad de modelo, elegir una opción nunca altera la lista en sí.
  2. El Topics El array contiene los dos valores “Controller” y “Models”. ng-options La expresión recorre ese array y muestra una opción por cada entrada, por lo que añadir un tercer tema no requiere ningún cambio en el marcado.
  3. selectedTopic Está preconfigurado con la primera entrada, lo que hace que el menú desplegable se abra con una opción predeterminada sensata en lugar de una fila en blanco.

Salida:

A partir de la salida, se puede observar que el valor asignado a la pName La variable es “Guru99”, y el control de selección ofrece las opciones “Controlador” y “Modelos”. Dejando de lado los ejemplos prácticos, a veces las vinculaciones se resisten a actualizarse, y conviene conocer los motivos.

¿Por qué a veces fallan los enlaces de ng-model?

La mayoría de los problemas reportados con ng-model no son errores de AngularJS, sino consecuencias de cómo funcionan los ámbitos y los tipos primitivos.

El caso clásico es un enlace colocado dentro de una directiva que crea un ámbito secundario, como por ejemplo: ng-repetir, ng-if o ng-switch. Escritura ng-model="name" Se crea una copia en la sombra en el ámbito secundario, por lo que el padre nunca ve la edición. En su lugar, se enlaza a una propiedad de un objeto. ng-model="user.name" — mantiene todos los ámbitos apuntando a la misma referencia. Por eso, los desarrolladores experimentados de AngularJS insisten en usar un punto en cada expresión ng-model.

Otras dos causas explican la mayor parte del resto:

  • Controlador o módulo faltante: Si ng-app o ng-controller están mal escritos, el enlace no renderiza nada silenciosamente en lugar de generar un error.
  • El valor se modificó fuera de AngularJS: un valor establecido desde un controlador jQuery o una devolución de llamada setTimeout llega fuera del ciclo de digestión, por lo que la vista no se actualiza hasta $scope.$apply() carreras.

Comprobar esos tres aspectos resuelve la gran mayoría de los problemas de conexión que parecen no funcionar.

Preguntas Frecuentes

ng-bind es unidireccional: imprime un valor del modelo en un elemento. ng-model es bidireccional y funciona solo en controles de formulario, por lo que la entrada del usuario fluye tanto hacia el modelo como desde él.

Agregue ng-model-options, por ejemplo ng-model-options=”{ debounce: 500 }”. AngularJS espera medio segundo después de la última pulsación de tecla antes de actualizar el modelo, lo cual es útil para cuadros de búsqueda que activan una solicitud.

En gran medida, sí. Los asistentes de IA reescriben ng-model como [(ngModel)] y agregan la importación de FormsModule. Los formularios reactivos, los analizadores personalizados y las canalizaciones de $formatters aún requieren revisión manual, porque Angular los modela de manera muy diferente.

Las herramientas de IA comprueban rápidamente los problemas habituales: una restricción de tipo primitiva dentro de un ámbito secundario, un nombre de controlador mal escrito y un valor asignado fuera del ciclo de digestión. Cada uno de estos problemas produce un fallo silencioso en lugar de un error en la consola.

Solo los controles de tipo "número" se analizan como valores numéricos. Un control de tipo "texto" siempre devuelve una cadena, por lo que las comparaciones con === fallan. Conviértalo explícitamente o cambie el tipo de entrada.

Resumir este post con: