我无法在重新加载时使用值动态填充表单 [英] I can't dynamically populate form with values on reload

查看:27
本文介绍了我无法在重新加载时使用值动态填充表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这段代码工作正常,模板部分没问题,这里的问题是模板被这个静态值(角色、权限和管理器)填充得很好

This code works fine, the template part is ok, the issue here is that the template get populated just fine with this static values (Roles, permissions and managers)

但是一旦我调用 API 并获取新值并更改角色对象或权限或管理器,表单就会读取初始空值

but once i call the API and get the new values and change the roles object or permissions or managers, the form read the initial empty values

也许它与订阅有关?主题 ?我不确定,因为我是 Angular 的新手

maybe it has something to so with subscription ? subject ? i'm not sure since i'm new to Angular

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl, Validators  } from "@angular/forms";
import { ManagersService } from "../../managers/managers.service";
import { NotificationService } from "../../notification/notification.service";
import { PermissionsService } from "../../permissions/permissions.service";
import { HttpClient } from "@angular/common/http";
import { environment } from "../../../../environments/environment";
import { Router, ActivatedRoute } from "@angular/router";
import { RolesService } from "../roles.service";

@Component({
  selector: 'app-edit-role',
  templateUrl: './edit-role.component.html',
  styleUrls: ['./edit-role.component.css']
})
export class EditRoleComponent implements OnInit {
  isLoading: boolean = false;
  roleId: number = +this.route.snapshot.params['id']
  roles: any;
  originalRole: any = {};
  role = { name: '', permissions: [], managers: [] };
  // permissions: any = {};
  // roles: any = {};
  
  permissions = [
    { id: 1, name: 'Can create category' },
    { id: 2, name: 'Can read category' },
    { id: 3, name: 'Can update category' },
    { id: 4, name: 'Can destroy category' }
  ];
  managers = [
    { id: 1, name: 'Amir' },
    { id: 2, name: 'Asmaa' },
  ];    
  
    
  constructor(
    private http: HttpClient,
    private router: Router,
    private route: ActivatedRoute,
    private fb: FormBuilder,   
    private notificationService: NotificationService,
    private rolesService: RolesService,
    private managersService: ManagersService,
    private permissionsService: PermissionsService
  ) { 
  } 
  ngOnInit(): void {
    this.rolesService.getRoles().subscribe(response => {
this.roles = response.body;
    this.originalRole = this.roles.find((el: any) =>  el.id === this.roleId)
    // this.permissions = this.originalRole.permissions;

    this.form.patchValue({
      'role': {
        'name': this.originalRole.name,
        'permissions': this.originalRole.permissions.map(a => a.id),
        'managers': this.originalRole.managers.map(a => a.id)
      }
    });

    console.log(this.role);
    this.isLoading = false;
    },
    error => {
      this.isLoading = false;
      this.notificationService.showNotification(
        error.error.title,
        error.error.details,
        'error'
      );
    })
  }

  form = new FormGroup({
    role: new FormGroup({
      name: new FormControl(this.role.name, [Validators.required]),
      permissions: new FormArray(
        this.permissions.map(
          x => new FormControl(this.role.permissions.find(p => p == x.id) != null)
        )
      ),
      managers: new FormArray(
        this.managers.map(
          x => new FormControl(this.role.managers.find(p => p == x.id) != null)
        )
      )
    })
  });
  get name() {
    return this.form.get('role.name') as FormArray;
  }
get rolePermisions() {
    return this.form.get('role.permissions') as FormArray;
  }
  get roleManagers() {
    return this.form.get('role.managers') as FormArray;
  }
  submit(form: FormGroup) {
    if (form.valid) {
      const data = {
        role: {
          name: this.form.value.role.name,
          permisions: this.permissions
            .filter((x, index) => form.value.role.permissions[index])
            .map(x => x.id),
          managers: this.managers
            .filter((x, index) => form.value.role.managers[index])
            .map(x => x.id)
        }
      };
      console.log(data);
    }
  }
}

如上所示,使用静态权限数组是可以的,但是当我将新获取的数组分配给权限变量时(注释掉的行),我仍然得到空的,是不是我在这里缺少一些东西要重新-正确填充值?

As shown above, it's ok to use the static permissions array, but when i assign the newly fetched array to the permissions variable (The commented out lines), i still get the empty one, am i missing something here to re-populate the values correctly ?

