【问题标题】:Calling a method from an Angular view only once仅从 Angular 视图调用方法一次
【发布时间】:2021-12-17 15:14:23
【问题描述】:

我用棱角材料制作了一张桌子。我有一个名为“matricula”的对象,在第一列中,我从矩阵列表中打印属性 matricula.matricula。在第二列中,我想打印一些数据,我从该 matricula.matricula 中调用了一个方法。我在我的 Typescrypt 文档中定义了我的方法,但由于它与 web 服务一起使用,我只想为每个时刻显示的对象调用该方法(随着我有一个分页器而变化)。我尝试使用 {{method}} 从视图中调用该方法,但由于 Angular 视图实时工作,该方法一直被调用并且项目崩溃。

我怎样才能对每个对象矩阵只调用一次?我确信这一定是可能的,但我不知道应该使用哪种工具或方法。

这是视图中的代码:


            <ng-container matColumnDef="matricula" style="flex: 0 0 10%;" >
                <th mat-header-cell *matHeaderCellDef> Matrícula </th>
                <td mat-cell *matCellDef="let matricula"height=70px> {{matricula.matricula}} </td>
            </ng-container>

            <ng-container matColumnDef="posicion" style="flex: 0 0 50%;">
                <th mat-header-cell *matHeaderCellDef> Ubicación </th>
                <td mat-cell *matCellDef="let matricula" height=70px> {{method(matricula.matricula)}} </td>
            </ng-container>

       

            <tr mat-header-row *matHeaderRowDef="mostrarColumnas"></tr>
            <tr mat-row *matRowDef="let matricula; columns: mostrarColumnas;"></tr>
        </table> 

编辑:这是方法中的代码:

    let matricula : MatriculaBuscada = {
      action : "ultima_posicion",
      matricula : placa
    }
    this.posicionService.posicion(matricula).subscribe(datos => {
    return datos;});
    console.log('método getDatos')
  }

posicionService 只调用一个 web 服务,该服务返回一个已映射的 Json。

【问题讨论】:

  • 使用OnInit
  • 我已经尝试过了,因为 OnInit 只初始化了一次,但我不确定它如何解决我的问题。我考虑为每个显示的元素调用该方法并将它们保存在一个数组中。问题是,一旦我这样做了,我显示数组的唯一想法就是一个循环方法,它打印数组的第一个元素并将其删除。这个方法会从视图中调用,所以它的问题是即使数组是空的,循环也会一直工作到无限。
  • 我不确定 Angular 模板是“实时的”是什么意思。 Angular 应该只在变更检测周期发现命中时重新渲染组件(从而调用方法)。
  • 也许我误解了为什么该方法被不间断地调用的原因,但关键是我只需要调用一次。
  • 每个变更检测周期都会调用该函数。请说明method() 函数是如何实现的。可能它可以移动到pipe

标签: angular typescript html-table angular-material


【解决方案1】:

如果您不能“分页”您的 API(参见 SO),我想最好的选择是订阅 matPaginator.changes。

我想你的服务有两个功能:getAllData - 返回不完整的数据 - 和 getData(id) - 返回一个项目的辅助数据

你可以在 ngAfterViewInit 中有一些类似的东西:-我用在例如具有周期元素的典型材料表

  ngAfterViewInit() {
    //I use the setTimeout for avoid
    // the error "ExpressionChangedAfterItHasBeenCheckedError"
    setTimeout(()=>{
      //simple get the data, getAllData simply return an array os "positions"
      this.dataService.getAllData().pipe(
        map((res: any[]) => {
          //create an object with all the properties necesary
          return res.map((x) => ({
            position: x,  //<--this is the only I get
            name: null,   //the rest properties I put as null
            weight: 0,
            symbol: null,
            yet: false,  //<--add this new property
          }));
        })
      ).subscribe((res:any[])=>{
        this.dataSource=new MatTableDataSource(res)
        this.dataSource.paginator = this.paginator;
        this.initPaginator()  //<--this is the "key"
      });
  
    })
  }
  initPaginator(){
    //I subscribe to paginator.page
    //happens always you change the page or the page size
    this.paginator.page.pipe(
      startWith(1),
      ).subscribe((_) => {

      //get the data that really is showed
      //and filter only I not loaded before
      const data = this.dataSource.filteredData
        .slice(
          this.paginator.pageIndex * this.paginator.pageSize,
          (this.paginator.pageIndex + 1) * this.paginator.pageSize
        )
        .filter((x: any) => !x.yet);

      //if there're data
      if (data.length) {
        this.isLoadingResults=true;
        //create a forkJoin -and array of Observables-
        //e.g. at first is a forkJoin of the array:
        //[this.dataService.getData(1),
        //   this.dataService.getData(2),
        //   ...]
        forkJoin(
          data.map((x: any) => this.dataService.getData(x.position))
        ).subscribe((res: any[]) => {

          //in subscribe, try to find the data
          res.forEach((x) => {
            let item = this.dataSource.data.find(
              (d: any) => (d.position == x.position)
            );
            //and put the properties I received
            if (item) {
              item.name=x.name;
              item.weight=x.weight;
              item.symbol=x.symbol;
              item.yet=true;
            }
          });

          this.isLoadingResults=false
        });
      }
    });
  }

你可以看到the stackblitz

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-02
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多