首页 > 解决方案 > 在 Angular 7 中将数据恢复为反应形式

问题描述

我为自己设定了登录任务,获取现有用户详细信息,然后为用户提供编辑它们的能力。我有一个像这样的Angular 7反应形式:

userdetails.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 服务是否是绝对必要的——或者它是否应该只是 userservice 调用的一部分?)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 才能回到表单,我可能应该订阅它。

我尝试将它定义为 observable<UserData>and also observable<IUserData>(这是一个接口而不是一个类),但是这样做会破坏元素的分配。我觉得我很接近,但缺少一些基本的东西。

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

标签: angulartypescriptionic-frameworkrxjs

解决方案


您的代码不起作用的原因是它的异步。数据不会记录,因为日志是在数据到达之前执行的。

我建议先创建一个空表单,确保属性与数据中的属性完全匹配。你的方法是正确的。在您的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 时的提示:如果您订阅了 observables,您几乎会在所有需要取消订阅的地方阅读它们。但这只是事实的一半。如果您确定 observable 将要完成,那么您不必取消订阅。HttpClient.get 被设计为在它发出第一个值之后完成,或者抛出一个错误。因此,您不必取消订阅。但是在使用订阅时要注意。如果您阅读诸如take之类的运算符,您会更清楚地理解。


推荐阅读