Como usar “ng-model” em AngularJS com EXEMPLOS

⚡ Resumo Inteligente

Em AngularJS, o ng-model vincula um controle de entrada diretamente a uma propriedade do $scope, mantendo a propriedade `$scope`.ping A visualização e o modelo estão sincronizados em ambas as direções. As seções abaixo abordam o atributo, três exemplos práticos e os erros mais comuns entre iniciantes.

  • 🔗 Encadernação bidirecional: O ng-model envia a entrada do usuário para a propriedade $scope e replica automaticamente as alterações do controlador de volta para o controle.
  • 📝 Vinculação de área de texto: Associe uma string de várias linhas a uma área de texto e use a sequência de escape \n para forçar quebras de linha no valor renderizado.
  • ☑️ Estado da caixa de seleção: Uma caixa de seleção vinculada com ng-model armazena um valor booleano, de forma que verdadeiro (true) marca a caixa como selecionada e falso (false) a deixa desmarcada.
  • 📋 Listas suspensas: Preencha um elemento select com ng-options e vincule o item escolhido a uma propriedade de modelo separada.
  • ⚠️ Falha comum: Vincular um elemento select ao mesmo objeto que fornece o texto da opção sobrescreve esse objeto na primeira seleção.
  • 🛠️ Ganchos de validação: ng-model adiciona classes ng-pristine, ng-dirty, ng-valid e ng-invalid que orientam estilos condicionais e verificações de formulário.

O que é modelo ng em AngularJS?

`ng-model` é uma diretiva do AngularJS que representa o modelo e tem como principal objetivo vincular a "visualização" ao "modelo". Tudo o que o usuário digita em um controle é gravado diretamente em uma propriedade do modelo. $scopeE tudo o que o controlador escrever nessa propriedade será enviado de volta diretamente para o controle.

Por exemplo, imagine que você queira apresentar uma página simples ao usuário final, como a mostrada abaixo, que solicita que o usuário insira o “Nome” e o “Sobrenome” em caixas de texto. E então, você queira garantir que as informações inseridas pelo usuário sejam armazenadas em seu modelo de dados.

Você pode usar a diretiva ng-model para mapear os campos de texto "Nome" e "Sobrenome" para o seu modelo de dados. A diretiva garantirá que os dados na "visualização" e no seu "modelo" permaneçam sincronizados o tempo todo, sem a necessidade de escrever uma única linha de código para tratamento de eventos.

⚠️ Nota sobre a versão: O AngularJS (versão 1.x) chegou ao fim de sua vida útil em 31 de dezembro de 2021 e não recebe mais atualizações de segurança. Os exemplos abaixo ainda funcionam, mas no Angular moderno, o mesmo vínculo bidirecional é escrito como [(ngModel)] e requer o FormsModule.

O atributo ng-model

Conforme discutido na seção anterior, o atributo ng-model é usado para vincular os dados do seu modelo à visualização apresentada ao usuário.

O atributo ng-model é usado para,

  1. Vincular controles como campos de entrada, áreas de texto e elementos de seleção da visualização ao modelo.
  2. Fornecer um comportamento de validação — por exemplo, uma validação pode ser adicionada a uma caixa de texto para que apenas caracteres numéricos possam ser inseridos.
  3. Manter o estado do controle. Por estado, queremos dizer que o controle e os dados são mantidos sempre sincronizados: se o valor dos dados mudar, o valor no controle muda automaticamente e vice-versa.
  4. Expondo esse estado como classes CSS. O AngularJS adiciona ng-pristine, ng-dirty, ng-valid e ng-invalid a todos os controles que possuem um ng-model, o que torna a estilização condicional de formulários bastante simples.

Com o atributo compreendido, o próximo passo é aplicá-lo aos três tipos de controle que você encontrará com mais frequência.

Como usar o modelo ng

1) Área de Texto

A tag de área de texto é usada para definir um controle de entrada de texto multilinha. A área de texto pode conter um número ilimitado de caracteres e o texto é renderizado em uma fonte de largura fixa.

Vamos agora analisar um exemplo simples de como adicionar a diretiva `ng-model` a um controle de área de texto. Neste exemplo, mostraremos como passar uma string de várias linhas do controlador para a visualização e associar esse valor ao controle 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 Explicação:

  1. O diretiva do modelo ng anexa a variável membro chamada “p”Description” para o controle “textarea”. O “pDescriptA variável “ion” contém o texto que é passado para o controle da área de texto. rows="4" e cols="50" Os atributos simplesmente dimensionam o controle para que o texto de várias linhas seja exibido corretamente.
  2. A variável membro “pDescriptÀ variável “ion” é atribuído um valor multilinha. \n A sequência de escape dentro da string é o que força o texto para uma segunda linha quando a área de texto o renderiza.

Saída:

A partir da saída, fica claro que o texto multilinha atribuído no controlador é exibido no controle de área de texto, dividido em duas linhas exatamente onde o \n senta.

2) Elementos de entrada

A diretiva ng-model também funciona com elementos de entrada comuns. Abaixo, vinculamos uma caixa de texto e duas caixas de seleção simultaneamente, para que você possa ver como o ng-model lida com um valor de string e um valor booleano lado a lado.

