【发布时间】:2020-08-18 09:07:42
【问题描述】:
我在父组件(LibraryComponent) 中有@ViewChildren 子组件(BookFormComponent)。在我的父组件中,我进行服务调用以获取一个 BookData 对象。
我将 DookData 对象赋予子组件initBookData(...) 的一个方法。我希望子组件使用 BookData 来初始化其表单控件。 BookData 有一个属性selectedTypes,其中包含用户已经选择的书籍数组。我使用数组来检查它的复选框。
有 10 个复选框,例如,如果用户在 selectedTypes 数组中有 5 个元素,则在显示视图时必须从 10 个复选框中选中这 5 个元素。
现在遇到的问题是name 和color 的表单控件使用来自BookData 对象的值进行初始化,但在显示视图时未选中(选中)复选框。我在子组件的initSelectedTypes(....) 内做了console.log(),数组的长度为0,同时子组件使用相同的数组来显示UI中的复选框,但是当它必须使用相同的数组来检查(选择)一些复选框,然后长度为 0。
我的理解是父组件UI中的<book-form #book></book-form>和组件类中的属性@ViewChildren(BookFormComponent) book: QueryList<BookFormComponent>;是一样的。因此,由于显示了视图,因此当我在属性(书)上调用方法时,我希望(书)的所有属性也被初始化。我不希望数组为空。所有复选框都在视图中正确显示,但是当我调用 initBookData(...) 时,数组为空。
我正在使用@ViewChildren,因为我尝试了@ViewChild,但我得到了“未定义”(所以甚至不能调用孩子的方法)
(为了节省空间,我在代码 sn-p 中省略了某些内容):
interface BookData {
name?: string,
color?: string,
selectedTypes?: Array<string> // this array contains the types a user has selected already
}
// PARENT COMPONENT CLASS
class LibraryComponent implements AfterViewInit, {
@ViewChildren(BookFormComponent) book: QueryList<BookFormComponent>;
// ADDITIONAL CHILDREN FOR OTHER mat-step omitted for clarity
bookData: BookData = {}
ngAfterViewInit(): void {
this.getBookData();
this.book.changes.subscribe((algemen: QueryList<BookFormComponent>) => {
book.first.initBookData(this.bookData);
});
}
// this method returns one book from the server and assigns it to "this.bookData"
getBookData() {
bookdataService.getBookData().subscribe(book => {
this.bookData = book;
});
}
}
// PARENT COMPONENT UI
<mat-horizontal-stepper #stepper linear>
<mat-step [stepControl]="book.bookForm">
<ng-template matStepLabel>Book</ng-template>
<book-form #book></book-form>
</mat-step>
<mat-step>
// ADDITIONAL STEPS ARE OMITTED FOR CLARITY
</mat-step>
</mat-horizontbal-stepper>
// CHILD COMPONENT CLASS
Component({
selector: 'book-form'
})
class BookFormComponent {
bookForm: FormGroup;
name = new FormControl('');
color = new FormControl('');
// Checkboxes for types of books a user can select. user can select multiple checkboxes
types = new FormArray([]);
optionsTypes = [];
ngOnInit(): void {
this.bookForm = this.fb.group({
name: this.name,
color: this.color
});
this.initializeTypesCheckboxes();
}
// This function will create 10 checkboxes that a user can select multiple of them
private initializeTypesCheckboxes() {
this.bookservice.getTypeOptions().subscribe(results => {
// the results from the server is array of strings of 10 elements
// eg: ["Maths", "English", "Chemistry", ...]
this.optionsTypes = results;
// we create checkboxes based on the number of types we get from the server
const typeCheckboxes = this.optionsTypes.map(t => new FormControl(false));
// we push the the checkboxes to the "this.types" form array
typeCheckboxes.forEach(type => this.types.push(type));
});
}
// This method is called from the parent component
public initBookData(bookData: BookData) {
this.naam.setValue(bookData.naam);
this.color.setValue(bookData.color);
this.initSelectedTypes(this.types, this.optionsTypes, bookData.selectedTypes);
}
// this method will use the already "alreadySelectedTypes" array to pre-select some of the checkboxes.
private initSelectedTypes(formArray: FormArray, optionsTypes: Array<string>, alreadySelectedTypes: Array<string>) {
for (let i = 0; i < formArray.controls.length; i++) {
for (const type of alreadySelectedTypes) {
if (optionsTypes === type) {
formArray.controls[i].patchValue(true);
}
}
}
console.log("LENGTH-formArray:", formArray.length); // i get O
console.log("LENGTH-optionsTypes:", optionsTypes.length); // i get O
}
}
我做错了什么?
【问题讨论】:
标签: javascript html angular typescript