2

I have a component with a numeric input. And based on that input value, I want to set a width to the component. I need to do it via class, because the width is calculated through sass variables and it is possible that it will be changed.

So I have three classes with different widths. Based on the input I want to set a class. I have it working, but it's incredibly ugly and I feel like an idiot for having this in my code:

@Input() public layoutColumns: number = 3;

@HostBinding('class.width-1') get isLayout1() { return this.layoutColumns === 1; }
@HostBinding('class.width-2') get isLayout2() { return this.layoutColumns === 2; }
@HostBinding('class.width-3') get isLayout3() { return this.layoutColumns === 3; }

Is it possible to somehow give argument to the get function so I don't have to have three of those? Or is that stupid because of some reasons?

Or do you know any other nicer way please? Or if something like this would be possible:

@HostBinding(`class.width-${layoutColumn}`);

Thank you for your time.

Laker
  • 1,622
  • 4
  • 20
  • 32
  • Can't you just have a container div inside your component with the required class?
    – David Feb 01 '18 at 21:03
  • I'll check that out, but I don't like to have redundant html elements in my template. It's possible like this, it should be possible programmatically and it shouldn't look as ugly as my code does. But thank you for the suggestion. – Laker Feb 01 '18 at 21:06

2 Answers2

1

Host bindings are supposed to be defined statically. HostBinding accepts string argument that leaves no place for dynamic behaviour.

Classes should be added and removed on the element, similarly to how it is done in ngClass directive:

constructor(private renderer2: Renderer2, private elementRef: ElementRef) {}

ngOnChanges({ layoutColumns }) {
  if (layoutColumns) {
    if (layoutColumns.previousValue)
      this.renderer2.removeClass(this.elementRef.nativeElement,
        'width-' + layoutColumns.previousValue);

    if (layoutColumns.currentValue)
      this.renderer2.addClass(this.elementRef.nativeElement,
       'width-' + layoutColumns.currentValue);
  }
}
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Oh, this looks great, didn't cross my mind. I'll try it out and if it works I'll accept your answer. Thank you very much. – Laker Feb 01 '18 at 21:51
0

Instead of using just a class, you can try to define css based on an attribute

//Component.ts
@HostBinding('attr.layoutIndex') layoutColumns : <type>;

//or 

@HostBinding('attr.layoutIndex') get layoutIndex(){return this.layoutColumns;}

And in your css file

//component.scss
[layoutIndex=1] {width: 100%}
[layoutIndex=2] {width: 50%}
David
  • 33,444
  • 11
  • 80
  • 118