Angular 角度应用组件体系结构

Angular 角度应用组件体系结构,angular,Angular,我目前正在尝试Angular 7*中应用程序组件的设计。由于没有对它做过很多工作,我发现很难设计一个干净的组件体系结构 这个组件,让我们称之为MainComponent,它接收一个JSON输入,例如 { "name": "name", "description": "description", "attributes": [ // Rectangle in the image { "attr1": "value", // Editable

我目前正在尝试Angular 7*中应用程序组件的设计。由于没有对它做过很多工作,我发现很难设计一个干净的组件体系结构

这个组件,让我们称之为MainComponent,它接收一个JSON输入,例如

{
   "name": "name",
   "description": "description",
   "attributes": [ // Rectangle in the image
      {
         "attr1": "value", // Editable
         "attr2": "value", // Editable
         "attr3": "value"  // Editable
      },
      {
         "attr1": "value", // Editable
         "attr2": "value", // Editable
         "attr3": "value"  // Editable
      },
      ...
   ]
}
重要的字段是属性。它的每个元素都将显示为一个单独的区域,我想将其编码为一个新组件

每个属性元素在主元素内变成一个矩形。 属性的每个字段都是可编辑的,因此必须构造FormGroup

但是,保存是全局的,而不是每个子组件。 我需要注意倾听每个组件中修改了哪些值

我考虑过两种解决方案

在主级别上有一个FormGroup,其中包含多个子FormGroup,每个子组件一个。每个子表单组都输入到子组件中。在保存时,我只查看主FormGroup,它已经包含所有更改的值

每个子组件都拥有一个单独的FormGroup。保存时,主组件要求调用每个子组件的方法来检索修改后的值

哪种解决方案最适合于角型?你会怎么做


编辑:我想问的是,如何更好地将JSON输入分发到多个子组件,并在保存时检索编辑的值,这是在上/主级别。我认为解决此类问题的最佳方法是数据共享。我们应该始终建立一种共同的服务。在那里放置一个表单组。并在每个组件中编写方法来更新该表单组的值。最后给出了一种求表单组值的方法。到目前为止,它是在服务中编写共享FormGroup代码的最佳方法

this.lotTwoFormGroup = this.formBuilder.group({
  title: ['', Validators.compose([Validators.required])],
  description: ['', Validators.compose([Validators.required])],
  dutchTitle: [''],
  dutchDescription: [''],
  frenchTitle: [''],
  frenchDescription: ['']
});
这是一个

我用过Formaray。欲了解更多信息,请阅读

首先,让我们创建一个输入组件,并将其称为MyInputComponent

并且,您可以在模板中使用此组件,如下所示

<div *ngFor="let attr of attributes; let i = index">
  <my-input></my-input>
  <hr />
</div>
export class AppComponent  {

  myForm = this.fb.group({
    array:  this.fb.array([])
  })

  attributes = [
    { 'attr1': 'value1', 'attr2': 'value12'},
    { 'attr1': 'value2', 'attr2': 'value22'},
    { 'attr1': 'value3', 'attr2': 'value32'},
  ];

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    const arrayFormControl = this.myForm.get('array') as FormArray;
    this.attributes.forEach(attr => 
      arrayFormControl.push(this.fb.control(attr)));
  }

  save() {
    console.log(this.myForm.value);
  }
}

并将主组件的模板更改为

<div [formGroup]="myForm">
  <div formArrayName="array">
    <div *ngFor="let attr of attributes; let i = index">
      <my-input [formControlName]="i"></my-input>
      <hr />
    </div>
    <button (click)="save()">Save</button>
  </div>
</div>

您可以调用共享组件并使用输入属性值创建表单组?编辑:问题是“保存”按钮在父组件上。@MsuArven“共享组件”是什么意思?是的,问题是那个!我认为最好的方法是使用formArray检查这个链接:@BunyaminCoskuner基本上在主组件中,我必须创建一个FormGroup,其中包含一个formArray的FormGroups?你是这么说的吗?因此,答案是选项1仅在主级别管理状态和表单组。此外,您需要使您的输入组件实现ControlValueAccessor,以便您可以在该组件上使用formControlName。非常感谢!有一个问题,在MyInputComponent中有一个值字段,它是非类型化的,因为接口使用任何类型。在这种情况下,它会是一个FormGroup吗?当您链接到它[formControlName]=iOkay时,它将是FormControl。只需阅读arrayFormControl.pushthis.fb.controlattr;这不是形式控制。它是你绑定的任何值。这样做的好处是MyInputComponent不知道如何使用它。您也可以使用ngModel而不是[formControlName]=i。好的!如何验证MyInputComponent中的单个属性?那不是个问题吗?是的,我想是的
@Component({
  selector: 'my-input',
  template: `
    <div>
      Attr1: <input type="text" [ngModel]="value.attr1" (ngModelChange)="updateModel($event, 'attr1')" />
    </div>
    <div>
      Attr2: <input type="text" [ngModel]="value.attr2" (ngModelChange)="updateModel($event, 'attr2')" />
    </div>
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MyInputComponent),
      multi: true
    }
  ]
})
export class MyInputComponent implements ControlValueAccessor {

  value;

  onChange;
  onTouched;
  disabled = false;

  updateModel(value, attrName) {
    this.value[attrName] = value;
    this.onChange(this.value); // now I call onChange method to update the value within form
  }

  // comes from ControlValueAccessor
  writeValue(newValue): void {
    this.value = newValue;
  }

  // comes from ControlValueAccessor
  registerOnChange(fn: (rating: number) => void): void {
    this.onChange = fn;
  }

  // comes from ControlValueAccessor
  registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
  }

  // comes from ControlValueAccessor
  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

}
<div [formGroup]="myForm">
  <div formArrayName="array">
    <div *ngFor="let attr of attributes; let i = index">
      <my-input [formControlName]="i"></my-input>
      <hr />
    </div>
    <button (click)="save()">Save</button>
  </div>
</div>
export class AppComponent  {

  myForm = this.fb.group({
    array:  this.fb.array([])
  })

  attributes = [
    { 'attr1': 'value1', 'attr2': 'value12'},
    { 'attr1': 'value2', 'attr2': 'value22'},
    { 'attr1': 'value3', 'attr2': 'value32'},
  ];

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    const arrayFormControl = this.myForm.get('array') as FormArray;
    this.attributes.forEach(attr => 
      arrayFormControl.push(this.fb.control(attr)));
  }

  save() {
    console.log(this.myForm.value);
  }
}