网站搜索

typescript - 在 Angular 7 中将数据返回到响应式表单


我给自己设定了一个任务,即登录、获取现有用户信息,然后为用户提供编辑这些信息的功能。我有一个像这样的 Angular 7 响应式表单:

用户详情.page.ts

    constructor(private formBuilder: FormBuilder,
    private currentuser: UserService,
    private router: Router ) {

     }

     ngOnInit() {
    // first we need to make sure the current user data is up to date.
      this.currentuser.getUserServer();
      //
        console.log('currentUser = ' + this.currentuser.data);


      this.userDetailsForm = this.formBuilder.group({
        id: [this.currentuser.data.Id],
        email: [this.currentuser.data.Email],  // [Validators.required, Validators.email]],
        username: [this.currentuser.data.UserName],
        dateofbirth: [this.currentuser.data.DateOfBirth],
        title: [this.currentuser.data.Title],
        firstname: [this.currentuser.data.FirstName],
        middlename: [this.currentuser.data.MiddleName],
        lastname: [this.currentuser.data.LastName],
        displayname: [this.currentuser.data.DisplayName],
        fullname: [this.currentuser.data.FullName],
        detailscomplete: [this.currentuser.data.Id],
        password: [this.currentuser.data.Password], // [Validators.required, Validators.minLength(6)]]
      });

  }

我正在尝试保持各个部分的分离,所以有一个用户服务和一个 API 服务。(但我不确定 API 服务是否严格必要——或者它是否应该只是用户服务调用的一部分?)正在使用的 API 服务(函数)是:

api.service.ts

  Get(endpoint: string) {
        const fullurl = this.ServerUrl + endpoint;
        return this.http.get(fullurl, {
          headers: {'Content-Type': 'application/json'}
        });

  }

我理解它返回一个可观察对象,而正是在这里我有点卡住了。来自服务器的 JSON 对象还包含一些无关的对象以及我需要的对象,所以我尝试只获取我想要的项目。中间的函数是这样的:

用户服务.ts

public data:  UserData;

getUserServer() {
  this.api.Get(this.api.GetUserDetailsEndPoint).subscribe(res => {
    console.log('Id from server = ' + res['Id']);
    this.data = {
    Id:           res['Id'],
    Email:        res['Email'],
    UserName:     res['UserName'],
    DateOfBirth:  res['DateOfBirth'],
    Title:        res['title'],
    FirstName:    res['FirstName'],
    MiddleName:   res['MddleName'],
    LastName:     res['LastName'],
    DisplayName:  res['DisplayName'],
    FullName:     res['FullName'],
    DetailsComplete: res['DetailsComplete'],
    Password:     res['Password']
    };
    console.log('This Data.Id = ' + this.data.Id)
  });
}

这能工作到获取数据的地步,并且 Id 的日志显示了正确的信息,其他的也都在那里。(上面最后一行。)然而,我觉得我需要将 this.data 本身变成一个可观察对象,以便回到表单,在那里我可能需要订阅它。

我尝试将其定义为 observable<UserData>,也尝试过 observable<IUserData>(这是一个接口而不是类),但这样做会破坏元素的赋值。我觉得我已经非常接近了,但缺少了一些基本的东西。

这是正确的方法吗?我如何将返回的数据实际放入表单中?然后我猜把它放回服务器的做法也会类似。

答案#1

你的代码无法工作的原因是它是异步的。数据不会被记录,因为日志在数据到达之前就执行了。

我建议先创建一个空表单,确保属性与数据中的属性完全匹配。你的方法是正确的。在你的 user.service.ts 中将代码切换为

getUserServer(): Observable<UserData> {
  return this.http.get<UserData>(`pathToEndpoint`);
}

在你的 userdetails.page.ts 中

constructor(private userService: UserService, ...) {}

ngOnInit() {
  this.userForm = this.formBuilder.group({
    Id: [],
    ...
  });

  this.userService.getUserServer().subscribe(user => this.userForm.patchValue(user.data));
}

表单提供的 patchValue 函数会对你的数据和表单之间所有匹配的键进行补丁操作。它会忽略表单中不存在的属性,反之亦然。你应该考虑将所有属性重命名为 lowerCamelCase。

一个关于使用 RxJS 的小提示:你几乎会在各处读到,如果你订阅了 observable,就需要取消订阅。但那只是事情的一半。如果你确定 observable 会完成,那么你不必取消订阅。HttpClient.get 在发出第一个值后就会完成,或者抛出一个错误。因此,你不必对它进行取消订阅。但是在使用订阅时请注意。如果你阅读像 take 这样的操作符,你会理解得更清楚。