英文:
Is there a better way to structure an Angular 15 reactive form with inputs populating from an api?
问题
Angular 15 使用 FormGroup 的响应式表单
我正在查看文档,尝试构建一个具有 4 个输入字段的表单,这些字段使用 GET 数据填充,并在提交时通过 PUT 更新。它确实有效,但似乎有些冗长,我想知道是否有更好的方法。
以下是我的变量和构造函数:
adminForm: FormGroup;
parameters$: Observable<any[]>;
constructor(
@Inject("environment") public environment: IEnvironment,
private formBuilder: FormBuilder,
private adminService: AdminService
) { }
以及 ngOnInit:
ngOnInit() {
this.adminForm = this.formBuilder.group({
pendingTimeout: ['', Validators.required],
readyTimeout: ['', Validators.required],
processingTimeout: ['', Validators.required],
activeTimeout: ['', Validators.required]
});
this.parameters$ = this.adminService.getParameters();
this.parameters$.subscribe(p => {
console.log('p', p);
this.f['activeTimeout'].setValue(p[0].value);
this.f['pendingTimeout'].setValue(p[1].value);
this.f['processingTimeout'].setValue(p[2].value);
this.f['readyTimeout'].setValue(p[3].value);
})
}
一个 getter,用于减少 HTML 冗长性:
get f()
{
return this.adminForm.controls;
}
以及提交方法,配置为以正确的格式返回给 API:
submit() {
if (!this.adminForm.valid) {
return;
}
console.log(this.adminForm.value);
this.adminService.putParameters([
{
"name": "ActiveTimeout",
"value": this.adminForm.value.activeTimeout
},
{
"name": "PendingTimeout",
"value": this.adminForm.value.pendingTimeout
},
{
"name": "ProcessingTimeout",
"value": this.adminForm.value.processingTimeout
},
{
"name": "ReadyTimeout",
"value": this.adminForm.value.readyTimeout
}
]);
}
英文:
Angular 15 Reactive Form using FormGroup
I am going through the docs trying to build a form with 4 inputs that populate with GET data, and update on submit via PUT. And it works. But it seems verbose and I wonder if there is a better way.
Here are my variables and the constructor:
  adminForm: FormGroup;
  parameters$: Observable<any[]>;
  constructor(
    @Inject("environment") public environment: IEnvironment,
    private formBuilder: FormBuilder,
    private adminService: AdminService
  ) { }
and ngOnInit:
  ngOnInit() {
    this.adminForm = this.formBuilder.group({
      pendingTimeout: ['', Validators.required],
      readyTimeout: ['', Validators.required],
      processingTimeout: ['', Validators.required],
      activeTimeout: ['', Validators.required]
    });
    this.parameters$ = this.adminService.getParameters();
    this.parameters$.subscribe(p => {
      console.log('p', p);
      this.f['activeTimeout'].setValue(p[0].value);
      this.f['pendingTimeout'].setValue(p[1].value);
      this.f['processingTimeout'].setValue(p[2].value);
      this.f['readyTimeout'].setValue(p[3].value);
    })
  }
A getter, to make the html less verbose:
  get f()
    {
        return this.adminForm.controls;
    }
and the submit method, configured so it returns to the API in the proper format:
submit() {
    if (!this.adminForm.valid) {
      return;
    }
    console.log(this.adminForm.value);
    this.adminService.putParameters([
      {
        "name": "ActiveTimeout",
        "value": this.adminForm.value.activeTimeout
      },
      {
        "name": "PendingTimeout",
        "value": this.adminForm.value.pendingTimeout
      },
      {
        "name": "ProcessingTimeout",
        "value": this.adminForm.value.processingTimeout
      },
      {
        "name": "ReadyTimeout",
        "value": this.adminForm.value.readyTimeout
      }
    ]);
  }
