角计算ngfor累积值和总计通过父级

时间:2020-01-15 19:24:33

标签: angular

我正在尝试获取* ngFor循环中值列表的累积总数,但是必须将该值返回给父级,然后传递给for循环中的下一项,因此父级会知道总也。可以在以下位置找到代码沙箱:https://codesandbox.io/s/angular-test-01-n0hme?fontsize=14&hidenavigation=1&theme=dark

这些值不是在事件上计算的,而是在ngFor期间进行的,无需用户干预。

  1. 来自ngFor的计数(不使用索引),标题为“列表编号{{count}}”

  2. ngFor的累计总数以及for循环中的下一个项目都可以访问此值。

执行此操作的最佳方法是什么?

谢谢

D

文件:app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'test-app';

  listNo = 0;
  totalPriceOfAllLists: number = 0;

  lists = [
    {
      name: "item list 1",
      items: [{ name: "item 1", value: 10 }, { name: "item 2", value: 10 }]
    },
    {
      name: "item list 2",
      items: [
        { name: "item 1", value: 10 },
        { name: "item 2", value: 10 },
        { name: "item 3", value: 10 }
      ]
    },
    {
      name: "item list 3",
      items: [
        { name: "item 1", value: 10 },
        { name: "item 2", value: 10 },
        { name: "item 3", value: 10 },
        { name: "item 4", value: 10 }
      ]
    }
  ];

}

文件:app.component.html

<h2>Test App</h2>

<app-item
  *ngFor="let list of lists; let i = index;"
  [listIndex]="i"
  [list]="list"
></app-item>

<b>Total £ {{totalPriceOfAllLists}}</b>

<hr />
<div class="">
  list no 1 cumulativeTotal should be £20<br />
  list no 1 cumulativeTotal should be £50<br />
  list no 1 cumulativeTotal should be £90<br />
  Total should be £160
</div>

文件:item.component.ts

import { Component, OnInit, Input, AfterViewChecked } from "@angular/core";

@Component({
  selector: "app-item",
  templateUrl: "./item.component.html",
  styleUrls: ["./item.component.css"]
})
export class ItemComponent implements OnInit {
  @Input() listIndex: number; // shouldn't use index as it should be a counter increment from parent
  @Input() list: { name: string; value: number }[];

  listNo = 0;
  cumaliativeTotal = 0;

  constructor() {}
  ngOnInit() {
    console.log(this.list);
    this.getListTotal();
  }
  ngAfterViewChecked() {}

  getListTotal() {
    let total: number = 0;
    this.list.items.forEach(item => {
      total += item.value;
    });
    this.listTotal = total;
  }
}

文件:item.component.html

<div class="item">
  <!-- do not use index which is available as i -->
  <h4>List no {{ listNo }}</h4>

  <div *ngFor="let item of list.items;">
    {{ item.name }} - £{{ item.value }}
  </div>

  <p><b>List total £{{ listTotal }}</b></p>
  <p><b>Cumulative total £{{ cumulativeTotal }}</b></p>
</div>

2 个答案:

答案 0 :(得分:1)

对于我来说,一次用代码计算所有这些似乎更容易:

在应用程序组件中:

setListTotals(list) {

  const listWithTotals = list.reduce((acc, val) => {
    const listTotal = val.items.reduce((a, v) => a += v.value, 0)
    const cumulativeTotal = listTotal + acc.reduce((a, v) => a += v.cumulativeTotal, 0)
    return acc.concat([{...val, listTotal, cumulativeTotal}])
  }, [])

  return {listWithTotals, totalPrice: listWithTotals.reduce((a,v) => a += v.listTotal, 0)}
}

vm;
ngOnInit() {
  this.vm = this.setListTotals(this.lists);
}

和在模板中:

<h2>Test App</h2>

<app-item
  *ngFor="let list of vm.listWithTotals; let i = index;"
  [listIndex]="i"
  [list]="list"
></app-item>

<b>Total £ {{vm.totalPrice}}</b>

和孩子:

<div class="item">
  <!-- do not use index which is available as i -->
  <h4>List no {{ listNo }}</h4>

  <div *ngFor="let item of list.items;">
    {{ item.name }} - £{{ item.value }}
  </div>

  <p><b>List total £{{ list.listTotal }}</b></p>
  <p><b>Cumulative total £{{ list.cumulativeTotal }}</b></p>
