Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculate only selected values of Angular Material selection list

I have a simple Angular Material selection list with some values inside it.

My requirement is to calculate the sum of the selected (checked) values only (and after that, apply a discount to the price, if it exceeds some amount).

I believe it must be easy, but I am new to Angular and Material components, and somehow cannot find what I want on Google or here... My code is as below:

HTML

 <mat-selection-list #options>
    <mat-list-option *ngFor="let option of optionArray">
      {{option.name}} - ${{option.price}}

    </mat-list-option>
  </mat-selection-list>

  <p>
    You have selected {{options.selectedOptions.selected.length}} items with total sum of $ {{  }}. </p>
  <p *ngIf="">
    Your discount is 10%. </p>

TS

interface Options {
  name: string;
  price: number;
}

optionArray: Options[] = [
    {
      name: 'Item 1',
      price: 4000
    },
    {
      name: 'Item 2',
      price: 8000
    },
    {
      name: 'Item 3',
      price: 3500
    },
    {
      name: 'Item 4',
      price: 500
    }
  ]

Thank you in advance!

like image 737
石井友梨 Avatar asked Dec 18 '22 13:12

石井友梨


2 Answers

Attach a model and a change event to your mat-selection-list element and then, you can use the javascript methods: map, reduce.

HTML:

<mat-selection-list #options [(ngModel)]="selectedOptions" (ngModelChange)="onSelectedOptionsChange($event)">
    <mat-list-option *ngFor="let option of optionArray">
        {{option.name}} - ${{option.price}}
    </mat-list-option>
</mat-selection-list>

<p>
    You have selected {{selectedOptions.selected.length}} items with total sum of $ {{ totalSum }}. </p>
<p *ngIf="..."> Your discount is 10%. </p>

TS controller:

onSelectedOptionsChange() {
    this.totalSum = this.selectedOptions
        .map((option: Options) => option.price)
        .reduce((priceA: number, priceB: number) => priceA + priceB)
}

Hope this helps.

like image 118
Ben Ari Kutai Avatar answered Jan 05 '23 01:01

Ben Ari Kutai


There are multiple ways to achieve it. Here is another way without binding to the model property and only using template variable.

Template

<mat-selection-list #options (selectionChange)="onSelectionChange()">
  <mat-list-option *ngFor="let option of optionsArray" [value]="option">
    {{option.name}} - ${{option.price}}
  </mat-list-option>
</mat-selection-list>

<p>You have selected {{options.selectedOptions.selected.length}} items with total sum of ${{ sum }}.</p>
<p *ngIf="discount">Your discount is 10%. </p>

Controller

export class ListSelectionExample {
  @ViewChild('options') optionsSelectionList: MatSelectionList;
  optionsArray: Options[] = [
    { name: 'Item 1', price: 4000 },
    { name: 'Item 2', price: 8000 },
    { name: 'Item 3', price: 3500 },
    { name: 'Item 4', price: 50 }
  ];
  sum = 0;
  discount = false;

  onSelectionChange() {
    this.getSum();
  }

  getSum() {
    this.sum = 0;
    this.discount = false;

    this.optionsSelectionList.selectedOptions.selected
      .map(s => s.value)
      .forEach(option => this.sum += option.price);

    if (this.sum > 12500) {   // apply discount if sum > $12500
      this.sum = this.sum * 0.9;
      this.discount = true;
    }
  }
}

Working example: Stackblitz

like image 32
ruth Avatar answered Jan 05 '23 00:01

ruth