Angular: Wrap anchors with specific class with a span and add svg alongside anchor while styling both elements

35 Views Asked by At

I would like to know how I can automatically wrap all anchor elements with a class X with a span element. Then, add an svg to the span along with the anchor.

Illustration

Imagine I have any amount of anchor elements declared as such:

<a class="x">text</a>

Then after executing some given implementation I would like this to be the outcome:

<span>
<svg xmlns="http://www.w3.org/2000/svg">
<!-- SVG content here -->
</svg>
<a class="x">text</a>
</span>

All of this whilst retaining the ability to style all 3 elements.

Limitations

I cannot use:

  • A selector:'a' since I'm using Angular Material MatAnchor component which is already using this selector.

I would prefer not to:

  • Replace the anchor elements with a custom element/component.
  • Use an attribute selector.

Previous attempts

I've attempted to create a directive which dynamically creates a component to wrap the anchor:

import {Directive, OnInit, ViewContainerRef} from '@angular/core';
import {AnchorComponent} from "../components/typography/anchor/anchor.component";

@Directive({
  selector: 'a.x'
})
export class AnchorDirective implements OnInit {
  constructor(
    private viewContainer: ViewContainerRef,
  ) {

  }

  ngOnInit(): void {
    const nativeElement = this.viewContainer.element.nativeElement as HTMLAnchorElement;
    let anchorComponentComponentRef = this.viewContainer.createComponent(AnchorComponent,
      {
        projectableNodes: [[nativeElement]]
      });
  }
}

The component has the following template:

<span>
<svg xmlns="http://www.w3.org/2000/svg">
<!-- SVG content here -->
</svg>
<ng-content></ng-content>
</span>

The component has the following styling:

span > * {
  outline: 1px solid red;
  background-color: rgba(255, 255, 255, 0.4)
}

The above "works" in the sense that I am able to wrap the anchor with the span and add the svg. However, the styling is only applied to the svg and not to the anchor.

1

There are 1 best solutions below

0
Naren Murali On

Due to ViewEncapsulation of angular you are not able to see the CSS applied only for the stuff in <ng-content/> so we have two options to resolve this:

  1. You can use use ::ng-deep to try to style the contents.

css

::ng-deep span > * {
  outline: 1px solid red;
  background-color: rgba(255, 255, 255, 0.4)
}
  1. Set this style at the global-styles.scss so that we dont need ng-deep because its anyway deprecated!

code

span > * {
  outline: 1px solid red;
  background-color: rgba(255, 255, 255, 0.4)
}

Note: I am a bit worried how this CSS is structured, this code will apply the styles to all the elements that are inside the span, so it looks a bit dangerous, so please just add a unique class to the span to ensure the other contents is not affected.

Recommended CSS

span.ultra-unique-name > * {
  outline: 1px solid red;
  background-color: rgba(255, 255, 255, 0.4)
}