是否可以将数据从一个指令传递到另一个指令?

时间:2017-04-14 07:07:07

标签: angular angular2-directives

我创建了两个指令。一个是处理Modal Popup的事件,另一个是处理自定义工具提示事件。现在我需要做的就是将数据从Modal指令传递给工具提示指令。我试过谷歌,但没有任何有用的东西。那么我们是否可以通过任何方式将值从一个指令传递到另一个指令?

工具提示指令如下:

import { Directive, ElementRef, Input, HostListener, Renderer, ViewChild } from '@angular/core';
import { ReportModel } from '../../models/ReportModel';
//import {FormFieldModel } from '../../models/FormFieldModel';
import { FormFieldModel } from '../../models/FrameworkElementFormFieldModel';

 @Directive( 
 {
    selector: '[Tooltip]'
 }
)

export class TooltipDirective {

constructor(public el: ElementRef, public renderer: Renderer) { }
tooltipTitle: any = '';
tooltipText: any = '';
tooltipImage: any = '';
isFormFieldModel: boolean = false;
@Input() dataContext: any = new ReportModel();
@Input() IsButtonPanel: boolean = false;



private mouseTop: number = 0;
private mouseLeft: number = 0;
tooltipTop: number = 0;
tooltipLeft: number = 0;
@HostListener('click') onclick() {
    this.hover(false);
}

@HostListener('mouseenter', ['$event']) onMouseEnter(event: MouseEvent) {debugger
    this.hover(false);
    if (this.mainDiv != null) {
        this.mainDiv.remove();
        this.ImgElement.remove();
    }
    this.mouseLeft = event.clientX;
    this.mouseTop = event.clientY;
    if (this.dataContext != null) {

        this.tooltipText = this.dataContext.Description;

        if (this.dataContext instanceof FormFieldModel) {
            this.isFormFieldModel = true;
        }

        if (this.isFormFieldModel) {
            if (!this.dataContext.IsShowToolTip) {
                return;
            }
            this.tooltipTitle = this.dataContext.PrettyName;
        }
        else {
            this.tooltipTitle = this.dataContext.Header;
            this.tooltipImage = this.dataContext.Icon;
        }

        if (this.tooltipTitle == '' || this.tooltipTitle == null || this.tooltipTitle == 'null') {
            this.tooltipTitle = "Header";
        }

        if (this.tooltipText == null || this.tooltipText == 'null') {
            this.tooltipText = "";
        }

        if (this.tooltipImage == '' || this.tooltipImage == 'null') {
            this.tooltipImage = "info.png";
        }

        this.hover(true);
    }
}
@HostListener('mouseleave') onMouseLeave() {
    this.hover(false);
}

@HostListener('focusin') onFocus() {

    if (this.mainDiv != null) {
        this.mainDiv.remove();
        this.ImgElement.remove();
    }

    this.mouseLeft = this.el.nativeElement.getBoundingClientRect().left;
    this.mouseTop = this.el.nativeElement.getBoundingClientRect().top;

    if (this.dataContext != null) {

        this.tooltipText = this.dataContext.Description;

        if (this.dataContext instanceof FormFieldModel) {
            this.isFormFieldModel = true;
        }

        if (this.isFormFieldModel) {
            if (!this.dataContext.IsShowToolTip) {
                return;
            }
            this.tooltipTitle = this.dataContext.PrettyName;
        }
        else {
            this.tooltipTitle = this.dataContext.Header;
            this.tooltipImage = this.dataContext.Icon;
        }

        if (this.tooltipTitle == '' || this.tooltipTitle == null || this.tooltipTitle == 'null') {
            this.tooltipTitle = "Header";
        }

        if (this.tooltipText == null || this.tooltipText == 'null') {
            this.tooltipText = "";
        }

        if (this.tooltipImage == '' || this.tooltipImage == 'null') {
            this.tooltipImage = "info.png";
        }

        this.hover(true);
    }
}

@HostListener('focusout') onFocusout(target) {
    this.hover(false);
}

//@HostListener('document:mousemove', ['$event'])
//onMouseMove(event: MouseEvent) {
//    this.mouseLeft = event.clientX;
//    this.mouseTop = event.clientY;
//}

mainDiv: any; ImgElement: any; InputElement: any; divElement: any; divElement1: any; divElement2: any;
hover(onMouseHover: boolean) {debugger

    if (onMouseHover && !this.IsButtonPanel) {debugger
        //Dynamically Create Img Element   

        //Delete existing Tooltip
        let tooltipItem = this.el.nativeElement.getElementsByClassName("tooltipMain")[0];
        if (tooltipItem != null) {
            tooltipItem.outerHTML = '';
        }
        else
        {
            tooltipItem = this.el.nativeElement.nextElementSibling;
            if (tooltipItem != null && tooltipItem.className.indexOf("tooltipMain") >= 0)
            {
                tooltipItem.outerHTML = '';
            }
        }

        this.ImgElement = this.renderer.createElement(this.el.nativeElement, "img");

        this.renderer.setElementAttribute(this.ImgElement, "src", "images/" + this.tooltipImage);

        //if (this.tooltipImage == '') {
        //    this.renderer.setElementAttribute(this.ImgElement, "src", "images/info.png");
        //}
        //else {
        //    this.renderer.setElementAttribute(this.ImgElement, "src", "images/" + this.tooltipImage);
        //}

        this.renderer.setElementStyle(this.ImgElement, "width", "40px");
        this.renderer.setElementStyle(this.ImgElement, "height", "40px");
        this.renderer.setElementStyle(this.ImgElement, "margin-right", "2px");
        this.renderer.setElementStyle(this.ImgElement, "float", "left");
        this.renderer.setElementStyle(this.ImgElement, "border", "1px solid #CCC");
        this.renderer.setElementStyle(this.ImgElement, "border-radius", "5px");
        this.renderer.setElementStyle(this.ImgElement, "padding", "5px");
        this.renderer.setElementStyle(this.ImgElement, "backgroundColor", "#f5f5f5");

        //tooltip text outer div

        this.divElement = this.renderer.createElement(this.el.nativeElement, "div");

        this.renderer.setElementStyle(this.divElement, "border", "1px solid #CCC");
        this.renderer.setElementStyle(this.divElement, "margin-left", "38px !important");
        this.renderer.setElementStyle(this.divElement, "color", "black");
        this.renderer.setElementStyle(this.divElement, "border-radius", "5px");
        this.renderer.setElementStyle(this.divElement, "padding", "5px");
        this.renderer.setElementStyle(this.divElement, "float", "left");
        this.renderer.setElementStyle(this.divElement, "backgroundColor", "#f5f5f5");
        this.renderer.setElementStyle(this.divElement, "text-align", "left !important");

        //tooltip text header div

        this.divElement1 = this.renderer.createElement(this.el.nativeElement, "div");

        this.renderer.setElementClass(this.divElement1, "header", true);
        this.renderer.createText(this.divElement1, this.tooltipTitle);


        //tooltip text description div

        this.divElement2 = this.renderer.createElement(this.el.nativeElement, "div");

        this.renderer.setElementClass(this.divElement2, "description", true);
        this.renderer.createText(this.divElement2, this.tooltipText);


        this.mainDiv = this.renderer.createElement(this.el.nativeElement, "div");

        this.renderer.setElementProperty(this.mainDiv, "disabled", true);
        this.renderer.setElementClass(this.mainDiv, "tooltipMain", true);


        let tooltipWidth = this.mainDiv.clientWidth + 10;
        let tooltipHeight = this.mainDiv.clientHeight + 10;

        let windowWidth = window.innerWidth;
        let windowHeight = window.innerHeight;

        if ((windowWidth - this.mouseLeft) < tooltipWidth) {
            //this.tooltipLeft = windowWidth - (tooltipWidth);
            this.renderer.setElementStyle(this.mainDiv, "right", "0px");
        } else {
            //this.tooltipLeft = this.mouseLeft;
            this.renderer.setElementStyle(this.mainDiv, "left", this.mouseLeft + "px");
        }

        if ((windowHeight - this.mouseTop) < tooltipHeight) {
            this.tooltipTop = this.mouseTop - 20;
            this.renderer.setElementStyle(this.mainDiv, "bottom", "0px");
        } else {
            this.renderer.setElementStyle(this.mainDiv, "top", this.mouseTop  + 5 + "px");
        }

        this.mainDiv.appendChild(this.ImgElement);
        this.divElement.appendChild(this.divElement1);
        this.divElement.appendChild(this.divElement2);
        this.mainDiv.appendChild(this.divElement);
        //this.renderer.setElementStyle(this.mainDiv, "left", this.tooltipLeft + "px");
        //this.renderer.setElementStyle(this.mainDiv, "top", this.tooltipTop + "px");  
    }
    else {
        if (this.mainDiv != null) {
            this.mainDiv.remove();
            this.ImgElement.remove();
        }
    }
}
}

