【问题标题】:Angular 4 - Share data with directive attributeAngular 4 - 使用指令属性共享数据
【发布时间】:2026-01-26 05:40:01
【问题描述】:

我正在尝试制作一个工具提示指令/组件,但是我尝试了一切,我无法在我的工具提示中使用插值来使用重复中的变量。 我的主页标记如下所示:

<md-card class='col-md-3 image-gallery' *ngFor="let advertiser of AdvertiserService.advertisers;let i = index" [@fadeIn]>
    <md-card-content 
    [tooltip]="template" [advertiser]="advertiser">
        //some other markup
    </md-card-content>
</md-card>

我的工具提示指令如下所示:

import { ComponentFactoryResolver, ComponentRef, Directive, ElementRef, 
HostListener, Injector, Output, Input, ReflectiveInjector, Renderer2,     
TemplateRef, Type, ViewContainerRef, ViewRef } from '@angular/core';
import { TooltipComponent } from './tooltip.component';
import { AdvertiserClass } from './../advertiser/advertiser-class';

@Directive({
    selector: '[tooltip]'
})
export class TooltipDirective {
    // We can pass string, template or component
    @Input('tooltip') content: string | TemplateRef<any> | Type<any>;
    @Input('advertiser') advertiser: AdvertiserClass;
    private componentRef: ComponentRef<TooltipComponent>;

    constructor(private element: ElementRef,
        private renderer: Renderer2,
        private injector: Injector,
        private resolver: ComponentFactoryResolver,
        private vcr: ViewContainerRef) {
    }

    @HostListener('mouseenter')
    mouseenter() {
        //console.log(this.advertiser);
        if (this.componentRef) return;
        const factory = 
this.resolver.resolveComponentFactory(TooltipComponent);
        const injector = ReflectiveInjector.resolveAndCreate([
            {
                provide: 'tooltipConfig',
                useValue: {
                    host: this.element.nativeElement
                }
            }
        ]);
        this.componentRef = this.vcr.createComponent(factory, 0, injector, 
this.generateNgContent());
    }

    generateNgContent() {
        if (typeof this.content === 'string') {
            const element = this.renderer.createText(this.content);
            return [[element]];
        }

        if (this.content instanceof TemplateRef) {
            const viewRef = this.content.createEmbeddedView({});
            return [viewRef.rootNodes];
        }

        // Else it's a component
        const factory = this.resolver.resolveComponentFactory(this.content);
        const viewRef = factory.create(this.injector);
        return [[viewRef.location.nativeElement]];
    }

    @HostListener('mouseout')
    mouseout() {
        this.destroy();
    }

    destroy() {
        this.componentRef && this.componentRef.destroy();
        this.componentRef = null;
    }

    ngOnDestroy() {
        this.destroy();
    }
}

我的工具提示组件如下所示:

import { Component, Directive, ElementRef, Inject, OnInit, ViewChild, Input         
} from '@angular/core';
import { AdvertiserClass } from './../advertiser/advertiser-class';

@Directive({
    selector: '.tooltip-container'
})
export class TooltipContainerDirective {
}

@Component({
    template: `
    <div class="tooltip-container" [ngStyle]="{top: top}">
        {{advertiser | json}}
    </div>
  `,
    styles: [
        `
      .tooltip-container {
        background-color: black;
        color: #fff;
        display: inline-block;
        padding: 0.5em;
        position: absolute;
      }
    `
    ]
})
export class TooltipComponent implements OnInit {
    @Input('advertiser') advertiser: AdvertiserClass;
    top: string;
    @ViewChild(TooltipContainerDirective, { read: ElementRef }) private 
tooltipContainer;

    constructor( @Inject('tooltipConfig') private config) {
    }

    ngOnInit() {
        const { top } = this.config.host.getBoundingClientRect();
        const { height } = 
this.tooltipContainer.nativeElement.getBoundingClientRect();
        this.top = `${top - height}px`;
    }
}

我如何在有效的代码中使用 {{advertisers}} interpotalion? 我已经尝试了这个的每一个变体,但我无法将重复的数据传递给工具提示组件模板。

【问题讨论】:

  • 嗯只有两件事。 .one 为什么您将工具提示称为您的指令并且还称为输入属性? ..然后..你在@input更改事件中尝试过console.log吗?
  • 是的,我知道不应该两者都需要,我只是试了一下,也许它会起作用。但是,是的,那个输入控制台记录了正确的数据!
  • 所以如果它帮助你评价我的评论;-)

标签: javascript angular components interpolation directive


【解决方案1】:

按原样,您的工具提示指令知道广告商,但用于生成视图的工具提示组件却不知道。您需要做的是在指令创建广告商时将其从指令传递给 TooltipComponent。我可能会在您正在创建并注入 TooltipComponent 的“tooltipconfig”对象中执行此操作。

    const injector = ReflectiveInjector.resolveAndCreate([
        {
            provide: 'tooltipConfig',
            useValue: {
                host: this.element.nativeElement,
                advertiser: this.advertiser
            }
        }
    ]);

然后在 ToolTipComponent 中,您可以将该值从构造函数中的配置对象中提取出来,以使其可用于模板

constructor( @Inject('tooltipConfig') private config) {
    this.advertiser = config.advertiser;
}

或者您可以在构造函数中公开您的配置对象并绑定到模板中的{{config.advertiser}}

【讨论】: