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.

2
  • Can't you just have a container div inside your component with the required class? <div class='class.width-{{layoutColumns}}'> Commented Feb 1, 2018 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. Commented Feb 1, 2018 at 21:06

2 Answers 2

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);
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

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.
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%}

3 Comments

Still not what I've wanted but better than mine. I'll try it out, thanks.
The problem is that this works only for layoutIndex="1", a binding like [layoutIndex]="1" doesn't result in DOM attribute.
I'm not sure what you mean? (but I haven't tried what I wrote in my answer)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.