我的Popup Draggable指令如下:

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

 @Directive({
   selector: '[draggable-component]'
 })
export class DraggableDirective implements OnInit {
topStart: number = 0;
leftStart: number = 0;
_allowDrag: boolean = true;
valueTop: any = 0;
valueLeft: any = 0;
md: boolean;

constructor(public element: ElementRef) { }

ngOnInit() {
    if (this._allowDrag) {
        this.element.nativeElement.style.position = 'absolute';
    }
}

@HostListener('mousedown', ['$event'])
onMouseDown(event: MouseEvent) {
    if (event.button === 2)
        return; // prevents right click drag, remove his if you don't want it
    this.md = true;
    this.topStart = event.clientY - this.element.nativeElement.style.top.replace('px', '');
    this.leftStart = event.clientX - this.element.nativeElement.style.left.replace('px', '');
}

@HostListener('document:mouseup')
onMouseUp(event: MouseEvent) {
    this.md = false;
}

@HostListener('document:mousemove', ['$event'])
onMouseMove(event: MouseEvent) {
    if (this.md && this._allowDrag) {

        this.valueTop = this.element.nativeElement.style.top = (event.clientY - this.topStart) + 'px';
        console.log(this.valueTop);
        this.valueLeft = this.element.nativeElement.style.left = (event.clientX - this.leftStart) + 'px';
        console.log(this.valueLeft);
    }
}

@HostListener('touchstart', ['$event'])
onTouchStart(event: TouchEvent) {
    this.md = true;
    this.topStart = event.changedTouches[0].clientY - this.element.nativeElement.style.top.replace('px', '');
    this.leftStart = event.changedTouches[0].clientX - this.element.nativeElement.style.left.replace('px', '');
    event.stopPropagation();
}

@HostListener('document:touchend')
onTouchEnd() {
    this.md = false;
}

@HostListener('document:touchmove', ['$event'])
onTouchMove(event: TouchEvent) {
    if (this.md && this._allowDrag) {
        this.element.nativeElement.style.top = (event.changedTouches[0].clientY - this.topStart) + 'px';
        this.element.nativeElement.style.left = (event.changedTouches[0].clientX - this.leftStart) + 'px';
    }
    event.stopPropagation();
}
}

现在我需要将valueTopvalueLeft从Draggable指令传递给Tooltip。这就是我想要的。

1 个答案:

答案 0 :(得分:2)

由于您的指令无关,您需要创建一个将在您的指令中注入的服务,该服务将成为它们之间的通信通道:

@Injectable()
export class Myservice{
  private _foo=new BehaviorSubject<string>("foo");
  setFoo(foo:string){
    this._foo.next(foo);
  }
  foo = this._foo.asObservable()
}
@Directive({
   selector: '[draggable-component]'
 })
export class DraggableDirective{
  constructor(public element: ElementRef, private service: MyService) {
    this.service.setFoo("bar");
  }
}
@Directive( 
{
  selector: '[Tooltip]'
})
export class TooltipDirective {

  constructor(public el: ElementRef, public renderer: Renderer, private service:MyService) {}

  ngOnInit(){
    this.service.foo.subscribe(value=>console.log(value));
  }

}

请注意,我使用的是BehaviorSubject,因为您可能会遇到DraggableDirective在另一个订阅之前发出值,因此无法在正确的时间获得正确的值。但是您完全可以自由实施,如果您认为它更符合您的需求,您甚至可以使用不基于Observable / Subject的模式。