单击时来自组件的Angular2触发指令
Posted
技术标签:
【中文标题】单击时来自组件的Angular2触发指令【英文标题】:Angular2 trigger directive from component on click 【发布时间】:2017-05-11 21:41:52 【问题描述】:我有一个指令可以为页面上的任何悬停元素添加框阴影,但我需要它在单击按钮后开始应用阴影。我遇到的问题是它只适用于单个元素。
Here is an image of the box shadow
它只适用于我悬停后的标题。我需要将它应用于任何悬停的元素。
我的 app.component:
@Component(
moduleId: module.id,
selector: 'my-app',
template: `
<h1 myHighlight="orange">title clickedElement | async</h1>
<nav>
<a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a>
<a routerLink="/secret-heroes" *ngIf="authService.loggedIn()" routerLinkActive="active">Secret Heroes</a>
<a (click)=authService.login() *ngIf="!authService.loggedIn()">Log In</a>
<a (click)=authService.logout() *ngIf="authService.loggedIn()">Log Out</a>
<a (click)=giveFeedback()>Give Feedback</a>
<a (click)="listening = !listening" >Give Feedback2</a>
<button id="modalButton" type="button" (click)="feedbackModal.show()">test</button>
<my-feedback-modal>
</my-feedback-modal>
</nav>
<router-outlet></router-outlet>
`,
styleUrls: ['app.component.css']
)
export class AppComponent
//@Input() highlight: boolean = false;
title = 'Tour of Heroes';
@ViewChild(ModalComponent) modal: ModalComponent;
@ViewChild(HighlightDirective) highlightDir: HighlightDirective;
@ViewChild(FeedbackModalComponent) feedbackModal: FeedbackModalComponent;
constructor(private authService: AuthService, private el: ElementRef, private cdr: ChangeDetectorRef)
this.cdr = cdr;
clickedElement:BehaviorSubject<ElementRef> = new BehaviorSubject(this.el);
ngAfterViewInit()
//this.clickedElement.next(this.highlightDir.getElement().nativeElement.nodeName);
ngDoCheck()
giveFeedback(): void
this.highlightDir.startFeedback();
this.cdr.detectChanges();
//this.highlight = true;
我的 highlight.directive:
@Directive(
selector: 'a, abbr, address, article, body, br, button, div, h1, h2, h3, h4, h5, h6, header, hr, i, iframe, img, ' +
'input, label, li, link, meta, nav, object, ol, option, output, p, param, pre, section, select, small, source, span,' +
'summary, table, tbody, td, textarea, tfoot, th, thead, time, title, tr, u, ul, video'
)
export class HighlightDirective
elementsArray: string[];
listening: boolean = false;
constructor(private el: ElementRef, private cdr: ChangeDetectorRef)
this.cdr = cdr;
this.elementsArray = ["a", 'abbr', 'address', 'article', 'body', 'br', 'button', 'div', 'h1', 'h2', 'h3', 'h4', 'h5'
, 'h6', 'header', 'hr', 'i', 'iframe', 'img', 'input', 'label', 'li', 'link', 'meta', 'nav', 'object', 'ol', 'option'
, 'output', 'p', 'param', 'pre', 'section', 'select', 'small', 'source', 'span', 'summary', 'table', 'tbody', 'td'
, 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'u', 'ul', 'video'];
//@Input() defaultColor: string;
//@Input() listening: boolean = false;
//check: boolean = false;
public getElement(): ElementRef
return this.el;
public startFeedback(): boolean
this.listening = true;
this.cdr.detectChanges();
return true;
@HostListener('click') onClick()
if(this.listening)
document.getElementById('modalButton').click();
this.listening = false;
@HostListener('mouseenter') onMouseEnter()
if(this.listening)
this.el.nativeElement.style.boxShadow = '0 0 0 5px yellow';
this.el.nativeElement.parentNode.style.boxShadow = null;
@HostListener('mouseleave') onMouseLeave()
if(this.listening)
this.el.nativeElement.style.boxShadow = null;
this.el.nativeElement.parentNode.style.boxShadow = '0 0 0 5px yellow';
let check = false;
for (let entry of this.elementsArray)
if (this.el.nativeElement.parentNode.nodeName == entry.toUpperCase())
check = true;
break;
if (!check)
this.el.nativeElement.parentNode.style.boxShadow = null;
任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:问题是您使用@ViewChild
而不是@ViewChildren
。对于 ViewChild,它只处理可以在模板中找到的 HighlightDirective
的第一个实例。
除了您在这里做出的其他一些晦涩的选择之外,我想说您必须更改为这样的内容:
@ViewChildren(HighlightDirective) highlightDirs: QueryList<HighlightDirective>;
然后您必须将 giveFeedback 函数更改为:
giveFeedback(): void
this.highlightDirs.forEach((highlightDir: HightlightDirective) =>
highlightDir.startFeedback();
);
在您的任何代码中都不需要 changeDetectionRef。仅当您将 changeDetection: ChangeDetectionStrategy.OnPush
放在组件/指令上时才需要这样做
【讨论】:
谢谢,其他元素现在已经应用了阴影,但不幸的是它有问题,并且某些阴影在悬停后会卡住。我猜我的 Host 监听器的设置不是最好的。 我刚刚意识到它并没有完全解决我的问题,因为它不适用于我的nativeElement
。 document.getElementById
,以及直接的组件间通信,这些在 angular2 中都是不受欢迎的,并且总是会导致意大利面条代码......就像现在一样。我建议您多看一下 angular.io 网站上显示的示例。数据下降,事件上升以上是关于单击时来自组件的Angular2触发指令的主要内容,如果未能解决你的问题,请参考以下文章