子项更改中的变量时更新父项-Angular

时间:2018-07-06 14:11:29

标签: javascript angular typescript

我有一个表格父母。 此表单由两个子组件组成:

创建实验(父级)

  • creation-dataset(子级)
  • 创建元数据(子级)

我使用角度组件-> mat手风琴浏览两个子组件。 我使用@Input将子组件中的内容填充到父项中。 我只想为两个都选择一个文件才提交表单。因此,我设置了一个变量(在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>

2 个答案:

答案 0 :(得分:3)

因此,为了使答案更清晰,请阅读有关问题的评论。

我将结束@Output的示例:

这是CHILD.COMPONENT.TS

@Component({
  selector: 'children',
  templateUrl: './children.component.html',
  styleUrls: ['./children.component.scss'],
  providers: [{...
  })
})

export class ChildrenComponent {

  @Output() editedEmitter = new EventEmitter<number>();
  
  private variableToPass = 10;
  
  constructor() {}
  
  functionToCall() {
    this.editedEmitter.emit(20);
  }

这是PARENT.COMPONENT.HTML

<section>
      <children (editedEmitter)="updateValue($event)"></children>
</section>

<!-- in the component you'll do 
  updateValue(val: number) {
    this.variableToUpdate = val;
  }
-->

答案 1 :(得分:1)

[disabled]需要一个条件(对或错),您输入的代码:isMetadataFilesValid() != -1 isDatasetFilesValid() != -1不是适当的条件,它们是两个。如果两个条件都成立,则使用&&表示法。

[disabled]="(isMetadataFilesValid() != -1) && (isDatasetFilesValid() != -1)"

或者,我建议将条件移至函数本身,以便它们返回布尔值。