Building a wrapper directive (wrap some content / component) in angular2

前端 未结 2 1903
轮回少年
轮回少年 2020-12-31 06:30

I\'m pretty new building directives with Angular2. What I want is to create a popup directive that will wrap the content with some css classes.

Content

相关标签:
2条回答
  • 2020-12-31 06:55

    The other answer is related but different.

    For something closer, see this: How to conditionally wrap a div around ng-content - my solution is for Angular 4, but the linked question has some hints about how this might be doable for Angular 2.

    I solved this problem with a component and a directive combined. My component looks something like this:

    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>;
    }
    

    and my directive like this:

    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;
      }
    }
    

    To be able to load your component dynamically, you need to list your component as an entryComponent inside your module :

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

    so the HTML in the end is:

    <some_tag *myWrapperDirective />
    

    Which renders as:

    <my-wrapper-container>
      <div class="whatever">
        <some_tag />
      </div>
    </my-wrapper-container>
    
    0 讨论(0)
  • 2020-12-31 07:02

    You can achieve this with a component attribute selector and 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 {
    
    }
    
    0 讨论(0)
提交回复
热议问题