Definir valor manualmente para o controle FormBuilder


176

Isso está me deixando louco, estou sob o revólver e não posso me dar ao luxo de passar mais um dia inteiro nisso.

Estou tentando definir manualmente um valor de controle ('departamento') dentro do componente, e ele simplesmente não está funcionando - até mesmo o novo valor registra para o console corretamente.

Aqui está a instância do FormBuilder:

initForm() {
  this.form = this.fb.group({
    'name': ['', Validators.required],
    'dept': ['', Validators.required],
    'description': ['', Validators.required],
  });
}

Este é o manipulador de eventos que recebe o departamento selecionado:

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // This is how I am trying to set the value
  this.form.controls['dept'].value = selected.id;
}

Agora, quando o formulário é enviado e eu saio, this.formo campo ainda está em branco! Eu já vi outras pessoas usarem, updateValue()mas isso é beta.1 e não vejo isso como um método válido para chamar o controle.

Eu também tentei ligar updateValueAndValidity()sem sucesso :(.

Eu usaria apenas ngControl="dept"o elemento do formulário, como estou fazendo com o restante do formulário, mas é uma diretiva / componente personalizado.

<ng-select
  [data]="dept"
  [multiple]="false"
  [items]="depts"
  (selected)="deptSelected($event)" <!-- This is how the value gets to me -->
  [placeholder]="'No Dept Selected'"></ng-select>

Eu já havia passado por uma situação semelhante, o cenário era o valor definido em http.get-subscribe e carregava o valor do formulário, mas definindo a linha de valor sendo executada primeiro, a assinatura realmente é executada posteriormente como assíncrona. para definir o valor na assinatura, verifique se está definido. my2cents!
HydTechie

Respostas:


326

Atualizado: 19/03/2017

this.form.controls['dept'].setValue(selected.id);

VELHO:

Por enquanto somos forçados a fazer uma conversão de tipo:

(<Control>this.form.controls['dept']).updateValue(selected.id)

Não é muito elegante, eu concordo. Espero que isso melhore em versões futuras.


6
Isso funciona muito bem, obrigado. Também é necessário limpar a validação: (<Control>this.form.controls['dept']).setErrors(null)
Man Called Haney

17
Ou ainda this.form.get('dept').setValue(selected.id):)
developer033

6
Apenas uma nota. Você também pode acessar a propriedade diretamente sem um indexador. this.form.controls.dept.setValue(selected.id);
James Poulose 16/03/19

mas isso não executará a validação para os novos dados !! Como disparar manualmente a detecção de alterações após a atualização?
ksh

1
É 2019 para mim isso funciona:this.form.controls['dept'].setValue(selected.id);
John Lopez

98

No Angular 2 Final (RC5 +), existem novas APIs para atualizar os valores do formulário. O patchValue()método API suporta atualizações parciais de formulário, onde precisamos especificar apenas alguns dos campos:

this.form.patchValue({id: selected.id})

Há também o setValue()método API que precisa de um objeto com todos os campos do formulário. Se houver um campo ausente, obteremos um erro.


7
Só para acrescentar que a partir de agora updateValue(da resposta aceita por Filoche) está sendo preterida em favor desetValue
superjos 30/08/16

2
Aqui está a solicitação de recebimento oficial no Github e a justificativa para descontinuar updateValue()e introduzir patchValuee setValue.
TheBrockEllis

mas isso não executará a validação para os novos dados !! Como a detecção manualmente mudança gatilho após atualização
ksh

16

A 2 final retangular atualizou APIs. Eles adicionaram muitos métodos para isso.

Para atualizar o controle de formulário do controlador, faça o seguinte:

this.form.controls['dept'].setValue(selected.id);

this.form.controls['dept'].patchValue(selected.id);

Não há necessidade de redefinir os erros

Referências

https://angular.io/docs/ts/latest/api/forms/index/FormControl-class.html

https://toddmotto.com/angular-2-form-controls-patch-value-set-value


diferença entre os dois - setValue()quando chamado em a formGroup/formBuilder, exige que todos os valores sob o formulário sejam definidos. patchValue(), quando chamado da mesma forma, poderia ser usado para atualizar valores específicos.
Vibhor Dube 03/06

11

Você pode usar os seguintes métodos para atualizar o valor de um controle de formulário reativo. Qualquer um dos métodos a seguir será adequado à sua necessidade.

Métodos usando setValue ()

this.form.get("dept").setValue(selected.id);
this.form.controls["dept"].setValue(selected.id);

Métodos usando patchValue ()

this.form.get("dept").patchValue(selected.id);
this.form.controls['dept'].patchValue(selected.id);
this.form.patchValue({"dept": selected.id});

O último método fará um loop completo de todos os controles no formulário, portanto, não é preferível ao atualizar o controle único

Você pode usar qualquer método dentro do manipulador de eventos

deptSelected(selected: { id: string; text: string }) {
     // any of the above method can be added here
}

Você pode atualizar vários controles no grupo de formulários, se necessário, usando o

