2

I have a list of sliders rendered in a Mat table, and a final slider is displaying the total. I need to reset the value to 0 if it is moved and the total is greater than 100. It works perfectly fine if I release the mouse within the slider element, but if I release the mouse little bit outside the element, value is not reset.

I need to access to the matSlider by reference or id to set the value in the mat-table. but I couldn't find a way to achieve this.

I have attached the code of whatever I have tried so far and also a link to stackblitz for the same. Can anyone help? thanks.

link to stackblitz

    <table mat-table [dataSource]="dataSource" class="mat-elevation-z8">

    <!--- Note that these columns can be defined in any order.
        The actual rendered columns are set as a property on the row definition" -->

    <!-- Position Column -->
    <ng-container matColumnDef="position">
        <th mat-header-cell *matHeaderCellDef> Name </th>
        <td mat-cell *matCellDef="let element"> {{element.name}} </td>
    <td mat-footer-cell *matFooterCellDef>
        total value slider
    </td>
    </ng-container>

    <!-- Name Column -->
    <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef> Slider </th>
        <td mat-cell *matCellDef="let element">
            <mat-slider (input)="element.value = $event.value" (onChange)="change(element)" (mouseup)="change(element)"
                (pointerup)="change(element)" (slideend)="change(element)" [ngModelOptions]="{standalone: true}"
                 [max]="element.max" [(ngModel)]="element.value" [min]="element.min">
            </mat-slider>
      {{element.value}}
        </td>
    <td mat-footer-cell *matFooterCellDef>
            <mat-slider [disabled]="true" #slider [max]="100" [min]="0" [value]="getTotal()"></mat-slider>
      {{getTotal()}}
    </td>

    </ng-container>


    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-footer-row *matFooterRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

</table>



<!-- Copyright 2019 Google LLC. All Rights Reserved.
    Use of this source code is governed by an MIT-style license that
    can be found in the LICENSE file at http://angular.io/license -->
    import {Component} from '@angular/core';

    export interface PeriodicElement {
      name: string;
      id: number;
      max: number;
      min: number;
      value : number;
    }

    const ELEMENT_DATA: PeriodicElement[] = [
    {id:1,name:"test1",max:100,min:0,value:0},
    {id:2,name:"test2",max:100,min:0,value:40},
    {id:3,name:"test3",max:100,min:0,value:50},
    ];

    /**
     * @title Basic use of `<table mat-table>`
     */
    @Component({
      selector: 'table-basic-example',
      styleUrls: ['table-basic-example.css'],
      templateUrl: 'table-basic-example.html',
    })
    export class TableBasicExample {
      displayedColumns: string[] = ['position', 'name'];
      dataSource = ELEMENT_DATA;

    change($event:any){
      console.log($event.value);

      if(this.getTotal() > 100){
        console.log('total is greater than 100');

        $event.value = 0
      }
    }

    getTotal(){

      return (this.dataSource.map(t => t.value).reduce((acc, value) => +acc + +value, 0));
    }

    }


    /**  Copyright 2019 Google LLC. All Rights Reserved.
        Use of this source code is governed by an MIT-style license that
        can be found in the LICENSE file at http://angular.io/license */
quant24
  • 393
  • 6
  • 22

1 Answers1

0

Try to remove mouseup, pointerup and slideend handlers and just use (change) instead so you're not dependent on where the mouse is released:

<mat-slider (input)="element.value = $event.value" (change)="change(element)" 
            [(ngModel)]="element.value" [ngModelOptions]="{standalone: true}"
            [max]="element.max" [min]="element.min">
</mat-slider>

Here I'm passing element to the change function, so it has to be slightly modified:

change(element: any) {
  console.log(element.value);
  if(this.getTotal() > 100){
    console.log('total is greater than 100');
    element.value = 0
  }
}

Here is a stackblitz

Kirill Simonov
  • 8,257
  • 3
  • 18
  • 42
  • this makes things really better than before..but one small thing,... if you click on the slider anywhere(instead of dragging) in the middle it sets the value as 0, but slider does not return back...is it possible to catch it? – Ashok Prabhu Jan 17 '20 at 22:26
  • @AshokPrabhu it looks like when you click the input event happens later or at the same time as change. You could try to delay it a little, see the updated stackblitz – Kirill Simonov Jan 18 '20 at 01:47