How to update icon on tabs with custom image from a variable?

Hi Ionic team,

last time when I used Ionic 1 there was a hack that was used to display the custom image as the icon on my tabs.

I am currently using Ionic 2 I have looked into the code and I am not sure how to get started if I want to include my own image on the tabs as my icon.

Any leads would be helpful. CSS classes will not help because I can’t update them dynamically. Any other suggestion on how to do it would be highly appreciated as this is a big problem for me along with the fact that I can’t change colors dynamically on navbars and tabs bars from a value in one of my local variables either.

The Ionic team has done some spectacular work on making everything so simple but it seems to me that something so simple should not require developers to have to modify the DOM (as suggested here -> https://stackoverflow.com/questions/42386672/ionic-2-use-picture-in-tab-button) to be able to achieve something as basic changing the icon on a tab to a custom image.

This was an issue with Ionic 1 as well and it took such a long time to figure that one out(which still included manipulation of the DOM).

Hello.
show us a little bit of code. Maybe it is easier to help you,

If you can set your whatever with css, then you can with angular and use of ngclass and ngstyle make it dynamical. Especially with ngstyle you can make things dynamical at a granular level.

Best regards, anna-liebt

Hi Anna,

thanks for your reply. ngclass allows me to add a class and ng-style allows me to add a style. But when we create tab-icons the ion-icon is a separate tag. So nothing in ion-tab allows us to interact with the ion-icon that is being used in the tab via the tabIcon attribute. If you look at the following image you can see what I mean by that. In the chrome inspector I managed to change the content and it worked fine. But I can’t do that from ngstyle or ngclass. I am getting my colors from a call via a rest API and this means I need to dynamically update the value of my content(url info) but currently there is no other way than directly manipulating the DOM via code which is flat out terrible. If a property were to be given for the tabsIcon attribute then it would be so much easier. Or even just allowing us to declare the icon inside the ion-tab instead of having to use a self generated tabsIcon would allow the users to modify it to suit their needs. I am not sure if you want more examples of the code itself because there is very little in terms of actual code that is different to just a regular ion-tabs with two or three ion-tab components -
<ion-tabs tabsPlacement=“top” [color]=“headerColor”>
<ion-tab [root]=“Something” tabIcon=“bookmarks” tabTitle=“Something”>
<ion-tab [root]=“Something” tabIcon=“bookmarks” tabTitle=“Something”>
<ion-tab [root]=“Something” tabIcon=“bookmarks” tabTitle=“Something”>

.factory(‘AddCSSService’, [function() {
return function(selectors, declarations) {
var declarationString = “”;
angular.forEach(declarations, function(value, key) {
declarationString += key + “:” + value + " !important;"
});

    if (declarationString != "") {
        var sheet = document.createElement('style');
        sheet.innerHTML = selectors + " {" + declarationString + "}";
        //console.log("InnerHTML");
        //console.log(sheet);
        document.body.appendChild(sheet); 
    }
};

I used this previously in Ionic 1 to achieve the something similar. To go back to this seems like taking 10 steps back in terms of how we implement simple things like color change or change to ionic’s tabIcon image source.

Hello,

my english is quit bad. So maybe I understand you wrong.

[tabIcon]=“tab1icon” and in .ts tab1icon=‘alarm’; and with if(this.tab1icon ==‘bookmarks’){
this.tab1icon =‘alarm’;
}
else{
this.tab1icon =‘bookmarks’;
} you can toggle your icon as you need,

But I think you don’t want toogle an predefined ionIcon.

You want use a self made icon.
Maybe it is possible to add your icon to node_modules\ionicons\dist provided by ionic.

Best regards, anna-liebt

Hi Anna,

you don’t have to worry about your English to be honest. :slight_smile:

I am not trying to use a predefined icon. I have a rest service that has the link information that goes to the image which I can load via the url option in content of the tabsIcon.

Currently the ion-icon is not visible at the ion-tab level so there is no way for me to set the content on the ion-icon in the tab(tabicon).

I can’t use CSS because even the url is got from a Rest API so I can’t hard code the URL into the class either.

I hope you were able to visualize my problem.

You just need to bind a variable to the [tabIcon] property and then update the value of that variable:

In your template:

<ion-tabs [selectedIndex]="tabIndex" name="event">
  <ion-tab [root]="tab1Root" tabTitle="Discover" [tabIcon]="discover.icon"></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="Search" [tabIcon]="search.icon"></ion-tab>
  <ion-tab [root]="tab3Root" tabTitle="Me" [tabIcon]="me.icon"></ion-tab>
  <ion-tab [root]="tab4Root" tabTitle="My Events" [tabIcon]="myEvents.icon"></ion-tab>
</ion-tabs>

In your component:

this.discover.icon = 'beer';

See: Change icon type after clicking

That doesn’t work because my icons are not predefined. I am getting the url for the image for the icon from a Rest Service. So the only solution that I have found so far is -

updateAccountTab() : void {
let array = document.getElementsByClassName(‘tabbar’);
console.log(array);
let tabbar = array[1];
//let element = tabbar.childNodes[tabbar.childElementCount-1];
for(let i=1; i<4;i++){
let element = tabbar.childNodes[tabbar.childElementCount-i];
console.log(element);
if(element) {
console.log(element.childNodes[1]);
console.log(element.childNodes[2]);
element.removeChild(element.childNodes[1]);
let img = document.createElement(“img”);
img.setAttribute(“class”, “tab-icon-custom tab-button-icon icon icon-md ion-md-bookmarks”);
img.setAttribute(“src”, “http://blahblah.com/icons/skippythebear.png”);
element.insertBefore(img, element.childNodes[1]);
console.log(element);
}
}

I call this in the one of the lifecycles of my page. It’s a bit tricky though. You have to know which tabbar to access in which page otherwise your app could be screwed.

Hello,

maybe you can make your own tabs and tab component, I never have done this before, but in https://github.com/ionic-team/ionic/tree/master/src/components/tabs you can see how it is internal made. Maybe you can change inside tab-buttons the template to your needs.

best regards, anna-liebt

Hi Anna,

thanks for your reply.

In my opinion I think it is easier to manipulate the DOM once than changing the actual component just so that if I ever update Ionic I don’t have to redo my code for that section.

@Abhisht12, used your approach with some improvements, can be useful for someone:

  createTabsIcons() : void {
    let tabbar = document.getElementsByClassName('tabbar')[0];
    let tabs = tabbar.getElementsByTagName('a');
    for(let i=0; i < tabs.length; i++){
      let tabs = tabbar.getElementsByTagName('a');
      let img = this.createIconImage('myUri');
      tabs[i].insertBefore(img, tabs[i].childNodes[1]);
    }
  }

  private createIconImage(iconUri: string){
    let img = document.createElement("img");
    img.setAttribute("class", "tab-icon-custom tab-button-icon icon icon-md ion-md-bookmarks");
    img.setAttribute("style", "width:30px; height: 30px;");
    img.setAttribute("src", iconUri);
    return img;
  }
1 Like

Thanks @michalrzodkiewicz

That does look a lot cleaner.

Just for anyone using this solution please make sure to check what is the index of your tabbar selection. If you have tabs in tabs, you will have to know the tabbar index to be able to update the correct tabbar.

Isn’t the second line with

let tabs = tabbar.getElementsByTagName('a');

redundant?