Luiz Ricardo Cardoso
Luiz Ricardo Cardoso

Reputation: 173

subscribe in Observable + formControl Angular 4

I need to display the data returned from the FireStore in the screen fields when loaded, but buildForm () is called before the Subscribe, so it does not display the data returned from the FireStore in the fields on the screen.

perfil-model.ts:

export class Perfil {
    nome: string;
}

authService.ts:

getPerfil() {
    return this.afs.doc<Perfil>(`perfil/${this.id}`)
      .snapshotChanges()
      .map(p => {
        return { ...p.payload.data() };
      });
  }

perfilUser.component.ts:

  perfil: Perfil = new Perfil();
  perfilForm: FormGroup;

  ngOnInit() {
    const subscribe = this.authService
    .getPerfil()
    .subscribe((p: any) => {
      subscribe.unsubscribe();
      this.perfil = p;
    })

    this.buildForm();
  }

  buildForm() {
    this.perfilForm = this.formBuilder.group({
      nome: this.perfil.nome,
    });
  }

perfilUser.component.html:

<form [formGroup]="perfilForm" novalidade>
        <div class="row">
          <div class="form-group col-12 col-sm-12 col-md-7 col-lg-4 col-xl-4">
            <label for="name">Nome*</label>
            <input type="text" class="form-control" formControlName="nome" placeholder="Nome">
          </div>
</form>

I checked and are returning FireStore values, but I'm not able to return the screen.

Upvotes: 1

Views: 3632

Answers (3)

Luiz Ricardo Cardoso
Luiz Ricardo Cardoso

Reputation: 173

when I leave some blank field is not saving as an empty string and error occurs

ERROR Error: Function DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field administrador)
    at new FirestoreError (error.js:149)
    at ParseContext.createError (user_data_converter.js:162)
    at UserDataConverter.parseScalarValue (user_data_converter.js:439)
    at UserDataConverter.parseData (user_data_converter.js:339)
    at eval (user_data_converter.js:362)
    at Object.forEach [as c] (obj.js:49)
    at UserDataConverter.parseObject (user_data_converter.js:361)
    at UserDataConverter.parseData (user_data_converter.js:331)
    at UserDataConverter.parseSetData (user_data_converter.js:212)
    at DocumentReference.set (database.js:489)

perfilUser.component.html:

<form [formGroup]="perfilForm" novalidade>
<div class="row">
  <div class="form-group col-12 col-sm-12 col-md-7 col-lg-4 col-xl-4">
    <label for="name">Nome*</label>
    <input type="text" class="form-control" [(ngModel)]="perfil.nome" formControlName="nome" placeholder="Nome completo">
  </div>

<button class="btn btn-success" type="button" (click)="saveProfile()">Save</button>

</form>

perfilUser.component.ts:

perfil: Perfil = new Perfil();

  saveProfile() {
    this.authService.createProfile(this.perfilForm.value);
  }

authService.ts:

@Injectable()
export class AuthService {

  perfil: Observable<Perfil[]>;
  userId: string;

  constructor(private afs: AngularFirestore) {
    this.afAuth.auth.onAuthStateChanged((user) => {
      if (user) {
        this.userId = user.uid;
      }
    })
}

createProfile(perfil: Perfil) {
    const userRef: AngularFirestoreDocument<Perfil> = this.afs.doc(`perfil/${perfil.userId}`);
    return userRef.set(perfil);
  }

perfilModel.ts:

export class Perfil {
    nome: string;
    ..... : string;
    ..... : string;
}

the rest of the code is at the beginning of the question

Upvotes: 0

Safiyya
Safiyya

Reputation: 1393

If you want the observable to populate your form, you have to call the buildForm inside the subscribe or at least assign values inside the subscribe. Here is an example

perfil.component.ts

nome:string;
constuctor(){
    this.perfilForm = new FormGroup({
       "nome": new FormControl(this.nome)
    });
}    

ngOnInit() {
    const subscribe = this.authService
    .getPerfil()
    .subscribe((p: any) => {
         subscribe.unsubscribe();
         this.nome = p.nome;
    })
  }

perfil.component.html

<form [formGroup]="perfilForm" novalidade>
    <div class="row">
      <div class="form-group col-12 col-sm-12 col-md-7 col-lg-4 col-xl-4">
        <label for="name">Nome*</label>
        <input type="text" class="form-control" formControlName="nome" placeholder="Nome" [(ngModel)]="nome">
      </div>
    </div>
</form>

Upvotes: 0

Arun Kumaresh
Arun Kumaresh

Reputation: 6311

use patchValue inside the subscribe

this.authService
    .getPerfil()
    .subscribe((p: any) => {
      this.perfilForm.patchValue({'nome' : p.nome})
    })

Upvotes: 1

Related Questions