【发布时间】:2016-05-02 16:39:28
【问题描述】:
简介
嗨,我对 Angular2 和 Typescript 有点陌生(而且我也是 StackOverflow.com 的新手),我想知道您是否可以帮助我解决以下问题: 我在按钮单击时使用 ngOnChanges() 在按钮上制作了自己的折叠动画。现在,我的目标是当用户点击页面上的任何地方(在我显示的菜单之外或管理菜单的按钮之外的其他地方)时,菜单会折叠以隐藏。
为此,当我的 header.component.ts 中的折叠属性使用 clickOutsideEvent() 更新时,我希望我的 collapse.animation.ts 使用 ngDoCheck() 进行检测。
我一直在尝试使(blur)="onBlur()" 或(blur)="expression" 等事件工作,但不幸的是,由于关注单个html 元素,它无法正常工作。或者我没有成功地做到这一点......
这是我得到的例外: angular2.dev.js:23730 例外:在 [isCollapsed in HeaderComponent@16:59] 中尝试区分“true”时出错
抱歉,如果帖子太长或不够清楚,任何帮助将不胜感激。
我正在处理的代码
collapse.animation.ts:我在这个文件中管理折叠动画,并尝试检测折叠变化并相应地隐藏/显示。
import {Directive, DoCheck, KeyValueDiffers , OnChanges, ElementRef, Input } from 'angular2/core';
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
import {CssAnimationBuilder} from 'angular2/src/animate/css_animation_builder';
@Directive({
selector: '[collapse]',
host: {
'[attr.aria-expanded]': '!collapse',
'[attr.aria-hidden]': 'collapse'
}
})
export class Collapse implements OnChanges, DoCheck {
@Input() duration: number = 200; // Vitesse de l'animation en ms. (750 = 0.75 sec)
@Input() collapse: any; // Booléen définissant l'état collapse ou non
private _animation: CssAnimationBuilder; // Animation CSS
differ: any; // Tracker de propriété / attribut.
constructor(private _animationBuilder: AnimationBuilder, private _element: ElementRef, private differs: KeyValueDiffers) {
// Initialisation de l'animation css.
this._animation = _animationBuilder.css();
// Initialisation du tracker
this.differ = differs.find({}).create(null);
}
// trying to make this work...
ngDoCheck() {
var changes = this.differ.diff(this.collapse);
if (changes) {
changes.forEachChangedItem((elt) => {
if (elt.key === 'isCollapsed') {
this.show();
}
else {
this.hide();
}
});
}
}
// Manage property collapse
// This works when I click on my button
ngOnChanges(changes) {
if (changes.collapse) {
if (this.collapse) {
this.hide();
} else {
this.show();
}
}
}
header.component.ts :这是包含我的菜单的标题组件
import { Component, Input } from 'angular2/core';
import { RouteConfig, RouterOutlet, ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from "angular2/router";
import { Collapse } from './../../css/animations/collapse.animation';
import { ClickOutside } from './../directives/clickOutside.directive';
@Component({
selector: 'headerComponent',
templateUrl: 'app/master/header.component.html',
styleUrls: ['app/master/header.component.css', 'app/master/menuNavigation.component.css', 'css/animations/collapse.animation.css'],
directives: [
ROUTER_DIRECTIVES,
Collapse,
ClickOutside
],
providers: [
ROUTER_PROVIDERS
],
})
export class HeaderComponent {
@Input() collapse: boolean = false;
private headerMenuClass: string = "header_menu";
// clickOutside linked method
handleClickOutside(className) {
// I'm detecting the "click" on my button linked to my menu with it's class "header_menu". No need to collapse the menu when I click on my button.
let FirstClassName: string = className.split(" ")[0];
if (FirstClassName != this.headerMenuClass) {
console.log(this.collapse);
// Trying to make my collapse.animation.ts detect this !!
this.collapse = !this.collapse;
}
}
}
header.component.html : 我的组件的 HTML 模板
<div id="top_bar" class="top_bar">
<!-- This is the button that shows the menu -->
<button type="button" class="header_menu nav_icon root_navitem" id="btn_menu_switch" (click)="isCollapsed = !isCollapsed">
<img class="header_menu" src="css/App_Themes/VAL/48x48/m_bars.png" alt="" />
</button>
<button type="button" class="nav_icon" id="btn_home" [routerLink]="['Accueil']">
<img src="css/App_Themes/VAL/48x48/m_home.png" alt="" />
</button>
</div>
<!-- This is the menu I'm trying to collapse at will -->
<div id="left_bar" tabindex="-1" class="left_bar collapse" [collapse]="isCollapsed"
(clickOutside)="handleClickOutside( $event.target.className )">
<div id="left_bar_menu" class="left_bar_menu">
<button type="button" class="left_bar_icon" id="btn_left_histo">
<img src="css/App_Themes/VAL/48x48/m_history.png" alt="" />
</button>
<hr class="sep" />
<button type="button" class="left_bar_icon" id="btn_left_board" [routerLink]="['Dashboard']">
<img src="css/App_Themes/VAL/48x48/m_board.png" alt="" />
</button>
<hr class="sep" />
</div>
</div>
clickOutside.directive.ts :该文件允许我检测何时单击组件外部并获取一些信息。我认为这不是解决我的问题的一种干净的方法,但我稍后会解决这个问题。
import {Directive, EventEmitter, Input, Output } from 'angular2/core';
// Variable globale à la classe
var localEvent: any = null;
@Directive({
selector: '[clickOutside]',
host: {
"(click)": "trackEvent( $event )",
"(document: click)": "compareEvent( $event )"
}
})
export class ClickOutside {
@Output() clickOutside;
constructor() {
this.clickOutside = new EventEmitter();
}
// If the event at the document root is the same reference as the
// event at the target, it means that the event originated from
// within the target and bubbled all the way to the root. As such,
// if the event at the document root does NOT MATCH the last known
// event at the target, the event must have originated from
// outside of the target.
compareEvent(event) {
if (event !== localEvent) {
this.clickOutside.emit(event);
}
localEvent = null;
}
// I track the click event on the bound target.
trackEvent(event) {
// When the user clicks inside the bound target, we need to start
// tracking the event as it bubbles up the DOM tree. This way,
// when a click event hits the document root, we can determine if
// the event originated from within the target.
localEvent = event;
}
}
【问题讨论】:
标签: typescript angular