代码之家  ›  专栏  ›  技术社区  ›  juliano.net

使用FormBuilder生成的表单在服务订阅后未更新

  •  1
  • juliano.net  · 技术社区  · 7 年前

    this.getUser(+id); 执行,并且开发工具控制台上没有错误。我可以通过开发工具看到成功的HTTP请求/响应,但在我的表单中看不到更新。

    组成部分输电系统

    import { Component, OnInit } from '@angular/core';
    import { Router, ActivatedRoute } from '@angular/router';
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';
    import { NotificationsService } from 'angular2-notifications';
    
    import { UsersService } from '../../core/services/users.service';
    
    import { User } from '../../shared/interfaces/user';
    
    @Component({
      templateUrl: './users-form.component.html',
      styleUrls: ['./users-form.component.scss'],
        providers: [UsersService]
    })
    export class UsersFormComponent implements OnInit {
    
      userForm: FormGroup;
      user: User = {
        name: '',
        username: '',
        roleId: 3
      };
    
      formMode = 'Cadastro';
    
      constructor(
        private router: Router,
        private route: ActivatedRoute,
        private usersService: UsersService,
        private formBuilder: FormBuilder,
        private notification: NotificationsService) { }
    
      ngOnInit() {
        const id = this.route.snapshot.params['id'];
        this.buildForm();
        if (id) {
          this.formMode = 'Edição';
          this.getUser(+id);
        }
      }
    
      getUser(id: number) {
        this.usersService.getUserById(id)
          .subscribe((user: User) => {
            this.user = user;
          },
          (err) => console.log(err));
      }
    
      buildForm() {
        this.userForm = this.formBuilder.group({
          name: [this.user.name, Validators.required],
          username: [this.user.username, Validators.required],
          roleId: [this.user.roleId, Validators.required]
        });
      }
    
      submit({ value, valid }: { value: User, valid: boolean }) {
    
        value.id = this.user.id;
    
        if (value.id) {
          this.usersService.update(value)
            .subscribe((res: User) => {
              if (res) {
                this.router.navigate(['/users']);
                this.notification.success('Sucesso!', 'Registro atualizado.');
              } else {
                this.notification.error('Erro!', 'Registro não atualizado.');
              }
            },
            (err) => console.log(err));
        } else {
          this.usersService.insert(value)
            .subscribe((res: User) => {
              if (res) {
                this.router.navigate(['/users']);
                this.notification.success('Sucesso!', 'Cadastro realizado.');
              } else {
                this.notification.error('Erro!', 'Cadastro não realizado.');
              }
            },
            (err) => console.log(err));
        }
      }
    }
    

    组成部分html

    <div class="animated fadeIn">
      <div class="row">
        <div class="col-sm-12">
          <div class="card">
            <div class="card-header">
              <strong>Usuário</strong>
              <small>{{formMode}}</small>
            </div>
            <div class="card-block">
              <form [formGroup]="userForm" (ngSubmit)="submit(userForm)" novalidate>
                <div class="form-group">
                  <label for="name">Nome</label>
                  <input type="text" class="form-control" id="name" placeholder="Informe o nome" formControlName="name">
                  <div class="alert alert-danger" [hidden]="userForm.controls.name">Campo Nome requerido</div>
                </div>
                <div class="form-group">
                  <label for="login">Login</label>
                  <input type="text" class="form-control" id="username" placeholder="Informe o login" formControlName="username">
                  <div class="alert alert-danger" [hidden]="userForm.controls.username">Campo Login requerido</div>
                </div>
                <div class="form-group">
                  <label for="role">Perfil</label>
                  <select class="form-control" id="role" formControlName="roleId">
                    <option value="1">Supervisor</option>
                    <option value="2">Analista</option>
                    <option value="3">Inspetor</option>
                  </select>
                  <div class="alert alert-danger" [hidden]="userForm.controls.roleId">Campo Perfil requerido</div>
                </div>
                <div class="form-group">
                  <button class="btn btn-primary" type="submit" [disabled]="!userForm.valid">Salvar</button>
                  <button [routerLink]="['/users']" class="btn btn-secondary" type="button">Cancelar</button>
                </div>
              </form>
            </div>
          </div>
        </div>
        <!--/.col-->
      </div>
      <!--/.row-->
    </div>
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   joshrathke    7 年前

    你很接近。但当新值可用时,您需要使用新值更新表单。当您使用以下命令实例化表单时:

    name: [this.user.name, Validators.required],

    您只是告诉表单预先填充 name 价值为的财产 this.user.name ,这还没有解决(我猜)。它不是一个绑定,只是一个初始值。在这种情况下,表单的实例化速度比 getUser() 函数正在检索用户数据。

    您可以做的最简单的事情是等到API调用解决后再构建表单。

    getUser(id: number) {
        this.usersService.getUserById(id)
          .subscribe((user: User) => {
            this.user = user;
    
            // Now your form will have access to the correct data
            this.buildForm();
          },
          (err) => console.log(err));
      }
    

    在更复杂的场景中,您可能需要遍历数据并合并多个订阅。在这些情况下,您可以用空白值实例化表单,然后在API调用时更新这些值。

    getUser(id: number) {
        this.usersService.getUserById(id)
          .subscribe((user: User) => {
            this.user = user
    
                    // Update the Form Values
                    if (this.userForm) {
                        this.userForm.get('name').setValue(this.user.name);
                        this.userForm.get('username').setValue(this.user.username);
                        this.userForm.get('roleID').setValue(this.user.roleID);
                    }
          },
          (err) => console.log(err));
      }
    
        2
  •  1
  •   Jonalogy    7 年前

    再加上@joshrathke answer,下面应该可以为您节省更多的代码行。

    您可以选择使用 .patchValue() 直接:

    getUser(id: number) {
      this.usersService.getUserById(id).subscribe(user => {
          this.user = user;
          this.userForm.patchValue(this.user);
        },
        (err) => console.log(err)
      );
    }
    

    如果您的发射接口来自 .subscribe() 方法类似于 :user 界面,也可以选择使用 .setValue()

    getUser(id: number) {
      this.usersService.getUserById(id).subscribe(user => {
          this.user = user;
          this.userForm.setValue(this.user);
        },
        (err) => console.log(err)
      );
    }