<!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 Explicação:

  1. A diretiva ng-model associa a variável de membro “pname” ao controle de entrada de texto e às propriedades. Topic.Controller e Topic.Models aos dois controles de caixa de seleção.
  2. No controlador, “pname” recebe a string “Guru99”, e o objeto “Topic” recebe dois membros booleanos. Uma caixa de seleção vinculada com ng-model sempre lê e grava um booleano, e é por isso que true faz com que a caixa seja marcada e false Deixa tudo claro.

Saída:

Da saída,

  • É possível observar claramente que o valor atribuído ao pname variável é “Guru99".
  • Como o primeiro valor limitado é true, a caixa de seleção “Controlador” está marcada. Da mesma forma, como o segundo valor é falseA caixa de seleção "Modelos" não está marcada.

3) Selecione o elemento no menu suspenso

A diretiva ng-model também pode ser aplicada ao elemento select, de forma que o item escolhido pelo usuário seja armazenado no modelo.

Aqui teremos um campo de entrada de texto que conterá o nome “Guru99”, e uma lista de seleção com dois itens, “Controlador” e “Modelos”.

⚠️ Correção: A captura de tela acima mostra a listagem original, que vinculou o elemento select exatamente ao mesmo. Topics objeto que fornecia o texto da opção. No momento em que um usuário escolhe uma opção, o AngularJS sobrescreve. Topics Com a string selecionada, ambas as opções desaparecem. A listagem corrigida abaixo mantém a lista em uma propriedade e a seleção em outra, e usa ng-options para criar a 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 Explicação:

  1. O campo de entrada de texto está vinculado a pNamee o elemento select está vinculado a selectedTopicComo o elemento select possui sua própria propriedade de modelo, escolher uma opção nunca altera a lista em si.
  2. O Topics O array contém os dois valores “Controller” e “Models”. ng-options A expressão percorre esse array e renderiza uma opção por entrada, portanto, adicionar um terceiro tópico não requer nenhuma alteração na marcação.
  3. selectedTopic está predefinido para a primeira entrada, o que faz com que o menu suspenso abra com um valor padrão adequado em vez de uma linha em branco.

Saída:

A partir da saída, pode-se observar que o valor atribuído ao pName variável é “Guru99”, e o controle de seleção oferece as opções “Controlador” e “Modelos”. Deixando os exemplos práticos de lado, as associações às vezes se recusam a atualizar, e vale a pena conhecer os motivos.

Por que as vinculações do ng-model às vezes falham

A maioria dos problemas relatados com ng-model não são bugs do AngularJS, mas sim consequências de como os escopos e os tipos primitivos funcionam.

O caso clássico é uma vinculação colocada dentro de uma diretiva que cria um escopo filho, como por exemplo: ng-repetir, ng-if ou ng-switch. Escrevendo ng-model="name" Isso cria uma cópia sombra no escopo filho, de modo que o escopo pai nunca vê a edição. Em vez disso, vincule a uma propriedade de um objeto. ng-model="user.name" — mantém todos os escopos apontando para a mesma referência. Essa é a razão pela qual desenvolvedores experientes de AngularJS insistem em um ponto em cada expressão ng-model.

Outras duas causas são responsáveis ​​pela maior parte do restante:

  • Controlador ou módulo ausente: Se ng-app ou ng-controller estiverem escritos incorretamente, a vinculação simplesmente não renderiza nada em vez de gerar um erro.
  • O valor foi alterado fora do AngularJS: Um valor definido por um manipulador jQuery ou um retorno de chamada setTimeout chega fora do ciclo de digestão, portanto a visualização não é atualizada até que $scope.$apply() corre.

Verificar esses três itens resolve a grande maioria dos problemas de vinculação que parecem não funcionar.

Perguntas Frequentes

O ng-bind é unidirecional: ele imprime um valor do modelo em um elemento. O ng-model é bidirecional e funciona apenas em controles de formulário, portanto, a entrada do usuário flui de volta para o modelo, bem como para fora dele.

Adicione `ng-model-options`, por exemplo, `ng-model-options="{ debounce: 500 }"`. O AngularJS então aguarda meio segundo após a última tecla pressionada antes de atualizar o modelo, o que é útil para caixas de pesquisa que disparam uma requisição.

Em grande parte, sim. Os assistentes de IA reescrevem ng-model como [(ngModel)] e adicionam a importação do FormsModule. Formulários reativos, analisadores personalizados e pipelines de $formatters ainda precisam de revisão manual, porque o Angular os modela de maneira muito diferente.

As ferramentas de IA verificam rapidamente os suspeitos de sempre: um limite primitivo dentro de um escopo filho, um nome de controlador escrito incorretamente e um valor atribuído fora do ciclo de digestão. Cada um deles produz uma falha silenciosa em vez de um erro no console.

Somente os campos de entrada do tipo "number" são interpretados como valores numéricos. Um controle do tipo "text" sempre retorna uma string, portanto, comparações com === falham. Converta explicitamente ou altere o tipo de entrada.

Resuma esta postagem com: