[英]Angular2 trigger directive from component on click
I have a directive that adds box shadow to any hovered element on page but I need it to start applying the shadow after a click of a button. 我有一个指令,可以将框阴影添加到页面上的任何悬停元素上,但是我需要它才能在单击按钮后开始应用阴影。 The problem I have, is it only applies to a single element. 我的问题是,它仅适用于单个元素。
Here is an image of the box shadow 这是盒子阴影的图像
It applies only to the header after I hover it. 将鼠标悬停后,它仅适用于标题。 I need it to apply to any hovered element. 我需要将其应用于任何悬停的元素。
My app.component: 我的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;
}
}
My highlight.directive: 我的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;
}
}
}
Any help would be greatly appreciated. 任何帮助将不胜感激。
The problem is that you use @ViewChild
instead of @ViewChildren
. 问题是您使用@ViewChild
而不是@ViewChildren
。 With ViewChild it only addresses the first instance of HighlightDirective
it can find in the template. 使用ViewChild时,它仅处理可以在模板中找到的HighlightDirective
的第一个实例。
Besides some other obscure choices you made here, I would say you have to change to something like this: 除了您在此处做出的其他一些晦涩的选择外,我还想说您必须更改为以下内容:
@ViewChildren(HighlightDirective) highlightDirs: QueryList<HighlightDirective>;
You then have to change your giveFeedback function to this: 然后,您必须将GiveFeedback函数更改为此:
giveFeedback(): void {
this.highlightDirs.forEach((highlightDir: HightlightDirective) => {
highlightDir.startFeedback();
});
}
There is no need for the changeDetectionRef inside any of your code. 您的任何代码内都不需要changeDetectionRef。 This is only necessary if you put changeDetection: ChangeDetectionStrategy.OnPush
on your component/directive 仅当在组件/指令上放置changeDetection: ChangeDetectionStrategy.OnPush
,才有必要
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.