Dimanoid
Dimanoid

Reputation: 7289

How to dynamically generate CSS class and/or set its property

The title is not really a question it is more like an idea, I don't know what approach is best for my situation.

So, the problem. I have some 3rd party component that have some complex structure and styling. Some part of it has some predefined CSS class that I can override with CSS in my surrounding component. Something like this:

my component:

<div class="my-cmp-container">
    <some-3rd-party-cmp></some-3rd-party-cmp>
</div>

3rd party component:

<div class="3rd-party-css-class">
    ...
</div>

For example, 3rd-party-css-class has style background-color: #f00, I can override it with .my-cmp-container .3rd-party-css-class { background-color: #fff; } etc. But. What if I need to set color dynamically, it's stored in a DB for example and I can't predefine each case in my class' CSS. I just have the color in hex.

In theory I can generate unique string to set as CSS class for every instance of some-3rd-party-cmp and somehow generate CSS in my component? I'm lost a little, what is the best approach for this?

Edit: Code sample to illustrate the situation https://stackblitz.com/edit/angular-kxdatq

Upvotes: 2

Views: 3729

Answers (2)

Martin Parenteau
Martin Parenteau

Reputation: 73761

What you are trying to do is the subject of this open issue about stylesheet binding in Angular. Until that feature is available, you can get what you want with a custom directive. Here is a directive that retrieves the checkbox element generated by ng-zorro-antd and applies two color attributes to it. The two colors are @Input properties and the directive implements OnChanges which allows to react to property binding changes.

@Directive({
  selector: "[nz-checkbox][nz-chk-style]"
})
export class CheckBoxStyleDirective implements OnInit, OnChanges {

  @Input("nz-chk-bkgnd") chkBkgndColor: string;
  @Input("nz-chk-border") chkBorderColor: string;

  private checkbox: HTMLElement;

  constructor(private renderer: Renderer2, private el: ElementRef) { }

  ngOnInit() {
    this.checkbox = this.el.nativeElement.querySelector(".ant-checkbox-inner");
    this.updateBackgroundColor();
    this.updateBorderColor();
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes.chkBkgndColor) {
      this.updateBackgroundColor();
    }
    if (changes.chkBorderColor) {
      this.updateBorderColor();
    }
  }

  updateBackgroundColor() {
    if (this.checkbox) {
      this.renderer.setStyle(this.checkbox, "background-color", this.chkBkgndColor);
    }
  }

  updateBorderColor() {
    if (this.checkbox) {
      this.renderer.setStyle(this.checkbox, "border-color", this.chkBorderColor);
    }
  }
}

Once the directive attribute selector nz-chk-style is applied to the 3rd party element, you can set the checkbox background and border colors with property binding as follows:

<span nz-checkbox nz-chk-style [nz-chk-bkgnd]="bkgndColor" [nz-chk-border]="borderColor" >

See this interactive stackblitz for a demo.

Upvotes: 1

Daniel Kemeny
Daniel Kemeny

Reputation: 690

Not sure if you are using Angular but you tagged it, so I guess you are.

If you want to change only the color and nothing more, instead of having a .3rd-party-css-class class, you could just have your with an ng-style like so:

<some-3rd-party-cmp ng-style="{ color: your_color_hex_variable }"></some-3rd-party-cmp>

You can also define a whole object if styles and pass it.

You can also use ng-class and pass one or an array of class names what you want to put additionally on your component:

<some-3rd-party-cmp ng-class="[cls1, cls2, cls3]"></some-3rd-party-cmp>

<some-3rd-party-cmp ng-class="[3rd-party-css-class, someCondition ? 'another-class-name' : '']"></some-3rd-party-cmp>

In the classes you can define the css rules you want to apply and thats it.

With this solutions you can avoid having extra wrapper elements for styling purposes which is a nice thing.

Upvotes: 0

Related Questions