单击时来自组件的 Angular2 触发指令
Angular2 trigger directive from component on click
我有一个指令可以将框阴影添加到页面上的任何悬停元素,但我需要它在单击按钮后开始应用阴影。我遇到的问题是它只适用于单个元素。
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;
}
}
}
如有任何帮助,我们将不胜感激。
问题是您使用 @ViewChild
而不是 @ViewChildren
。使用 ViewChild 时,它仅处理可以在模板中找到的 HighlightDirective
的第一个实例。
除了你在这里做出的其他一些模糊的选择之外,我会说你必须改成这样:
@ViewChildren(HighlightDirective) highlightDirs: QueryList<HighlightDirective>;
然后您必须将 giveFeedback 函数更改为:
giveFeedback(): void {
this.highlightDirs.forEach((highlightDir: HightlightDirective) => {
highlightDir.startFeedback();
});
}
您的任何代码中都不需要 changeDetectionRef。仅当您将 changeDetection: ChangeDetectionStrategy.OnPush
放在 component/directive
上时才需要这样做
我有一个指令可以将框阴影添加到页面上的任何悬停元素,但我需要它在单击按钮后开始应用阴影。我遇到的问题是它只适用于单个元素。
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;
}
}
}
如有任何帮助,我们将不胜感激。
问题是您使用 @ViewChild
而不是 @ViewChildren
。使用 ViewChild 时,它仅处理可以在模板中找到的 HighlightDirective
的第一个实例。
除了你在这里做出的其他一些模糊的选择之外,我会说你必须改成这样:
@ViewChildren(HighlightDirective) highlightDirs: QueryList<HighlightDirective>;
然后您必须将 giveFeedback 函数更改为:
giveFeedback(): void {
this.highlightDirs.forEach((highlightDir: HightlightDirective) => {
highlightDir.startFeedback();
});
}
您的任何代码中都不需要 changeDetectionRef。仅当您将 changeDetection: ChangeDetectionStrategy.OnPush
放在 component/directive