Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make a structural directive to wrap part of my DOM?

I currently have the following line in my HTML:

<p> this is my first line </p>

Using a wrapper directive I want to add a second paragraph and wrap it in a div so it will look like this:

<p wrapper> this is my first line </p>

And then the directive will add the wrapper and second line to make the final HTML look like this:

<div>
    <p> this is my first line </p>
    <p> this is my second </p>
</div>

From what I understand from angular.io I will need to create a structural directive and use a TemplateRef and a ViewContainerRef, but I can't find an example on how to use them to wrap an existing part of the dom and add a second line.

I'm using Angular 5 in this project.

like image 534
Friso Avatar asked Jan 29 '18 10:01

Friso


People also ask

What are structural directives in HTML?

Structural directives are a type of directive which changes the structure of the DOM. We use the <ng-template> tag to define the element we want to insert into the DOM. We can prepend the directive name with * to skip having to define a <ng-template> and have the directive use the element it’s attached to as the template.

Can you apply more than one structural directive to an element?

You may apply only one structuraldirective to an element. The reason is simplicity. Structural directives can do complex things with the host element and its descendents. When two directives lay claim to the same host element, which one takes precedence?

What is the asterisk in front of a structural directive?

When structural directives are applied they generally are prefixed by an asterisk, *, such as * ngIf. This convention is shorthand that Angular interprets and converts into a longer form. Angular transforms the asterisk in front of a structural directive into an <ng-template> that surrounds the host element and its descendants.

How do I create a directive from a component?

Creating a directive is similar to creating a component. Import the Directivedecorator (instead of the Componentdecorator). Import the Input, TemplateRef, and ViewContainerRefsymbols; you'll need them for anystructural directive.


2 Answers

I made the directive like so:

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

@Directive({
    selector: '[wrapper]'
})
export class WrapperDirective implements OnInit {

    constructor(
        private elementRef: ElementRef,
        private renderer: Renderer2) {
        console.log(this);
    }

    ngOnInit(): void {
        //this creates the wrapping div
        const div = this.renderer.createElement('div');

        //this creates the second line
        const line2 = this.renderer.createElement('p');
        const text = this.renderer.createText('this is my second');
        this.renderer.appendChild(line2, text);

        const el = this.elementRef.nativeElement; //this is the element to wrap
        const parent = el.parentNode; //this is the parent containing el
        this.renderer.insertBefore(parent, div, el); //here we place div before el

        this.renderer.appendChild(div, el); //here we place el in div
        this.renderer.appendChild(div, line2); //here we append the second line in div, after el
    }
}
like image 167
Friso Avatar answered Sep 20 '22 16:09

Friso


the templateRef has property called "elementRef" you can throw it access the native dom like this:

this.templateRef.elementRef.nativeElement

So you can get the access to your element like above and use the built in Renderer class providing by angular.

check the below link please

https://angular.io/api/core/Renderer2

like image 35
Nour Avatar answered Sep 19 '22 16:09

Nour