更新

我不知道你们是否理解我以更简单的方式

I'm not sure if you guys understood me or not in a simpler way

myRole: any = [];

  
  ngOnInit(): void {           
    this.rolesService.getRoles().subscribe(response => {
  
      let roles = response.body;
      let role = roles.find((el: any) =>  el.id === this.roleId)
      console.log(role)
      // This logs the role fine
      
      // Now setting the above variable
      this.myRole = role
    })

    console.log(this.myRole)
    // This NEVER want to be set, i know i'm missing something simple but i can't get it
  }

推荐答案

您有一个静态值,但您有一个返回角色和权限的服务.

You has a static values, but you has a service that return roles and permisions.

//your service, I imagine more or less 
//I use an unique service, perhafs you use two services

getPermissions(){
   return httpClient.get("yoururl/api/permissions");
}
getManagers(){
   return httpClient.get("yoururl/api/managgers");
}
getRole(id){ //(*)
   return httpClient.get("yoururl/api/role/"+id);
}

//(*) from your another question, if you has a function that return all the roles 
//you can has in your service a "cache" of roles

import {of} from 'rxjs'
import {tap,map} from 'rxjs/operators'
allRoles:any[]
getRole(id){ //(*)
   if (this.allRoles) //If exist, use "of" rxjs operator to return an observable of role
      return of(this.allRoles.find(x=>x.id==id)

   //else get all roles
   return httpClient.get("yoururl/api/getAllRoles").pipe(
      tap(res=>this.allRoles=res), //<--use tap to store in the variable the result
      map(res=>res.find(x=>x.id==id))  //<--use map to return only the role with id
   )
}
//be careful!!!!, if we "cache" the allRoles, rememeber after you edit a role
//"clean" de caché using:
        this.allRoles=null
//else you always received the caché roles

//similar, create a new variables "permisions" and "managers" to "cache"
//so the functions becomes
permisions:any[];
managers:any[];

getPermissions(){
   if (this.permisions)
       return of(this.permisions);
   return httpClient.get("yoururl/api/permissions").pipe(
      tap(res=>this.permisions=res));
}

//and
getManagers(){
   if (this.managers)
       return of(this.managers);
   return httpClient.get("yoururl/api/managgers").pipe(
       tap(res=>this.managers=res))
   )
}

(*) 轻敲运算符简单地接收到值以生成某物"与响应 - 通常它用于记录"或缓存"

(*) the tap operator simple received the value to make "something" with the response- generally it's used to "log" or to "cache"

您会看到,要创建 FormGroup,您需要获取角色"、权限"和权限"的值.和经理".

You see that, to create the FormGroup you need get the value of "role", "permissions" and "managers".

所以我们将在 ngOnInit 中做所有.如何获得所有可观察的?使用 forkJoin(是的另一个 rxjs 运算符)

So we are going to do all in ngOnInit. How get all observables? using forkJoin (yes another rxjs operator)

如果我们有一个变量id"我们可以扮演的角色

If we has in a variable "id" the role we can make

ngOnInit()
{
   forkJoin([this.roleService.getPermissions(),
            this.roleService.getManagers(),
            this.rolesService.getRole(id)]).subscribe(
              ([permisions,managers,role]:[any[],any[],any])=>{
                  this.permisions=permisions;
                  this.managers=managers;
                  this.role=role;
                  ..here we call to a funciton to create the formGroup..
              })
            )
}

(*)forkjoin 创建一个并行调用所有调用"的 observable,当完成所有调用"时返回结果 - 仅当调用是独立的时使用

(*)forkjoin create an observable that call in parallel all the "calls", when finished with all return the result -use only if the calls are independients

好吧,我们没有id"(因为我们是从参数中获取的)所以,来自 docs 我们

Well, we has not the "id" (because we get it from the params) so, from the docs we

ngOnInit(){
   this.activatedRoute.paramMap.pipe(
     switchMap(params => {
      const id=Number(params.get('id'));
      //here we has the "id"
      return forkJoin([this.roleService.getPermissions(),
                this.roleService.getManagers(),
                this.rolesService.getRole(id)]
    }).subscribe(([permisions,managers,role]:[any[],any[],any])=>{
         ....
       })
  );
}

(*) 切换映射reemplace";另一个可观察到的

(*) switchmap "reemplace" an observable by another one

这篇关于我无法在重新加载时使用值动态填充表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