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:
@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:
@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
. With ViewChild it only addresses the first instance of HighlightDirective
it can find in the template.
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(): void {
this.highlightDirs.forEach((highlightDir: HightlightDirective) => {
highlightDir.startFeedback();
});
}
There is no need for the changeDetectionRef inside any of your code. This is only necessary if you put changeDetection: ChangeDetectionStrategy.OnPush
on your component/directive
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.