使用FormBuilder构建的表单在服务订阅后不会更新

时间:2017-11-13 23:42:15

标签: angular

我的表单显示正确,但在执行this.getUser(+id);并且开发工具控制台上没有错误时,服务中的数据未应用于表单控件。我可以通过开发工具看到成功的HTTP请求/响应,但无法在我的表单中看到更新。

我的代码出了什么问题?

Component.ts

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

Component.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 个答案:

答案 0 :(得分:1)

你关闭了。但是,您需要在新值可用时更新表单。使用以下内容实例化表单时:

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

答案 1 :(得分:1)

添加@joshrathke答案,以下内容应该为您节省更多代码。

您可以选择直接使用.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)
  );
}