How can we assign various class names depending on the value of an object?

I have a set of objects stored in my component. I need to dynamically apply different classes based on the value of the ErrorLevel property within each object. If an object has ErrorLevel equal to 1, I want to assign the following classes to various elements:

class-red
class-container-red
class-message-red

If the ErrorLevel is not equal to 1, I would like to assign the following classes to the elements instead:

class-yellow
class-container-yellow
class-message-yellow

Is there a more efficient way to achieve this using Angular or CSS (or SASS) without having separate methods for each individual class?

Here is an example code snippet showcasing what I currently have:

<html>
<body>
<div *ngFor="let obj of myObjects">
<h1 [ngClass]="getCssClass(obj.ErrorLevel)"></h1>
<p [ngClass]="getCssClass2(obj.ErrorLevel)"></p>
<div [ngClass]="getCssClass3(obj.ErrorLevel)"></div>
</div>
</body>
</html>
export interface MyObject {
    Id: number;
    ErrorLevel: number;
}

@Component({
  selector: 'my',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.scss']
})
export class MyComponent implements OnInit {
  @Input() myObjects: MyObject[];

  constructor() { }

  ngOnInit() {
  }

  getCssClass(errrorLevel) {
    if(errrorLevel === 1) {
      return "class-red";
    } else {
      return "class-yellow";
    }
  }

  getCssClass2(errorLevel) {
    if(errrorLevel === 1) {
      return "class-container-red";
    } else {
      return "class-container-yellow";
    }
  }

  getCssClass3(errorLevel) {
    if(errrorLevel === 1) {
      return "class-message-red";
    } else {
      return "class-message-yellow";
    }
  }
}

Answer №1

Here is a suggestion for styling your HTML elements using Angular syntax:

<div [class.class-red]="errorLevel === 1" [class.class-yellow]="errorLevel !== 1"></div>

This code will add the specified class based on the condition being true.

Alternatively, you can follow xyz's solution, but I personally prefer using the [ngClass] syntax as it tends to be more readable.

I want to point out that naming your CSS classes starting with "class-" is unnecessary since the period in CSS already indicates it is a class. Just use names like red instead of class-red.


For a more efficient approach, consider placing the class on the parent div rather than individual elements:

<div [class.red]="object.ErrorLevel === 1" [class.yellow]="object.ErrorLevel !== 1" *ngFor="let object of myObjects">
    <h1>...</h1>
    <p>...</p>
    <div>...</div>
</div>

Then use CSS to style the child elements based on the parent class:

.red h1 {
    // styles for red h1
}
.red p {
    // styles for red p
}
...
.yellow div {
    // styles for yellow div
}

This method is recommended for several reasons:

  1. Easier maintenance with one class applied to a single element, reducing the need to update multiple places when adding new color options.

  2. Improved readability by centralizing the styling logic in one location.

  3. Better performance as Angular only monitors changes on one element rather than multiple ones.

Answer №2

If your project requires managing more than 2-3 error color cases, I suggest the following approach:

interface IError {
   id: string;
   color: string;
}

var errors: { [id: string]: IError; } = {
   "e1": { id: "1", color: "class-red" },
   "e2": { id: "3", color: "class-yellow" },
   ...
   "en": { id: "n", color: "class-n" }
};

Then, you can proceed to implement the getValueById method.

UPDATE: You may consider implementing a similar solution like the one below. Please excuse any potential errors as this was written in notepad. :)

interface IErrors<T> {
    add(key: string, value: T): void;
    remove(key: string): void;
    containsKey(key: string): boolean;
    keys(): string[];
    values(): T[];
    errorClass(key: string): T;
}

class Dictionary<T> implements IErrors<T> {

    _keys: string[] = [];
    _values: T[] = [];

    constructor(init?: { key: string; value: T; }[]) {
        if (init) {
          for (var x = 0; x < init.length; x++) {
            this[init[x].key] = init[x].value;
            this._keys.push(init[x].key);
            this._values.push(init[x].value);
          }
        }
    }

    add(key: string, value: T) {
        this[key] = value;
        this._keys.push(key);
        this._values.push(value);
    }

    remove(key: string) {
        var index = this._keys.indexOf(key, 0);
        this._keys.splice(index, 1);
        this._values.splice(index, 1);

        delete this[key];
    }

    keys(): string[] {
        return this._keys;
    }

    values(): T[] {
        return this._values;
    }

