【发布时间】:2023-03-05 20:15:01
【问题描述】:
我有一个父母,它是一种形式。 此表单由两个子组件组成:
实验创建(父)
- 创建数据集(子)
- 创建元数据(子)
我使用 angular 组件 -> mat-accordion 来浏览两个子组件。 我使用@Input 将子组件中填充的结果填充到父组件中。 我只想在为他们俩都选择了文件的情况下提交表格。因此,我设置了一个变量(in datasetList[i].fileValid)来表示是否选择了文件。像这样,如果文件未更新,我禁用了该按钮。要禁用按钮,我调用了两个函数:
- isDatasetFilesValid()
- isMetadataFilesValid()
但是,当第二个子组件的变量发生更改时,它不会更新禁用的按钮。 只有当我按“上一个”和“下一个”时,这才有效。该按钮不再被禁用。就像我需要重新加载或刷新父级一样。也许是因为生命周期?
父组件:
export class ExperimentCreateComponent implements OnInit {
data: any = {};
datasetList: any = [{ fileValid: false }];
metadataList: any = [{ fileValid: false }];
// Functions to navigate through the expansion panels
setStep(index: number) {
this.step = index;
}
nextStep() {
this.step++;
}
prevStep() {
this.step--;
}
isDatasetFilesValid() {
return this.datasetList.findIndex(function(item, i) {
return item.fileValid == false;
});
}
isMetadataFilesValid() {
return this.metadataList.findIndex(function(item, i) {
return item.fileValid == false;
});
}
}
父 HTML:
<div class="jumbotron">
<div class="container">
<div class="row">
<div class="col-sm-8 offset-sm-2">
<form name="form" (ngSubmit)="f.form.valid" #f="ngForm" novalidate>
<mat-accordion class="headers-align">
<mat-expansion-panel id="datasetUpload" [expanded]="step === 0" (opened)="setStep(1)" hideToggle="true">
<app-creation-dataset [datasetList]="datasetList"></app-creation-dataset>
<mat-action-row>
<button mat-button color="warn" (click)="prevStep()">Previous</button>
<button mat-button color="primary" (click)="nextStep()">Next</button>
</mat-action-row>
</mat-expansion-panel>
<mat-expansion-panel id="metadataUpload" [expanded]="step === 1" (opened)="setStep(2)" hideToggle="true">
<app-creation-metadata [metadataList]="metadataList"></app-creation-metadata>
<mat-action-row>
<button mat-button color="warn" (click)="prevStep()">Previous</button>
<button mat-button color="primary" type="submit" [disabled]="(isMetadataFilesValid() != -1) && (isDatasetFilesValid() != -1)" (click)="createExperiment()">End</button>
</mat-action-row>
</mat-expansion-panel>
</mat-accordion>
</form>
</div>
</div>
</div>
</div>
子组件:
export class CreationDatasetComponent implements OnInit {
@Input() datasetList: any = [{ fileValid: false }];
fileSelected: File;
constructor(private papa: Papa, private cd: ChangeDetectorRef) {}
ngOnInit() {}
onChange(files: FileList, index: number, dom: any) {
// Option to parse the file with papaparse
let options = {
header: true,
error: (err, file) => {
this.datasetList[index].fileValid = false;
alert(
"Unable to parse CSV file, please verify the file can be accessed and try again. Error reason was: " +
err.code
);
return;
},
complete: (results, file) => {
console.log("Parsed:", results, file);
let filename = file.name;
// Add the dataset to the datasetList
this.datasetList[index].headers = results.meta.fields;
this.datasetList[index].values = results.data;
this.datasetList[index].filename = filename;
this.datasetList[index].is_metadata = false;
this.datasetList[index].fileValid = true;
this.cd.detectChanges();
}
};
this.fileSelected = files[0]; // Get the file
// Call the function to parse the file, option is the callback
this.papa.parse(this.fileSelected, options);
}
// Add a dataset form
addDataset() {
this.datasetList.push({ fileValid: false });
}
// Remove a dataset form
removeDataset(index: number) {
this.datasetList.splice(index, 1);
}
}
子 HTML:
<div *ngFor="let dataset of datasetList; let index = index">
<div id="datasetFiles">
<h6>Select the type of dataset and browse the files:</h6>
<div class="container">
<div class="row justify-content-between">
<div class="col-6 d-flex align-items-center">
<input id="file" #file (change)="onChange(file.files, index, $event.currentTarget)" type="file">
</div>
</div>
</div>
</div>
</div>
<div>
<button mat-icon-button color="primary" (click)="addDataset()">
<mat-icon>add_box</mat-icon>
</button>
</div>
【问题讨论】:
-
@Input 用于
pass variables FROM parent TO child,而不是@Output 用于pass variables FROM child TO parent.. 参见:angular.io/guide/… -
所以我应该使用@output 而不是@input?然而,它有效,我的意思是当我将它发送到我的服务器时,我拥有父级中子级的值。
-
您可以使用@Output 创建一个EventListener,它将您想要的变量传递给您的父组件。但是如果你想从父级初始化你的 children 变量,你仍然需要 Input
-
我真的不需要在父级中初始化它。我可以在孩子中初始化它吗?
-
是的,但您会失去“父值”。因此,如果您只想“要求您的父母更新一个值”,请创建一个输出事件,父母将听取然后更改您需要的内容。我可以举个例子
标签: javascript angular typescript