web-dev-qa-db-fra.com

Construire une directive wrapper (envelopper du contenu / composant) dans angular2

Je suis de nouvelles directives de construction avec Angular2. Ce que je veux, c'est créer une directive popup qui encapsulera le contenu avec certaines classes CSS.

Conten

Le contenu peut être du texte pur et des en-têtes comme:

<div class="data">
    <h2>Header</h2>
    Content to be placed here.
</div>

Ensuite, je veux donner à cet attribut une directive comme: popup

<div class="data" popup>
    <h2>Header</h2>
    Content to be placed here.
</div>

Ce que la directive devrait faire, c'est d'envelopper le div à l'intérieur, disons:

<div class="some class">
    <div class="some other class">
        <div class="data">
            <h2>Header</h2>
            Content to be placed here.
        </div>
    </div>
</div>

Le cas que j'ai décrit jusqu'à présent, est-ce un attribut ou des directives structurelles.

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: `[popup]`
})

export class PopupDirective {


}
13
Mikkel

L'autre réponse est liée mais différente.

Pour quelque chose de plus proche, voir ceci: Comment envelopper conditionnellement une div autour de ng-content - ma solution est pour Angular 4, mais la question liée a quelques indices sur la façon dont cela pourrait être faisable pour Angular 2.

J'ai résolu ce problème avec un composant et une directive combinés. Mon composant ressemble à ceci:

import { Component, Input, TemplateRef } from '@angular/core';

@Component({
  selector: 'my-wrapper-container',
  template: `
<div class="whatever">
  <ng-container *ngTemplateOutlet="template"></ng-container>
</div>
`
})
export class WrapperContainerComponent {
  @Input() template: TemplateRef<any>;
}

et ma directive comme celle-ci:

import { Directive, OnInit, Input, TemplateRef, ComponentRef, ComponentFactoryResolver, ViewContainerRef } from '@angular/core';

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

  private wrapperContainer: ComponentRef<WrapperContainerComponent>;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainerRef: ViewContainerRef,
    private componentFactoryResolver: ComponentFactoryResolver
  ) { }

  ngOnInit() {
    const containerFactory = this.componentFactoryResolver.resolveComponentFactory(WrapperContainerComponent);
    this.wrapperContainer = this.viewContainerRef.createComponent(containerFactory);
    this.wrapperContainer.instance.template = this.templateRef;
  }
}

Pour pouvoir charger votre composant dynamiquement, vous devez lister votre composant en tant que entryComponent à l'intérieur de votre module:

@NgModule({
  imports: [CommonModule],
  declarations: [WrapperContainerComponent, WrapperDirective],
  exports: [WrapperContainerComponent, WrapperDirective],
  entryComponents: [WrapperContainerComponent]
})
export class MyModule{}

donc le HTML à la fin est:

<some_tag *myWrapperDirective />

Ce qui se traduit par:

<my-wrapper-container>
  <div class="whatever">
    <some_tag />
  </div>
</my-wrapper-container>
12
Dan Field

Vous pouvez y parvenir avec un sélecteur d'attribut de composant et Angular 2 Content Projection <ng-content>

@Component({
  selector: 'my-app',
  template: `
    <div class="app"> 
        <div class="data" myWrapper>
            <h2>Header</h2>
            Content to be placed here.
        </div> 
    </div>
  `
})
export class AppComponent {}


@Component({
  selector: '[myWrapper]',
  template: `
    <div class="my-class">
      <div class="my-sub-class">
          <ng-content></ng-content>
      </div>
    </div>
  `
})
export class MyComponent {

}
8
Kld