I'm using angular and I have a reactive form for editing an item. When I open the component for editing, the inputs load value for object correctly, but if I don't click the input and change value, the value in reactive form is empty.
My code here:
<form [formGroup]="entidadesForm">
<div class="row">
<div class="col-lg-12">
<nb-card>
<nb-card-header>Digite os dados solicitados</nb-card-header>
<nb-card-body>
<div class="form-group">
<label class="container-title" >Nome</label>
<input type="text" autocomplete="off" formControlName="Nome" value="{{nome}}" class="form-control" placeholder="Nome" class="form-control"
/>
</div>
<div class="form-group" *ngIf="entidade === 'setor' || entidade === 'unidadeproduto' " >
<label class="container-title">Descricao</label>
<input type="text" autocomplete="off" value="{{descricao}}"placeholder="Descricao" class="form-control" formControlName="Descricao"
/>
</div>
<div class="form-group" *ngIf="entidade === 'unidadeproduto' " >
<label class="container-title">Pode Fracionar</label>
<select class="form-control" formControlName="PodeFracionar" >
<option *ngIf="!atualizar"></option>
<option [selected]="podeFracionar == 'S'" value="S" >Sim</option>
<option [selected]="podeFracionar == 'N'" value="N" >Nao</option>
</select>
</div>
</nb-card-body>
</nb-card>
</div>
</div>
</form>
and ts file
constructor(private fb: FormBuilder, private entidadesProdutoService: EntidadesProdutoService, private route : ActivatedRoute, private router: Router, private location: Location) {
this.atualizar = false;
}
ngOnInit() {
this.route.queryParams.subscribe( params =>{
this.id = params['id'];
this.nome = params['nome'];
this.descricao = params['descricao'];
this.podeFracionar = params['podeFracionar'];
this.entidade = params['entidade'];
if(this.id !== undefined) this.atualizar = true;
});
this.entidadesForm = new FormsModels(this.fb).formularioModel(this.entidade)
}
salvar( ){
if(this.atualizar){
this.entidadesProdutoService.atualizar(this.id, this.entidadesForm.value, this.entidade).subscribe(response => {
this.location.back()
},
erro => console.log(erro))
}else{
this.entidadesProdutoService.salvar(this.entidadesForm.value, this.entidade).subscribe(response=>{
this.location.back()
},
erro => {
console.log(erro)
})
}
}
the component to define a form here:
import { FormBuilder, FormGroup } from '@angular/forms';
export class FormsModels{
constructor(public fb: FormBuilder){}
public formularioModel(entidade): FormGroup{
if(entidade === 'categoria' || entidade === 'marca' || entidade === 'subcategoria' || entidade === 'secao' ){
return this.fb.group({
Nome: this.fb.control('', [])
})
}
else if(entidade === 'setor'){
return this.fb.group({
Nome: this.fb.control('', []),
Descricao: this.fb.control('', [])
})
}
else if(entidade === 'unidadeproduto'){
return this.fb.group({
Nome: this.fb.control('', []),
Descricao: this.fb.control('', []),
PodeFracionar: this.fb.control('', [])
})
}
}
}
when i load the component the inputs load correct value, see the image:

if i edit only input nome for exemple, the form value of inputs descricao and the select input pode fracionar will empty, see the console here.

Your input fields are showing the correct value, because you set value="{{nome}}" in your html.
During your FormGroup creation you set an empty string as value in the control configuration this.fb.control('YOUR_EMTPY_STRING', []), so the value of the control is empty.
So you need to set the value of your controls during the FormGroup creation, e.g. like this:
this.route.queryParams.subscribe( params =>{
this.id = params['id'];
this.nome = params['nome'];
this.descricao = params['descricao'];
this.podeFracionar = params['podeFracionar'];
this.entidade = params['entidade'];
if(this.id !== undefined) this.atualizar = true;
// After receiving the router params init your FormGroup
this.entidadesForm = new FormsModels(this.fb).formularioModel(this.entidade)
});
...
public formularioModel(entidade): FormGroup{
if(entidade === 'categoria' || entidade === 'marca' || entidade === 'subcategoria' || entidade === 'secao' ){
return this.fb.group({
Nome: this.fb.control(this.nome, [])
})
} else if(entidade === 'setor'){
return this.fb.group({
Nome: this.fb.control(this.nome, []),
Descricao: this.fb.control(this.descricao, [])
})
} else if(entidade === 'unidadeproduto'){
return this.fb.group({
Nome: this.fb.control(this.nome, []),
Descricao: this.fb.control(this.descricao, []),
PodeFracionar: this.fb.control(this.podeFracionar, [])
})
}
}
Or otherwise you just update the value of your FormGroup like following:
this.route.queryParams.subscribe( params =>{
this.id = params['id'];
this.nome = params['nome'];
this.descricao = params['descricao'];
this.podeFracionar = params['podeFracionar'];
this.entidade = params['entidade'];
if(this.id !== undefined) this.atualizar = true;
// Updates the value of your FromGroup
this.entidadesForm.setValue({Nome: this.nome, Descricao: this.descricao, PodeFracionar: this.podeFracionar});
});
You're missing a fundamental design principle about Angular.
In Angular, the single point of truth is the model. Not the DOM. The DOM is generated based on the model. So value="{{descricao}}" and [selected]="podeFracionar == 'S'" for example are wrong.
You must not set the selected/entered value in the DOM. You must set it in the model. And Angular will set the value/select the option based on what the model contains, because the input/select is bound to the model.
So, initialize the values of the FormControls, when creating the FormGroup. And the view will display/select these values. You're doing the reverse, which is incorrect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With