    containsKey(key: string) {
        if (typeof this[key] === "undefined") {
          return false;
        }

        return true;
    }
    errorClass(key: string): T {
        return this[_keys]._values;
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

CSS-only method for creating a fixed position sidebar with adjustable width

https://i.stack.imgur.com/e4Gsv.png I have a vision of creating something similar to the image above solely using CSS. The design must incorporate the following elements: The image-container will hold a 3x4 aspect ratio image, filling the available heig ...

Safari-exclusive: Google Maps API dynamically altering page aesthetics post-loading

Recently, I encountered a peculiar problem. Upon loading a page, the text displayed with full opacity. However, upon the Google Maps API loading after 2 seconds, the entire page's styling suddenly changed. It was as if the text on the page became less ...

Enhancing the style of the top menu Index by applying a border-bottom effect when hovering over it in a CSS Horizontal Drop Down Menu

I'm having trouble adding a border-bottom: 1px solid #FFF to all the top menu (index) items when they are hovered over. Can anyone help me with this? #menu{ padding:0; margin:0; position: fixed; top: 30px; left: 0px; font-size ...

The server's file URLs are modified within the page source of a WordPress site

I've been attempting to integrate Adsense code into a WordPress blog at demonuts.com. I placed the Google code in the TEXT WIDGET provided by WordPress. However, upon running the website, I noticed that the URLs for .js, .css, or .png files are being ...

What is the best way to re-render a component immediately following an update in React?

As I attempt to change the color of a bar to green and then back to black, it seems like the latter color update is taking precedence in my code. const [color, setColor] = useState("black") const bubbleSort = async () => { const sleep = ms => ...

Angular2 routing does not trigger the Component constructor and Router life-cycle hooks when the router.parent.navigate method is called from a child component

I am currently working on an application that includes child routes. The parent component (App component) consists of 2 routes: @RouteConfig([ { path: '/overview', name: 'Overview', component: OverviewComponent, useAsDefault:true }, { ...

The dimensions of the pop-up window in Chrome's JavaScript are not displaying correctly

My goal is to launch a new chat room window on our website. The dimensions of the chat room are set to 750px x 590px. Below is the link I am using to trigger the javascript popup. <a href="javascript:void(0)" onclick="window.open('http://gamersuni ...

What is the best way to horizontally align an inline div using CSS?

Is it possible to apply CSS to center an inline div that has an unknown width? Note: The width of the div cannot be specified beforehand. ...

Ways to position the second section below the button

Is there a way to make a section of my website where, upon pressing a button, the button moves to the left and reveals collapsed text that appears below it with some padding on top? I've been trying to achieve this as a beginner by looking through doc ...

What is the method to cancel an Observable subscription without having a reference to the object of type "Subscription"?

If I were to subscribe to an Observable without an object of type "Subscription," how can I properly unsubscribe from it? For instance, if my code looks something like this: this.subscription = bla ... I know I can easily unsubscribe using the following ...

Placing a JavaScript button directly below the content it interacts with

I am currently working on a button that expands a div and displays content upon clicking. I am facing an issue where I want the button to always be positioned at the bottom of the div, instead of at the top as it is now, but moving it within the parent div ...

How can I bind the ID property of a child component from a parent component in Angular 2 using @Input?

I have a unique requirement in my parent component where I need to generate a child component with a distinct ID, and then pass this ID into the child component. The purpose of passing the unique ID is for the child component to use it within its template. ...

Rearrange information when the textarea is adjusted in size

One issue I am facing is that when I resize the textarea in my form, the content below the textarea does not move along with it. How can I ensure that the content moves accordingly when resizing the textarea? <form name="contactform" method="post" ...

How to harness the power of loops in JavaScript

Having trouble getting this code to repeat a CSS transition properly. for (var i=0 ; i<4 ; i++){ setTimeout(function() { $('#top-left').css('margin', '45px 0 0 45px'); $('#top-mid' ...

CSS - Dynamic triangle separator

I've been working on creating a triangle-shaped CSS divider. Using the code snippet below, I was able to achieve the desired result: border-width: 4vw 75vw 0 23vw; However, this method feels a bit unconventional. Since you can't use percentages ...

Tips for providing a base URL in Angular to fetch images from an API

How do I access the API URL to retrieve images from a database? <table class="table"> <tr> <th>Id</th> <th>Image</th> </tr> ...

Transmitting messages from a cross-domain iframe to the parent window

In my parent component, I am embedding an iframe from a different domain. The iframe contains a button that when clicked, I need to capture the event and pass it back to the parent component. I have experimented with using window.postMessage and window.ad ...

Exploring the Various Path Options in Angular 2 Routing

As a newcomer to Angular and Node JS, I am currently working on an application and struggling with how to efficiently navigate between my different components. Users can input the name of a user and add books associated with them When clicking on a book ...

Analyze the information presented in an HTML table and determine the correct response in a Q&A quiz application

I need to compare each row with a specific row and highlight the border accordingly: <table *ngFor="let Question from Questions| paginate: { itemsPerPage: 1, currentPage: p }"> <tr><td>emp.question</td></tr> <tr> ...

Angular: displaying dates in a specific format while disregarding time zones

Is there a way to format date-time in Angular using DatePipe.format() without converting timezones, regardless of location? For instance, for various examples worldwide (ignoring time differences) I would like to obtain 07/06/2022: console.log('2022-0 ...