【问题标题】:subscribe in Observable + formControl Angular 4订阅 Observable + formControl Angular 4
【发布时间】:2018-07-13 20:58:59
【问题描述】:

我需要在加载时在屏幕字段中显示从FireStore返回的数据,但是在订阅之前调用了buildForm(),所以没有显示屏幕上的字段中从 FireStore 返回的数据。

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>

我检查并正在返回 FireStore 值,但我无法返回屏幕。

【问题讨论】:

  • 使用默认值初始化constructor 中的表单,然后在订阅可观察时使用this.perfilForm.patchValue() 更改表单字段
  • @Hareesh 为什么我们需要在构造函数中?把它放在外面应该也可以。如果是构造函数,为什么不使用 ngOnInit?

标签: angular typescript firebase google-cloud-firestore angularfire2


【解决方案1】:

在订阅中使用 patchValue

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

【讨论】:

  • 谢谢,它也可以这样工作,但我会看看最正确的方法......谢谢。
【解决方案2】:

如果您希望 observable 填充您的表单,您必须在 subscribe 内调用 buildForm 或至少在 subscribe 内分配值。这是一个例子

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>

【讨论】:

  • 我认为formControlName 做的数据绑定和[(ngModel)] 一样,两者不能一起工作。
  • 抱歉,它正在与 [(ngModel)] 一起工作,现在它正在屏幕上显示数据,谢谢!
  • @Hareesh 如果您在保存时未在字段中输入值,则该对象带有未定义的字段而不是字符串。示例:{'name': undefined, 'city': undefined, .....} 应该是:{'name', "", 'city' "", .....}
  • @Safiyya 如果我保存空字段,保存时会出错...我正在发送 this.perfilForm.value 参数,字段不是字符串未定义示例:{'name' : undefined, 'city': undefined, .....} 应该是:{'name', "", 'city' "", .....}
  • @LuizCardoso 你如何保存?你添加了(submit)="save()" 吗?你也可以分享那个代码吗?
【解决方案3】:

当我留下一些空白字段时没有保存为空字符串并发生错误

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;
}

其余代码在问题的开头

【讨论】:

    猜你喜欢
    • 2017-11-30
    • 2017-05-12
    • 2020-06-19
    • 2018-01-24
    • 2018-05-25
    • 2019-08-16
    • 2018-12-12
    • 2016-10-28
    • 2019-01-25
    相关资源
    最近更新 更多