3

For an Angular project I'm working on, I'm injecting HTML into a <div> like so:

<div class="myClass" [innerHTML]="htmlToInsert"></div>

The htmlToInsert contains a variety of things, notably <a> tags. Previously we were styling all these tags like so:

.myClass ::ng-deep a {
  color: #f00;
  text-decoration: none;
}

And this worked fine. But now I need the color of these links to be dynamically generated during component initialization, based on data coming in from elsewhere. All of the dynamic styling I've seen in Angular requires you to apply things directly to the HTML tag, but we don't have them here to work with.

How can I apply dynamic styling to HTML that is also dynamically generated? Can I directly change the CSS class somehow? Would using a pipe be the correct approach here? Is there another method I don't know about? I could maybe refactor code if there is absolutely no other way of doing this.

TheSoundDefense
  • 6,753
  • 1
  • 30
  • 42

1 Answers1

1

So if you can't modify the innerHTML you are passing in, you can achieve this functionality with a custom directive. Essentially you would tag your div that contains your innerHTML with a custom directive. That directive then looks for any anchor tags in it and changes the color based on an input.

// component.html
<div anchorColor [color]="dynamicColor" [innerHTML]="htmlToInsert"></div>

// directive.ts
@Directive({selector: '[anchorColor]'})
export class AnchorColorDirective implements OnAfterViewInit {
    @Input() color: string;

    constructor(private el: ElementRef){
    }

    // afterViewInit lifecycle hook runs after DOM is rendered
    ngAfterViewInit(){
        // get anchor element
        let anchorEl = this.el.nativeElement.querySelector('a');
        // assign color
        if(anchorEl){
            anchorEl.style.color = this.color;
        }
    }
}

Here is a working plunkr https://plnkr.co/edit/QSYWSeJaoUflP94Cy4Hm?p=preview

LLai
  • 13,128
  • 3
  • 41
  • 45
  • 1
    Oh wow, this looks really useful. I will try to implement this and if we can get it working I will come back and mark this answer as correct. Thanks! – TheSoundDefense Aug 07 '17 at 21:20
  • Also this seems like something you could generalize further by accepting the tag (or class or whatever) as an additional parameter. – TheSoundDefense Aug 07 '17 at 21:25
  • 1
    @TheSoundDefense absolutely! if you have a set amount of tags/colors, you could pass in a class to avoid inline styles altogether – LLai Aug 07 '17 at 21:27
  • 1
    This did work, but ultimately we decided that the best solution was to make changes in another layer for greater efficiency. Still, it's good to know people can do something like this. – TheSoundDefense Aug 10 '17 at 16:41
  • 1
    @TheSoundDefense I'm glad to hear that. I'd agree, that if possible, editing that html at a different layer is more optimal. But this is a nice trick to have – LLai Aug 10 '17 at 16:49