Qual é a maneira angular de vincular muitas inputs?

Estou aprendendo angularjs e quero poder deixar o usuário inserir muitas inputs. Quando essas inputs são inseridas, os elementos da matriz da list devem ser alterados de acordo. Eu queria tentar usar a diretiva ngRepeat, mas eu li que, uma vez que cria um novo escopo, não consigo vincular:

 

Eu queria saber se eu deveria estar usando uma diretiva personalizada para fazer isso ou abordá-lo de forma diferente.

Você terá mais sorte se sua list for uma matriz de objects (em oposição a uma matriz de primitivos). Isso funciona bem, mesmo que um novo escopo seja criado com ng-repeat :

 

com um controlador de:

 function TestController($scope) { $scope.list = [ { value: 'value 1' }, { value: 'value 2' }, { value: 'value 3' } ]; }​ 

Veja este violino como um exemplo.

Por outro lado, se você estiver tentando se ligar a uma matriz de strings, o novo escopo causará um problema, pois os valores que você está modificando não estarão vinculados às primitivas de string da matriz original (como neste exemplo de violino ).

O motivo pelo qual a binding de dados a um “item” primitivo não funciona é devido à maneira como o ng-repeat cria os escopos filho para cada item. Para cada item, ng-repeat tem o novo escopo filho herdado prototipicamente do escopo pai (consulte as linhas tracejadas na figura abaixo) e , em seguida , atribui o valor do item a uma nova propriedade no escopo filho (itens vermelhos na figura abaixo). O nome da nova propriedade é o nome da variável de loop. Do código-fonte do ng-repeat :

 childScope = scope.$new(); ... childScope[valueIdent] = value; 

Se item é uma primitiva, a nova propriedade de escopo filho recebe essencialmente uma cópia do valor da primitiva. Essa propriedade de escopo filho não é visível para o escopo pai e as alterações feitas no campo de input são armazenadas nessa propriedade de escopo filho. Por exemplo, suponha que tenhamos no escopo pai

 $scope.list = [ 'value 1', 'value 2', 'value 3' ]; 

E no HTML:

 

Em seguida, o primeiro escopo filho teria a seguinte propriedade de item , com um valor primitivo ( value 1 ):

 item: "value 1" 

ng-repeat com primitivos

Por causa da binding de dados do modelo ng, as alterações feitas no campo de input do formulário são armazenadas nessa propriedade de escopo filho.

Você pode verificar isso registrando o escopo filho no console. Adicione ao seu HTML, dentro do ng-repeat:

 show scope 

Adicione ao seu controlador:

 $scope.showScope = function(e) { console.log(angular.element(e.srcElement).scope()); } 

Com a abordagem do @Gloopy, cada escopo filho ainda obtém uma nova propriedade “item”, mas porque a lista é agora uma matriz de objects, childScope[valueIdent] = value; resulta no valor da propriedade do item sendo definido para uma referência a um dos objects da matriz (não uma cópia).

ng-repeat com objetos

Usando a técnica showScope (), você verá que o valor da propriedade do item escopo filho faz referência a um dos objects da matriz – não é mais um valor primitivo.

Veja também não ligar para primitivos em escopos filho ng-repeat e
Quais são as nuances do escopo protótipo / inheritance prototípica no AngularJS? (que contém fotos de como os escopos se parecem ao usar ng-repeat).

Eu encontrei uma maneira interessante de fazer isso, e isso me permite trabalhar em uma matriz de primitivos.

Estou usando o AngularJS 1.2.1, que é a única versão em que posso fazer isso funcionar.

HTML:

 

JavaScript:

 $scope.editItem = function(idx, eItem) { $scope.list[idx] = eItem; }; 

Link: http://jsfiddle.net/bxD2P/10/ (obrigado a Gloopy pelo arranque do Fiddle)

Tenho certeza de que existem maneiras fáceis de descobrir como isso funciona e adoraria ouvi-las. Isso me permitiria reforçar meu código.

Aqui está uma maneira de fazer isso. Eu usei textareas e uma estrutura diferente para meus repetidores, mas o conceito principal é:

  • exibir um valor simples com base no índice. (não vinculado)
  • no borrão atualizar o modelo
  • na atualização do modelo re-render

Essencialmente, é fingir a binding.

Violino de trabalho – http://jsfiddle.net/VvnWY/4/

O html:

   
Here's a few strings:
{{strings[$index]}}
Here's the strings as editable (twice so that you can see the updates from a model change):

O JS:

 var myApp = angular.module('myApp',[]); angular.module('myApp', []) .controller('MyCtrl', ['$scope', function($scope) { $scope.strings = [ "foo", "bar", "cow" ]; }]) .directive('formTextareas', function() { return { restrict: "E", scope: { strings: '=' }, templateUrl: "textareas.html", link: function( $scope ){ $scope.blur = function( $event, $index ){ $scope.strings[ $index ] = $event.currentTarget.value; }; } }; }) ; 

Considere usar a diretiva ngList https://docs.angularjs.org/api/ng/directive/ngList