首页 > 解决方案 > Reactive @Input 没有以角度正确获取数据

问题描述

我有一个父组件(container.component)和一个子组件(plotting.component)。

从容器中,用户可以上传文件。一个提交按钮会将此数据发送到绘图组件。不幸的是,我只能将数据从容器发送到绘图一次。如果我尝试来回上传多个数据,则无法正常工作。绘图组件未使用正确的数据进行更新。

这是我的container.component.html

   <div class="input-group">
      <div class="custom-file">
        <input type="file" class="custom-file-input inputFile" id="inputFile" (change)="upload($event.target)" />
         <label class="custom-file-label" for="inputFile">{{fileName}}</label>
       </div>
    </div>

    <button class="btn btn-primary mt-2" (click)="passDAta()"> submit </button>
        
  

  <div class="card-body">
    <plotting [data]="data"></plotting>
  </div>

container.ts文件:

data = new BehaviorSubject<any[]> ([]);
  scanData: any = [];

upload(input: HTMLInputElement) {
    const files = input.files;
    const fileToRead = files[0];

    if (fileToRead.type === "text/csv") {
      this.fileName = fileToRead.name;

      const fileReader = new FileReader();

      fileReader.onload = event => {
        const result = fileReader.result;
        if (typeof result !== "string") {
          throw new Error("Unexpected result from FileReader");
        }
        result.split("\n").map(data => {
          let [a, b] = data.split(",");
          this.scanData.push(this.p2c(parseFloat(b), parseFloat(a)));
        });
      };

      fileReader.readAsText(fileToRead, "UTF-8");
    } else {
      this.fileName = " unknow file type. csv only"
    }
  }

  passDAta() {
    this.data.next(this.scanData);
    console.log("parent: ", this.scanData)

  }

plotting component.ts的是:

private _data: any; 

@Input()
  set data(data: Observable<any>) {
    data.subscribe(data => {
      this._data = data;
    });
  }
  get data () {
    return this._data;
  }

我也尝试过使用 ngOnchanges。但无法检测到变化。我还创建了一个 stackbliz。您可以下载 csv1 和 csv2。如果您来回上传文件,您会看到,数据不会从容器传递到绘图中。我该如何解决这个问题?

这是堆栈闪电战

标签: angular

解决方案


在这种情况下使用 aBehaviorSubject并不优雅,可能会导致订阅过多。您可以只传递datato setter 而不必担心更改检测。尝试以下

容器组件

data = [];

passDAta() {
  this.data = this.scanData;
  console.log("parent: ", this.scanData)
}

绘图组件

private _data: any; 

@Input()
set data(data: any) {
  this._data = data;
}

get data () {
  return this._data;
}

更新

scanData在将新数据推送到变量之前,不会删除变量中的旧数据。所以@Input()按预期工作,除了新数据被附加到旧数据的末尾。您可以在函数this.scanData = [];开头使用删除旧数据。upload()尝试以下

upload(input: HTMLInputElement) {
  this.scanData = [];
  .
  .
}

我已经修改了您的Stackblitz

我已删除upload()Stackblitz 函数中的 CSV 文件检查以使其正常工作。如果没有,它会一直向我抛出“未知文件类型”。仅 csv' 错误。我还将类型分配给绘图组件Array<{'x': number, 'y': number}>中的_data成员变量。


推荐阅读