1

I want to change my buttons color on event. I tried 2 approaches but both failed. With the first option I even couldnt start the app anymore, with the second option the color just doesnt change.

1. HTML

<ion-button [color]="done ? 'primary' : 'danger'"> </ion-button>

TS

public done: boolean = true;

func() { 
this.done = !this.done;
}

2. HTML

     <ion-button (click)="toggleNamedColor()"></ion-button>

TS

public ionicNamedColor: string = 'light';
public ionicNamedColor2: string = 'primary';

public toggleNamedColor(): void {
  if(this.ionicNamedColor === 'light') { 
    this.ionicNamedColor = 'primary'
  } else {
    this.ionicNamedColor = 'light'
  }
CMC
  • 79
  • 1
  • 3
  • 11
  • 1
    Have you tried playing with ngClass or anything of the various angular directives? https://stackoverflow.com/questions/44535515/angular-ngclass-and-click-event-for-toggling-class – canpan14 Jul 24 '19 at 17:43
  • first two code snippets should work, so when `func` is called, color should change. Worked fine for me when I tested it. Please provide a demo reproducing the issue. – AT82 Jul 24 '19 at 18:06
  • For the first approach you need to use `[style.color]="..."`. – Tom Jul 24 '19 at 18:24
  • 1
    @Tim, ionic 4 has `color = "..."`, different from angular. so when ternary operator with variable `[color]` is correct. – AT82 Jul 24 '19 at 18:29
  • The first syntax appears to work when `ion-button` is used a as attribute: ``. See [this stackblitz](https://stackblitz.com/edit/ionic-button-q8vtiv?file=pages/home/home.html). – ConnorsFan Jul 24 '19 at 19:12
  • @ConnorsFan , that is ionic 3, but syntax has changed in ionic 4 :) it should work just fine if OP is using ionic 4: https://stackblitz.com/edit/angular-ionic-4-rcuycb?file=src/app/home/home.page.html Tried both on this beta version and stable version. – AT82 Jul 25 '19 at 08:16

3 Answers3

3

You can do so using the ngStyle directive. Here's the stackblitz for the same.

.ts

export class AppComponent  {
  toggle: boolean;

  toggleColor() {
    this.toggle = !this.toggle;
  }
}

.html

<button (click)="toggleColor()"
        [ngStyle]="{
          'background-color' : toggle ? 'yellow' : 'pink'
        }"
>Click me</button>
Nicholas K
  • 15,148
  • 7
  • 31
  • 57
0

edit: dont do this

I would do it like this:

<ion-button [color]="getColor()"></ion-button>

Then write a your code behind that returns the colour you want:

getColor(): string {
  return this.done ? 'primary' : 'danger';
}
rtpHarry
  • 13,019
  • 4
  • 43
  • 64
  • how is this any different than the first two snippets OP has presented, also, this is worse, since calling a function in template, which is fired on each change detection. – AT82 Jul 24 '19 at 18:39
  • 1
    @ajt_82 - do you think I've intentionally tried to do things worse? If I've made a mistake be nice. – rtpHarry Jul 25 '19 at 03:03
  • I am interested in what you are saying though. I thought the idea was to move all logic out of the template and only have function calls. – rtpHarry Jul 25 '19 at 03:04
  • 1
    Sorry, didn't mean to sound harsh :) Calling functions in template is strongly discouraged, in worst case can cause what seems to be an infinite loop and crash your browser. It's not an infinite loop, it's just change detection happening. See following sample. Type in the input and see console on how `getColor` is called. Here we have just one input, what if we have lots of things going on in our component, like we usually do, change detection is happening all the time and that function is called over and over. https://stackblitz.com/edit/angular-ionic-4-wzh9eq?file=src/app/home/home.page.ts – AT82 Jul 25 '19 at 08:29
  • hmm thanks yes I see it's making a mess. Guess I have to go back to the drawing board for some best practices theory. So the ` ` is just as bad then? I guess its being run just as many times. You have to set the value elsewhere so its calculated once, and then trust that while the change detection isnt triggered by you updating the value, it is checking it often enough to see when you have. – rtpHarry Jul 26 '19 at 03:14
  • ` ` is exactly what you should do, use variables, angular can detect when the `done` property changes and act accordingly, but angular cannot detect if the value returned from `getColor()` has changed unless the function is run, thus angular needs to run it. Hopefully a bit clearer now :) – AT82 Jul 26 '19 at 07:36
  • 1
    This is a really simplified example, but what if the function did something really expensive, like a http-call, it would massively impact the performance, and that would also likely crash the browser, as the http-call would be called over and over. So only use functions in template if you know exactly what you are doing :) This is why angular team warns about impure pipes, since it's basically the equivalent of calling functions in template, as they are run on each change detection. Also a reason why there isn't an `orderBy` or `filter` pipe inbuilt in angular, like there was in angularjs. – AT82 Jul 26 '19 at 07:48
  • 1
    Thanks. Yes, I did do something expensive a few weeks back a scenario like this and totally melted the browser. I didn't really understand why at the time. Thanks for your insight :) – rtpHarry Jul 26 '19 at 08:51
0

Have a look Stackblitz

.ts File

export class AppComponent  {
  name = 'Angular';
  toggle: boolean ;
  propColor:string ='red' ;

  changeColor() {
    this.toggle = !this.toggle;
    if(this.toggle ==true){
      this.propColor = 'blue'

    }else{
      this.propColor = 'red'
    }

    //console.log(this.toggle);
  }
}

html template

<button (click)="changeColor()"
        [ngStyle]="{
          'background-color' :  propColor 
        }"
>Toggle Color</button>