答案1
得分: 1
你可以创建一个模型类,其中包含一个构造函数来接收结果参数,然后使用这个类对象来设置结果,而不是使用formControl['control'].value。一个示例可以是:
// 在一个单独的类中
export class AdminModel {
  public pendingTimeout: number;
  public readyTimeout: number;
  public processingTimeout: number;
  public activeTimeout: number;
  constructor(
    pendingTimeout: number,
    readyTimeout: number,
    processingTimeout: number,
    activeTimeout: number
  ){
    this.pendingTimeout = pendingTimeout,
    this.readyTimeout= readyTimeout,
    this.processingTimeout= processingTimeout,
    this.activeTimeout= activeTimeout
  }
}
// 在你的组件类中
adminForm: FormGroup;
admin: any;
parameters$: Observable<any[]>;
constructor(
  @Inject("environment") public environment: IEnvironment,
  private formBuilder: FormBuilder,
  private adminService: AdminService
) { }
ngOnInit() {
  this.adminForm = this.formBuilder.group({
    pendingTimeout: ['', Validators.required],
    readyTimeout: ['', Validators.required],
    processingTimeout: ['', Validators.required],
    activeTimeout: ['', Validators.required]
  });
  this.parameters$ = this.adminService.getParameters();
  this.parameters$.subscribe(p => {
    admin = new AdminModel(p[0].value, p[1].value, p[2].value, p[3].value);
  })
}
我认为这种方式更简洁,缺点是有重复的类,但这样更容易阅读和理解。希望对你有所帮助 :)
<details>
<summary>英文:</summary>
You can create a model class with a constructor to receive the result parameters, then use this Class Object to set the result instead of using the formControl['control'].value
A example would be like:
    //In a separated class
    export class AdminModel {
      public pendingTimeout: number;
      public readyTimeout: number;
      public processingTimeout: number;
      public activeTimeout: number;
    
     constructor(
            pendingTimeout: number,
            readyTimeout: number,
            processingTimeout: number,
            activeTimeout: number
    ){
                this.pendingTimeout = pendingTimeout,
                this.readyTimeout= readyTimeout,
                this.processingTimeout= processingTimeout,
                this.activeTimeout= activeTimeout
    }
//in your component class
      adminForm: FormGroup;
      admin: any;
      parameters$: Observable<any[]>;
    
      constructor(
        @Inject("environment") public environment: IEnvironment,
        private formBuilder: FormBuilder,
        private adminService: AdminService
      ) { }
    ngOnInit() {
        this.adminForm = this.formBuilder.group({
          pendingTimeout: ['', Validators.required],
          readyTimeout: ['', Validators.required],
          processingTimeout: ['', Validators.required],
          activeTimeout: ['', Validators.required]
        });
    
        this.parameters$ = this.adminService.getParameters();
    
        this.parameters$.subscribe(p => {
          admin = new AdminModel(p[0].value,p[1].value,p[2].value,p[3].value);
        })
      }
I thinks is less verbose, the cons are the duplicated classes, but it's easyer to read and understand like that. I hope it helps :)
</details>
# 答案2
**得分**: 1
我们总是重复类似的代码时,需要考虑是否创建一个函数是否合适。
```typescript
// 返回一个 formGroup 的函数
createGroup(data: any = null) {
  data = data || {
    pendingTimeout: '',
    readyTimeout: '',
    processingTimeout: '',
    activeTimeout: ''
  };
  return this.formBuilder.group({
    pendingTimeout: [data.pendingTimeout, Validators.required],
    readyTimeout: [data.readyTimeout, Validators.required],
    processingTimeout: [data.processingTimeout, Validators.required],
    activeTimeout: [data.activeTimeout, Validators.required]
  });
}
我们可以使用以下方式:
this.adminForm = this.createGroup(); // 一个空的 FormGroup
或者
this.parameters$.subscribe(p => {
  const data = {
    activeTimeout: p[0].value,
    pendingTimeout: p[1].value,
    processingTimeout: p[2].value,
    readyTimeout: p[3].value
  };
  this.adminForm = this.createGroup(data);
});
英文:
Always we repeat similar code we need think if it's good or not create a function.
//function that return a formGroup
createGroup(data:any=null)
{
data=data || {pendingTimeout: '',
readyTimeout: '',
processingTimeout:'',
activeTimeout:''}
return this.formBuilder.group({
pendingTimeout: [data.pendingTimeout, Validators.required],
readyTimeout: [data.readyTimeout, Validators.required],
processingTimeout: [data.processingTimeout, Validators.required],
activeTimeout: [data.activeTimeout, Validators.required]
});
}
we can use
   this.adminForm=this.createGroup(); //<--an empty FormGroup
Or
   this.parameters$.subscribe(p=>{
const data={
activeTimeout: p[0].value,
pendingTimeout: p[1].value,
processingTimeout: p[2].value,
readyTimeout: p[3].value
}
this.adminForm=this.createGroup(data)
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论