this.form.patchValue({"dept": selected.id, "description":"description value"});

9

Você pode tentar o seguinte:

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // This is how I am trying to set the value
  this.form.controls['dept'].updateValue(selected.id);
}

Para obter mais detalhes, consulte o JS Doc correspondente em relação ao segundo parâmetro do updateValuemétodo: https://github.com/angular/angular/blob/master/modules/angular2/src/common/forms/model. ts # L269 .


Obrigado pela sua resposta - no entanto, updateValue não parece ser um método válido no angular2 beta.1 - Em qual versão você está e que pode usar esse método?
Matthew Brown

1
Datilografado dá o seguinte erro: error TS2339: Property 'updateValue' does not exist on type 'AbstractControl'. Nesse componente, o formulário tem o tipo de ControlGroup. Talvez se eu criá-los individualmente com new Control()isso funcionaria
Matthew Brown


3
  let cloneObj = Object.assign({}, this.form.getRawValue(), someClass);
  this.form.complexForm.patchValue(cloneObj);

Se você não deseja definir manualmente cada campo.


2

@ Solução atualizada Angular 2 da Filoche. UsandoFormControl

(<Control>this.form.controls['dept']).updateValue(selected.id)

import { FormControl } from '@angular/forms';

(<FormControl>this.form.controls['dept']).setValue(selected.id));

Como alternativa, você pode usar a solução da @ AngularUniversity, que usapatchValue


1

Eu sei que a resposta já foi dada, mas quero dar uma resposta breve como atualizar o valor de um formulário para que outros recém-chegados possam ter uma idéia clara.

sua estrutura de formulário é tão perfeita para usá-lo como exemplo. portanto, em toda a minha resposta, denotarei isso como a forma.

this.form = this.fb.group({
    'name': ['', Validators.required],
    'dept': ['', Validators.required],
    'description': ['', Validators.required]
  });

portanto, nosso formulário é um tipo de objeto FormGroup que possui três FormControl .

Há duas maneiras de atualizar o valor do modelo:

  • Use o método setValue () para definir um novo valor para um controle individual. O método setValue () segue estritamente a estrutura do grupo de formulários e substitui todo o valor do controle.

  • Use o método patchValue () para substituir quaisquer propriedades definidas no objeto que foram alteradas no modelo de formulário.

As verificações estritas do método setValue () ajudam a detectar erros de aninhamento em formulários complexos, enquanto o patchValue () falha silenciosamente nesses erros.

Da documentação oficial da Angular aqui

portanto, ao atualizar o valor para uma instância de grupo de formulários que contém vários controles, mas você pode querer atualizar apenas partes do modelo. patchValue () é o que você está procurando.

vamos ver o exemplo. Quando você usa patchValue ()

this.form.patchValue({
    dept: 1 
});
//here we are just updating only dept field and it will work.

mas quando você usa setValue (), é necessário atualizar o modelo completo, pois ele segue estritamente a estrutura do grupo de formulários. então, se escrevermos

this.form.setValue({
    dept: 1 
});
// it will throw error.

Devemos passar todas as propriedades do modelo de grupo de formulários. como isso

this.form.setValue({
      name: 'Mr. Bean'
      dept: 1,
      description: 'spome description'
  });

mas não uso esse estilo com frequência. Prefiro usar a seguinte abordagem que ajuda a manter meu código mais limpo e compreensível.

O que faço é declarar todos os controles como uma variável separada e usar setValue () para atualizar esse controle específico.

para o formulário acima, farei algo assim.

get companyIdentifier(): FormControl {
    return this.form.get('name') as FormControl;
}

get dept(): FormControl {
    return this.form.get('dept') as FormControl;
}

get description(): FormControl {
    return this.form.get('description') as FormControl;
}

quando você precisar atualizar o controle de formulário, use essa propriedade para atualizá-lo. No exemplo, o questionador tentou atualizar o controle do formulário de departamento quando o usuário seleciona um item na lista suspensa.

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // instead of using this.form.controls['dept'].setValue(selected.id), I prefer the following.

  this.dept.setValue(selected.id); // this.dept is the property that returns the 'dept' FormControl of the form.
}

Sugiro que dê uma olhada na API do FormGroup para conhecer todas as propriedades e métodos do FormGroup.

Adicional : para conhecer o getter veja aqui


1

Se você estiver usando o controle de formulário, a maneira mais simples de fazer isso:

this.FormName.get('ControlName').setValue(value);

-1

Dica: se você estiver usando, setValuemas não fornecendo todas as propriedades do formulário, receberá um erro:

Must supply a value for form control with name: 'stateOrProvince'.

Portanto, você pode ser tentado a usar patchValue, mas isso pode ser perigoso se você estiver tentando atualizar um formulário inteiro. Eu tenho um addressque pode não ter stateOrProvinceou stateCddepende se é americano ou mundial.

Em vez disso, você pode atualizar assim - que usará os nulos como padrões:

this.form.setValue( { stateOrProvince: null, stateCd: null, ...address } );
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.