Sergey Rudenko
Sergey Rudenko

Reputation: 9227

change ngModel bound to data without triggering a function bound to ionChange - Ionic 3

I have an app with ion-range UI element that is bound to a var using [(ngModel)] (2way) and then i have (ionChange) event that triggers a function that uses the value of ion-range.

Sometimes I need to "set" the range to a specific position by directly changing the var which is bound to ngModel, but I need to avoid triggering ionChange during this operation.

if I do that straightforward (see changeValue method) - the ionChange event will fire the moment the data changes and I need to avoid that (I need to place knob into a new location without triggering the event)

I used a trick with a flag (see changeValueViaFlag method) - now it works as expected, note I also have to use timeout, cause if I don't delay setting flag back to its "normal" state - angular's change detection won't pick up;(

UPDATE:

I tried the trick with ngModelChange which can be found in SO here: ionChange - detect changes only from view to model in Ionic 2 - the problem is with ngModelChange - I am not getting the same "change detection" as I get with ionChange...

So in my app the range is used to select color intensity. If I switch to ngModelChange - shape color intensity is not happening...;/

Question: is there a better way to achieve what I want?

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  private testRange: number = 20;

  private flag: boolean = true;

  constructor(
    public navCtrl: NavController,
  ) {
  }

  logRange($event) {
      if (this.flag) {
        console.log("ionChange emitted: ",$event.value, this.testRange)
      }
  }
  
  changeValue() {
      this.testRange = 10;
  }

  changeValueViaFlag() {
      this.flag = false;
      this.testRange = 10;
      setTimeout(()=>{
        this.flag = true;
      }, 500)
  }
 
}
<ion-header>
  <ion-navbar>
    <ion-title>
      Ion range test case
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
    <ion-range [(ngModel)]="testRange" (ionChange)="logRange($event)">
    </ion-range>
    <button ion-button (click)="changeValue()">Change range value to 10</button>
</ion-content>

Upvotes: 2

Views: 3615

Answers (1)

Rising Sun
Rising Sun

Reputation: 11

click is a DOM event, not related to the higher level ngModel. The proper event for this is ngModelChange. If you want to use DOM events, then forget about ngModel and use $event inside the handler or a #ref.

So, instead of

<input [(ngModel)]="item.completed" (click)="completed(i)" type="checkbox">

it should be

<input [(ngModel)]="item.completed" (ngModelChange)="completed(i)" type="checkbox">

Upvotes: 1

Related Questions