[英]Angular - application components architecture
I'm currently experimenting with the design of an application component in Angular 7.*
. 我目前正在尝试在
Angular 7.*
设计应用程序组件。 Not having worked a lot with it, I'm finding it hard to design a clean components architecture. 没有做很多工作,我发现很难设计一个干净的组件体系结构。
This component, lets call it MainComponent
receives a JSON
input such as 这个组件,让我们称它为
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
},
...
]
}
The important field is attributes
. 重要的领域是
attributes
。 Each of its elements will be displayed as a separate area, which I'd like to code as a new component. 它的每个元素都将显示为一个单独的区域,我想将其编码为一个新组件。
Each attributes
element become a rectangle inside the main one. 每个
attributes
元素在主元素内变成一个矩形。
And each field of an attribute
is editable, so a FormGroup
has to be constructed. 而且
attribute
每个字段都是可编辑的,因此必须构造一个FormGroup
。
However, saving is global, not per sub-component. 但是, 保存是全局的,而不是每个子组件。
And I need to take care of "listening" to which values have been modified inside each component. 而且,我需要注意“侦听”在每个组件中修改了哪些值。
I've thought about two solutions. 我考虑过两种解决方案。
Have a FormGroup
at the main level, with multiple sub- FormGroup
s, one per each sub-component. 在主级别具有一个
FormGroup
,具有多个子FormGroup
,每个子组件一个。 Each sub- FormGroup
is inputted inside a sub- Component
. 每个子
FormGroup
都输入到子Component
内部。 On save I just look at the main FormGroup, it already contains every changed value. 保存时,我只看主要的FormGroup,它已经包含每个更改的值。
Each sub-component owns a separate FormGroup
. 每个子组件都拥有一个单独的
FormGroup
。 On save, the main component asks (that is call a method) each sub-component to retrieve modified values. 保存时,主要组件要求 (即称为方法)每个子组件检索修改后的值。
Which solution is most suited to Angular
? 哪种解决方案最适合
Angular
? What would you do? 你会怎么做?
Edit : what I'm asking is what's the better way to distribute a JSON
input to multiple sub-components, taking care of retrieving the edited values on save, which is at the upper/main level. 编辑 :我要问的是将
JSON
输入分配到多个子组件的更好的方法是什么,请注意在保存时检索上级/主要级别的已保存值。
Here is a working solution. 这是一个可行的解决方案。
I've used FormArray
. 我用过
FormArray
。 For more info, read it here 欲了解更多信息,请在这里阅读
First, let's create an input component and call it MyInputComponent
首先,让我们创建一个输入组件并将其
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>
`
})
export class MyInputComponent {
value;
updateModel(value, attrName) {
this.value[attrName] = value;
}
}
It's a pretty simple component. 这是一个非常简单的组件。 It contains two inputs (you can add more) and binds a model to that input using
ngModel
. 它包含两个输入(您可以添加更多),并使用
ngModel
将模型绑定到该输入。 For now, it does not expose anything to outside world. 目前,它还没有向外界公开任何东西。 On change of any of the inputs, it updates
value
accordingly. 更改任何输入时,它将相应地更新
value
。
Now, let's use it in our main.component
现在,让我们在
main.component
使用它
Let's say you have following data 假设您有以下数据
attributes = [
{ 'attr1': 'value1', 'attr2': 'value12'},
{ 'attr1': 'value2', 'attr2': 'value22'},
{ 'attr1': 'value3', 'attr2': 'value32'},
];
And, you can use this component within your template as follows 而且,您可以按以下方式在模板中使用此组件
<div *ngFor="let attr of attributes; let i = index">
<my-input></my-input>
<hr />
</div>
Now, let's bind formArrayName
and formControlName
to that input. 现在,让我们将
formArrayName
和formControlName
绑定到该输入。
For that, we import ReactiveFormsModule
in our module and make MyInput
implement ControlValueAccessor
为此,我们在模块中导入
ReactiveFormsModule
并使MyInput
实现ControlValueAccessor
my-input.component
@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;
}
}
And change the template of main component to 并将主要组件模板更改为
<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>
And you need to create a formGroup
within main component as follows 并且您需要在主组件中创建一个
formGroup
,如下所示
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);
}
}
I think the best way to solve these types of problems (data sharing). 我认为解决此类问题(数据共享)的最佳方法。 we should always create a common service.
我们应该始终创建共同的服务。 place a single
FormGroup
there. 在那里放置一个
FormGroup
。 and write methods in each component to update the value of that form group. 并在每个组件中编写方法以更新该表单组的值。 and eventually a method to get value of form group.
最后是一种获取表单组值的方法。 It is by far the best method to write shared FormGroup code in services.
到目前为止,这是在服务中编写共享FormGroup代码的最佳方法。
this.lotTwoFormGroup = this.formBuilder.group({
title: ['', Validators.compose([Validators.required])],
description: ['', Validators.compose([Validators.required])],
dutchTitle: [''],
dutchDescription: [''],
frenchTitle: [''],
frenchDescription: ['']
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.