How to conditionally and dynamically set an ion-item background color

I have just been porting my app from Ionic 3 to Ionic 4.

I have a side menu, with a list of ion-items, and if selected would navigate to a new view. When the menu is shown, I shade the background slightly.

I have the following markup in my app.component.html

      <ion-list>
          <ion-menu-toggle auto-hide="false">
            <ion-item *ngFor="let p of availablePages" 
                      button=true lines='none' [routerLink]="[p.pageRoutePath]" 
                      [style.background]= "p.isCurrentPage ? '#F4F4F4' : ''">  /* < this line did the shading */
              <ion-avatar slot='start'>
                <img class='menu-icon' src='{{p.menuImage}}'>
              </ion-avatar>
              <div>{{p.title}}</div>
            </ion-item>

In Ionic 3, the following line took care of this shading…

[style.background]= "p.isCurrentPage ? '#F4F4F4' : ''"> 

But this no longer works.

When I look at the app in dev tools, I found the following element which will show the background (I have manually set it to pink in the dev tool while searching for which element to color…

Does anyone know how I can do this similar to how I did it before, ie conditionally set the background depending on a property value?

Thanks in advance for any help!

HTML:

<ion-item *ngFor=“let p of appPages” [routerDirection]="‘root’" [routerLink]="[p.url]" #rla=“routerLinkActive” [routerLinkActive]="[‘active’]" [disabled]=“rla.isActive”>
<ion-icon slot=“start” [name]=“p.icon”>

{{p.title}}

css:
ion-list ion-menu-toggle ion-item.active ion-label, ion-list ion-menu-toggle ion-item.active ion-icon, ion-list ion-menu-toggle ion-item.active{
color: #00FFFF !important;
–border-color: #00FFFF;
opacity: inherit !important;
}
ion-list ion-menu-toggle ion-item.active ion-icon.item-detail-icon {
opacity: inherit;
}

What you’ll find with ionic4 is that, because they added the shadow dom stuff, often setting a “regular” style in a component does not get applied to the element inside the shadow dom. In your case, you are setting a style on the ion-item, but ionic adds the #shadow-root layer, and then the item-native element inside it.

We’ve had much better success by using ionic’s --attribute stuff. So, try --background instead of background to the ion-item, and ionic will set background on item-native.

Hope this helps.

Thanks for the info @VictorNorman.

I tried a few things here, and just hardwired the color to 'Red' for testing…

<ion-item [attr.--background]= "red"></ion-item>
<ion-item [.--background]= "red"></ion-item>
<ion-item [style.--background]= "red"></ion-item>
<ion-item --background= "red"></ion-item>

But I could not get any of the above to work. Some through exceptions, others just didn’t color the item.

aside… I have also wanted to do the same thing with an ion-button, but would assume the same problem as with the ion-item (so if I can solve it for that, then should have it for the button as well)

Of course in the real app, I want to bind to a variable, as, especially in my button’s case, this can be any color at all.

Did you have any other trick on how to apply this?
Cheers

Thanks for the reply @ranjithreddy.

The above may be ok for just this router case, but I have other cases where I want to do similar things to other items, eg bind the background color of a ion-button to some color (and that color is not known till runtime).

@peterjc you can try this

<ion-item [class.favorite-background]="data.ticketData.splitItems.indexOf(order.$key) >= 0">
</ion-item>

inside theme/variables.scss

:root {
…
–ion-color-favorite: #69bb7b;
–ion-color-favorite-rgb: 105,187,123;
–ion-color-favorite-contrast: #ffffff;
–ion-color-favorite-contrast-rgb: 255,255,255;
–ion-color-favorite-shade: #5ca56c;
–ion-color-favorite-tint: #78c288;
}

inside global.scss

.ion-color-favorite {
–ion-color-base: var(–ion-color-favorite) !important;
–ion-color-base-rgb: var(–ion-color-favorite-rgb) !important;
–ion-color-contrast: var(–ion-color-favorite-contrast) !important;
–ion-color-contrast-rgb: var(–ion-color-favorite-contrast-rgb) !important;
–ion-color-shade: var(–ion-color-favorite-shade) !important;
–ion-color-tint: var(–ion-color-favorite-tint) !important;
}

1 Like

@peterjc, here is a solution for you.

The HTML:

<ion-content>
  <ion-list>
    <ion-item>
      <ion-label>I am item 1</ion-label>
    </ion-item>
    <ion-item [ngClass]="{ 'use-pink-background': item2BackgroundSet }">
      <ion-label>I am item 2. Value of backgroundSet: {{item2BackgroundSet}}</ion-label>
    </ion-item>
  </ion-list>
  <ion-button (click)="handleClick()">
    I am a button. Push me to toggle the background color of item 2.
  </ion-button>
</ion-content>

The .ts:

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  public item2BackgroundSet = false;

  constructor(
  ) {}

  handleClick() {
    this.item2BackgroundSet = !this.item2BackgroundSet;   // toggle true <-> false
  }
}

The .scss:

.use-pink-background {
  --ion-background-color: pink;
}

Using --ion-background-color is the key.

If you have questions about how this works, let me know and I can explain more.

2 Likes

Thank you @sereyvuthy! I could use the above to set the background of both a ion-item and an ion-button.

In the case of my item, I just wanted to toggle a background on and off, so, after following the above I have the following…

HTML

<ion-item *ngFor="let p of availablePages" 
     button=true lines='none' (click)="openPage(p)" 
    [class.selected-item]= "p.isCurrentPage">

SCSS

.selected-item {
     --background: #F4F4F4;
  }

So when p.isCurrentPage changed, the class as toggled as as needed.

For my button, it was a little more complicated, as I wanted to set this to any color (color is user set and comes from server data)

Here I had to do the following

HMTL

<ion-button #myButton class='my-button'>Mytext</ion-button>

SCSS

my-button {  
  --background:var(--ion-color-primary);
}

And then to change the color, I had to set the --background in code…

TS

@ViewChild('myButton') private myButton: any;
..
this.myButton.el.style.setProperty('--background', incomingColor);

So, all this works fine for the background!

The button text color, would still set via the binding, it is only the background color we seem to need to do this “special way”

[style.color]='myTextColour'

Cheers

Thank you @VictorNorman. This reply must have come in while I was trying the one from @sereyvuthy

I did get it working using the --background . I quickly try using the --ion-background-color, but for some reason, in my case (on the button at least) it didn’t work (perhaps it would on the ion-item)

@VictorNorman
Thank you so much!