反应式@Input无法正确获取角度数据

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

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

Here is my 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 file:

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)

  }

My plotting component.ts is :

private _data: any; 

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

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

Here is the stackblitz

评论
  • walias
    walias 回复

    Using a BehaviorSubject in this case isn't elegant and might lead to too many subscriptions. You could just pass the data to setter and not worry about the change detection. Try the following

    容器组件

    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;
    }
    

    更新资料

    Old data from the variable scanData isn't removed before new data is pushed to it. So @Input() is working as expected, except the new data is getting appended to the end of the old data. You could just remove the old data using this.scanData = []; at the beginning of the upload() function. Try the following

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

    I've modified your Stackblitz.

    I've removed the CSV file check in the upload() function in the Stackblitz to get it working. If not, it kept throwing me the ''unknown file type. csv only' error. I've also assigned the type Array<{'x': number, 'y': number}> to the _data member variable in plotting component.