0

I have a list of members, and each one has a role, I want to color its name based on its role. In my HTML I run with *ngFor to create each one a div, but I didn't manage to color the div.

Adam007
  • 71
  • 3
  • 8
  • 3
    Add your code to the question. – Anuradha Gunasekara Jun 04 '18 at 08:19
  • This can be closed under the official close reason: _Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question._ – halfer Aug 12 '18 at 11:46

3 Answers3

2
  1. The easiest way to do this is to just use the role of the member as your css class. Your html would simply be this:

    <div *ngFor="let member of members" class="{{member.role}}">
      {{member.name}}
    </div>
    

If for example you have a member list like this:

members = [
 {name: 'jan', role: 'admin'},
 {name: 'kees', role: 'user'},
 {name: 'piet', role: 'admin'},
 {name: 'joop', role: 'user'},
 {name: 'klaas', role: 'superman'},
];

your css would be like this:

.admin {
    background-color: yellow;
}

.user {
    background-color: red;
}

.superman {
    background-color: blue;
}
  1. Another way would be to use a function to determine the color for each role in your ts file:

    getColorClass(role: string) {
      let returnValue;
      switch (role) {
      case 'admin':
        returnValue = 'red';
        break;
      case 'user':
        returnValue = 'yellow';
        break;
      case 'superman':
        returnValue = 'blue';
        break;
      default:
        returnValue = 'white';
    }
    return returnValue;
    

    }

And use this function in your html like this:

<div *ngFor="let member of members" [style.background-color]="getColorClass(member.role)">
  {{member.name}}
</div>
  1. The thirth way would be to use ngClass in combination with the function from option 2. The returnvalue from the function would be the name of your class. Your html would look like this:

    <div *ngFor="let member of members [ngClass]="getColorClass(member.role)">
    {{member.name}}
    </div>
    

    And your css if you use the exact same function in your ts file as in option 2:

    .yellow {
      background-color: yellow;
    }
    
    .red {
      background-color: red;
    }
    
    .blue {
      background-color: blue;
    }
    

Ofcourse these class names can be changed to anything you want. Hope this helps.

Emmy
  • 3,493
  • 2
  • 16
  • 25
  • Hi guys, Thanks a lot for your answers. The problem with those suggestions are, the roles are being added by the users so the color could not retrived from css files. Second, regading the function retieving the color I tried it but it seems the function is constantly called and I was not sure it is fine solution. You can assume have the color on the member object. I thought about solution using template variable but I didn't manage to pull it out. – Adam007 Jun 05 '18 at 12:18
  • {{member?.member?.firstName}} {{member?.member?.firstName}} {{member?.member?.lastName}} {{member?.role?.roleName}} – Adam007 Jun 05 '18 at 12:23
  • The function gets called ones for every member you display, but that's how it is supposed to work. If I understand correctly you don't have the roles beforehand because the user provides them? The easiest I think would be to collect all the unique roles your user entered in an array. Then adapt the function so for example instead of case 'admin' it would say case yourArray[0] etc.. – Emmy Jun 05 '18 at 14:50
  • Emmy, your assumptions are right. I don't know how to implement it in the html, can I embed it in style="" or I need angular directive ? I tried to use the function method and I printed each call to console, I saw the function is constantly called. That's why I wonder if it is legit way – Adam007 Jun 06 '18 at 15:42
  • So apparently styles with functions get called multiple times because of change detection. The opinions on whether it is good practice to use this seem to differ. You can look a bit more into it if you want. See also: https://stackoverflow.com/questions/41471232/angular2-template-expression-called-twice-for-each-component-on-change-detection . – Emmy Jun 07 '18 at 07:05
2

So I though of an answer without having to use a function to get your style in your HTML, while still not having predefined roles.

You could add a color property to your members, which would be based on the role of the member. Assuming you know the members and the colors before the component is made you could set this in ngOnInit() like this:

ngOnInit() {
    this.assignColorsToMembers();
  }

  assignColorsToMembers() {
    const uniqueRoles = this.getUniqueRoles();
    const rolesWithColors = this.assignColorsToRoles(uniqueRoles);
    this.members.forEach(member => {
      member.color = rolesWithColors[member.role];
    });
  }

  getUniqueRoles(): string[] {
    const allRoles = this.members.map(member => member.role);
    const uniqueRoles = Array.from(new Set(allRoles));
    return uniqueRoles;
  }

  assignColorsToRoles(roles: string[]): RolesWithColors {
    const rolesWithColors = {};
    roles.forEach((role, index) => {
      rolesWithColors[role] = this.colors[index];
    });
    return rolesWithColors;
  }

Interfaces:

interface RolesWithColors {
  [key: string]: string;
}

interface Member {
  name: string;
  role: string;
  color?: string;
}

In getUniqueRoles() you make an array that get's the roles from all your members and then removes the duplicates. in assignColorsToRoles() you create an object where the keys (properties) are the roles from the array you made in getUniqueRoles() and the values are the colors from your colors array.

This assumes you have an array with colors similar to this: colors = ['red', 'yellow', 'blue', 'green', 'purple']; and the length of your colors array is sufficient to give each role a different color.

In case your colors array is not long enough you could check for this in the function:

assignColorsToRoles(roles: string[]): RolesWithColors {
  const rolesWithColors = {};
  roles.forEach((role, index) => {
    if (this.colors.length < index + 1) {
      rolesWithColors[role] = 'white';
    }
    rolesWithColors[role] = this.colors[index];
  });
  return rolesWithColors;
}

Ofcourse you can substitute white for any other colors you want.

If you already have your colors coupled to certain roles this will be a lot simpler. You can omit the first two steps of assignColorsToMembers, and alter the rest depending on how your roles and colors are saved (array or object).

Now that all members have a color assigned to them you can use this property in your html:

<div *ngFor="let member of members" [style.background-color]="member.color">
  {{member.name}}
</div>
Emmy
  • 3,493
  • 2
  • 16
  • 25
0

Try this:

<div *ngFor="let member of members">
 <div [ngClass]="{'red': member.role === 'name of the role', 'blue': member.role === 'name of the role'}">
  {{member.name}}
 </div>
</div>
halfer
  • 19,824
  • 17
  • 99
  • 186
Anuradha Gunasekara
  • 6,553
  • 2
  • 27
  • 37
  • The colors and roles are created by the users. So the values cannot be retieved from css or any constant variable in code. The color should be fetched from db/members object. – Adam007 Jun 06 '18 at 13:35
  • Then you just have to update the condition inside the `[ngClass]`. And can you add a sample of your colors and user roles to the question – Anuradha Gunasekara Jun 07 '18 at 06:41
  • Hi Anuradha, I didn't manage to assign the template variable a color(updated in every loop of the *ngFor), and push it in the ngClass can you give a simple example please ? – Adam007 Jun 08 '18 at 09:30
  • Please add a sample of your user role model. Atleast the array that you are using to generate the list. – Anuradha Gunasekara Jun 08 '18 at 09:38