Quando usar FormGroup vs. FormArray?

91

FormGroup :

Um FormGroup agrega os valores de cada FormControl filho em um objeto, com cada nome de controle como a chave.

const form = new FormGroup({
  first: new FormControl('Nancy', Validators.minLength(2)),
  last: new FormControl('Drew')
});

FormArray :

Um FormArray agrega os valores de cada FormControl filho em uma matriz.

const arr = new FormArray([
  new FormControl('Nancy', Validators.minLength(2)),
  new FormControl('Drew')
]);

Quando um deve ser usado em vez do outro?

jcroll
fonte

Respostas:

122

FormArray é uma variante do FormGroup. A principal diferença é que seus dados são serializados como um array (em vez de serem serializados como um objeto no caso de FormGroup). Isso pode ser especialmente útil quando você não sabe quantos controles estarão presentes no grupo, como formulários dinâmicos.

Deixe-me tentar explicar com um exemplo rápido. Digamos, você tem um formulário onde captura o pedido de pizza de um cliente. E você coloca um botão para permitir que eles adicionem e removam quaisquer pedidos especiais. Aqui está a parte html do componente:

<section>
  <p>Any special requests?</p>
  <ul formArrayName="specialRequests">
    <li *ngFor="let item of orderForm.controls.specialRequests.controls; let i = index">
      <input type="text" formControlName="{{i}}">
      <button type="button" title="Remove Request" (click)="onRemoveSpecialRequest(i)">Remove</button>
    </li>
  </ul>
  <button type="button" (click)="onAddSpecialRequest()">
    Add a Request
  </button>
</section>

e aqui está a classe de componente que define e lida com solicitações especiais:

constructor () {
  this.orderForm = new FormGroup({
    firstName: new FormControl('Nancy', Validators.minLength(2)),
    lastName: new FormControl('Drew'),
    specialRequests: new FormArray([
      new FormControl(null)
    ])
  });
}

onSubmitForm () {
  console.log(this.orderForm.value);
}

onAddSpecialRequest () {
  this.orderForm.controls
  .specialRequests.push(new FormControl(null));
}

onRemoveSpecialRequest (index) {
  this.orderForm.controls['specialRequests'].removeAt(index);
}

FormArray oferece mais flexibilidade do que FormGroup no sentido de que é mais fácil manipular FormControls usando "push", "insert" e "removeAt" do que usando "addControl", "removeControl", "setValue" etc. Os métodos FormArray garantem que os controles sejam devidamente rastreado na hierarquia do formulário.

espero que isto ajude.

Usman
fonte
4
e se você estiver tentando editar formulários? Como você itera e adiciona controles?
ctilley79,
1
Como você refatoraria isso em componentes?
Justin
É possível adicionar objetos com key: value na matriz do formulário em vez de apenas valores?
Anthony
Como podemos definir um nome de rótulo de formulário? existe alguma opção para definir enquanto o controle de formulário é inicializado? desde o formulário dinâmico, não poderíamos definir seu valor.
PC Krishnadas de
29

Para criar formas reativas, um pai FormGroupé uma obrigação. Isso FormGrouppode conter ainda formControls, filho formGroupsouformArray

FormArraypode ainda conter array de formControlsou a formGrouppróprio.

Quando devemos usar formArray?

Por favor, leia esta bela postagem que explica o uso deformArray

O exemplo interessante naquele blog é sobre as viagens formGroup

A estrutura de viagens formGroupusando formControle formArrayseria algo como:

this.tripForm = this.fb.group({
    name: [name, Validators.required],
     cities: new FormArray(
       [0] ---> new FormGroup({
           name: new FormControl('', Validators.required),
               places: new FormArray(
                  [0]--> new FormGroup({
                      name: new FormControl('', Validators.required),
                         }),
                      [1]--> new FormGroup({
                         name: new FormControl('', Validators.required),
                      })
                  )
              }), 
       [1] ---> new FormGroup({
           name: new FormControl('', Validators.required),
           places: new FormArray(
               [0]--> new FormGroup({
                   name: new FormControl('', Validators.required),
               }),
               [1]--> new FormGroup({
                   name: new FormControl('', Validators.required),
               })
               )
      }))
})

Não se esqueça de brincar com este DEMO , e observe o uso de array para citiese placesde uma viagem.

Amit Chigadani
fonte
Explicação curta e doce.
Kanchan
explicação incrível
Taoufik Jabbari
Excelente irmão.
jalpa,
@scopchanov Pode não ter muita explicação com o texto, mas a representação da estrutura do formulário dá alguma ideia. Avise-me se houver algo que possamos acrescentar para melhorar a resposta :)
Amit Chigadani
Bem, se alguém disser "explicação", espero ver exatamente isso. Com todo o meu respeito, a sua resposta está muito próxima de uma "resposta apenas com link" de acordo com as definições do SO, porque é exatamente onde vai direto ao ponto, ou seja, quando devemos usar formArray? , um link para uma postagem do blog é fornecido, sem citar nenhuma parte significativa dele. Você realmente postou algum código, mas novamente nenhuma explicação. Teria feito uma grande diferença se você tivesse citado ambas as regras deste post.
scopchanov
5

De: Livro de Anton Moiseev “Angular Development with Typescript, Second Edition.” :

Quando você precisar adicionar (ou remover) controles de forma programática a um formulário , use FormArray . É semelhante ao FormGroup, mas tem uma variável de comprimento . Enquanto FormGroup representa um formulário inteiro ou um subconjunto fixo de campos de um formulário , FormArray geralmente representa uma coleção de controles de formulário que podem aumentar ou diminuir .

Por exemplo, você pode usar FormArray para permitir que os usuários insiram um número arbitrário de emails.

HS Progr
fonte
0

Na documentação do angular, você pode ver que

FormArray é uma alternativa ao FormGroup para gerenciar qualquer número de controles não nomeados. Como ocorre com as instâncias de grupos de formulários, você pode inserir e remover dinamicamente controles de instâncias de array de formulários, e o valor da instância de array de formulários e o status de validação são calculados a partir de seus controles filhos. No entanto, você não precisa definir uma chave para cada controle por nome, portanto, esta é uma ótima opção se você não souber o número de valores filho com antecedência.

Deixe-me mostrar o exemplo deles e tentar explicar como eu entendo isso. Você pode ver a fonte aqui

Imagine um formulário com os seguintes campos

  profileForm = this.fb.group({
    firstName: ['', Validators.required],
    lastName: [''],
    address: this.fb.group({
      street: [''],
      city: [''],
      state: [''],
      zip: ['']
    }),
    aliases: this.fb.array([
      this.fb.control('')
    ])
  });

Aqui temos firstName, lastName, addresse aliasesAll campo juntos são um grupo formulário para que embrulhar tudo em group. Ao mesmo tempo addressé como um subgrupo, então o envolvemos em outro group(você pode olhar o modelo para melhor compreensão)! Cada controle de formulário aqui está keyexceto aliasese isso significa que você pode inserir os valores que quiser como array simples usando formBuildermétodos como push.

É assim que eu entendo, espero que ajude alguém.

Gh111
fonte