</div>

只要列表更改完毕就重新运行设置列表总计功能。

叉状沙箱:https://codesandbox.io/s/angular-test-01-70lw3

答案 1 :(得分:0)

希望这就是您想要的。如果没有,请告诉我。我将相应地更新答案。 https://codesandbox.io/s/angular-test-01-gxif7

由于您的父级组件中有整个列表,所以为什么不在父级组件中计算累计总数并将其传递给子级组件。将名为 cumulativeTotal 的新属性添加到列表对象。

所以您的列表应该如下所示。

lists = [
    {
      name: "item list 1",
      items: [{ name: "item 1", value: 10 }, { name: "item 2", value: 10 }],
      cumulativeTotal:0 
    },
    {
      name: "item list 2",
      items: [
        { name: "item 1", value: 10 },
        { name: "item 2", value: 10 },
        { name: "item 3", value: 10 }
      ],
     cumulativeTotal:0
    },
    {
      name: "item list 3",
      items: [
        { name: "item 1", value: 10 },
        { name: "item 2", value: 10 },
        { name: "item 3", value: 10 },
        { name: "item 4", value: 10 }
      ],
     cumulativeTotal:0
    }
  ];

您应该有一种新的方法来计算每个列表的累计总数和所有列表的总价。

 calculateCumulativeTotal(list) {
    list.forEach(item => {
      item.cumulativeTotal = item.items.reduce(
        (cumulativeTotal, k) => cumulativeTotal + k.value,
        0
      );
    });

    this.totalPriceOfAllLists = list.reduce(
      (cumulativeTotal, k) => cumulativeTotal + k.cumulativeTotal,
      0
    );
  }

这是您的 app.component.html

<h2>Test App</h2>

<app-item
  *ngFor="let list of lists; let i = index;"
  [listIndex]="i"
  [list]="list"
></app-item>

<b>Total £ {{totalPriceOfAllLists}}</b>

<hr />
<div class="">
  <span *ngFor="let list of lists; let i = index;">
    list no {{i}} cumulativeTotal should be £{{list.cumulativeTotal}}<br />
  </span>
  Total should be £{{totalPriceOfAllLists}}
</div>

这是您的 app.component.ts

import { Component, Oninit } from "@angular/core";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements Oninit {
  title = "test-app";
  lists: any = [];
  listNo = 0;
  totalPriceOfAllLists: number = 0;

  ngOnInit() {
    this.lists = [
      {
        name: "item list 1",
        items: [{ name: "item 1", value: 10 }, { name: "item 2", value: 10 }],
        cumulativeTotal: 0
      },
      {
        name: "item list 2",
        items: [
          { name: "item 1", value: 10 },
          { name: "item 2", value: 10 },
          { name: "item 3", value: 10 }
        ],
        cumulativeTotal: 0
      },
      {
        name: "item list 3",
        items: [
          { name: "item 1", value: 10 },
          { name: "item 2", value: 10 },
          { name: "item 3", value: 10 },
          { name: "item 4", value: 10 }
        ],
        cumulativeTotal: 0
      }
    ];

    this.calculateCumulativeTotal(this.lists);
  }

  calculateCumulativeTotal(list) {
    list.forEach(item => {
      item.cumulativeTotal = item.items.reduce(
        (cumulativeTotal, k) => cumulativeTotal + k.value,
        0
      );
    });

    this.totalPriceOfAllLists = list.reduce(
      (cumulativeTotal, k) => cumulativeTotal + k.cumulativeTotal,
      0
    );
  }
}

这是您的 item.component.html

<div class="item">
  <!-- do not use index which is available as i -->
  <h4>List no {{ listIndex }}</h4>

  <div *ngFor="let item of list.items;">
    {{ item.name }} - £{{ item.value }}
  </div>

  <p><b>List total £{{ listTotal }}</b></p>
  <p><b>Cumulative total £{{ list.cumulativeTotal }}</b></p>
</div>

这是您的 item.component.ts

import { Component, OnInit, Input } from "@angular/core";

@Component({
  selector: "app-item",
  templateUrl: "./item.component.html",
  styleUrls: ["./item.component.css"]
})
export class ItemComponent implements OnInit {
  @Input() listIndex: number; // shouldn't use index as it should be a counter increment from parent
  @Input() list: { name: string; value: number }[];

  ngOnInit() {
    console.log(this.list);
  }
}