1

I would like to know if it's possible to style a component through the 'styles' property of angular's @component object.

Here is an example of what I'm trying to achieve, pay attention to the {{ratio}} variable in 'styles' property.

@Component({
 selector: 'img-thumb',
 templateUrl: './img-thumb.component.html',
 styleUrls: ['./img-thumb.component.css'],
 styles: [`
   :host:after{
     content: '';
     display: block;
     padding-bottom: {{ratio}};
   }
 `],
 host: {
  '[style.height.px]' : 'height',
  '[style.padding.px]' : 'gap'
 } 
})

export class ImgThumbComponent implements OnInit {

 @Input() height : any
 @Input() gap : any
 @Input() ratio : any

 //More code...

 }

Basically I'm trying to implement :after on the host with a variable. If it's possible, I prefer to implement it inside the .ts file of the component.

7
  • The interpolation syntax is only for templates, not styles. Commented Oct 14, 2017 at 11:10
  • 1
    @jonrsharpe Thanks for your quick answer. I use the interpolation syntax to demonstrate what I'm trying to achieve. Commented Oct 14, 2017 at 11:23
  • Do you access to the img-thumb.component.html file? If you are comfortable in modifying that file, I would use the values of the @input variables directly on the HTML element using the [ngStyle] property biding syntax. Commented Oct 14, 2017 at 11:56
  • @Treeindev Yes, I can modify the html file as much as I want. though I'm not sure how its possible to add :after on the host component using [ngStyle]? Commented Oct 14, 2017 at 13:06
  • If you want to access the host from the class, see e.g. stackoverflow.com/a/34643330/3001761 Commented Oct 14, 2017 at 13:59

1 Answer 1

1

As it is not possible to add inline pseudo-element styles, one workaround would be to use Angular's renderer2 methods to create a new <style> tag and append it to the DOM at runtime. Here's a component:

import { Component, ElementRef, ViewChild, OnInit, Renderer2 } from '@angular/core';

@Component({
    selector: 'app-component',
    template: '<div #stylesContainer></div>'
})
export class singleComp implements OnInit{
    // Get destination container
    @ViewChild("stylesContainer") private stylesDist: ElementRef;

    // Define variable values
    height: string = "150px";
    gap: string = "30px";
    ratio: string = "10px";

    // Create the actual CSS style and store it in variables
    styleClass = ".class{ height: "+this.height+"; padding: "+this.gap+"}";
    pseudoStyle = ".class:after{content: '';display: block;padding-bottom: "+this.ratio+"}";

    constructor(private renderer: Renderer2) {}

    ngOnInit() {
        // Dynamically create the CSS tags
        const classStyle = this.renderer.createText(this.styleClass);
        const pseudoElementStyle = this.renderer.createText(this.pseudoStyle);

        // Insert the previously defined style into a new <style> element
        const newStyleElement = this.renderer.createElement('style');
        this.renderer.appendChild(newStyleElement, classStyle);
        this.renderer.appendChild(newStyleElement, pseudoElementStyle);
        this.renderer.appendChild(this.stylesDist.nativeElement, newStyleElement);
    }
}

In the component above the variables height, gap and ratio are hardcoded, but you can get them via @input. The HTML template contains a div with the local reference #stylesContainer this will be the destination element on where to dynamically append the styles.

When the component initialises, it generates a new <style> tag containing the dynamic styles including the pseudo-element ones. Then using the Renderer2 from Angular, it appends the new <style> tag back into the <div #stylesContainer> which you get from using @ViewChild

Sign up to request clarification or add additional context in comments.

2 Comments

Hi, Thanks a lot for your time, seriously appreciate it. Your solution solves the problem, but, it created a whole new html inside the component, with all the dependencies that my index.html holds. This causes two main problems: 1. Since I'm using this component alot through the whole application, it will affect the performance very badly. 2. The html created holds its own head and body tags, this might be an SEO issue according to some colleagues in my company.
It shouldn't create a new whole html inside, but just create a new <style> tag element and append it to the container. Where did you placed the local reference #stylesContainer?

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.