我的组件结构看起来大致如此。我的应用程序组件有一个导航栏和路由器插座。导航栏包含徽标,一些通用链接以及一些仅在用户登录和身份验证时显示的特定链接。路由器插座根据路由URL加载主组件或墙组件。主组件包含登录组件,其中包含常规用户标识,密码和提交按钮。在提交时,登录成功后,登录组件将发出一个事件。现在,我如何在home组件(父组件)中捕获该事件?
如果我直接在应用程序下使用主页选择器,我可以抓住该事件,将其冒泡到应用程序,然后使导航栏中的隐藏链接可见。
我不知道如何捕获home组件中登录组件发出的事件,因为它已加载到路由器输出中。
<!-- app.html -->
<div>
<nav>
<!-- Product logo -->
<!-- Some generic links -->
<!-- some hidden icons to be shown on authentication -->
</nav>
<router-outlet></router-outlet>
</div>
<!-- home.html -->
<div>
<login></login>
</div>
<!-- login.html -->
<div>
<!-- user name and password -->
<!-- submit button - the associated ts file raises an event on successful login -->
</div>
<!-- wall.html -->
<div>
<!-- Content to be displayed on authentication -->
</div>
&#13;
谢谢, 希尔帕
答案 0 :(得分:0)
我想出了这个问题,虽然我还没有解决方案。 原来在地图上调用的方法无法访问类级对象。如果我通过身份验证调用发出事件,它就可以正常工作。 我尝试将事件发射器对象传递给映射方法,但这也没有帮助。如何将对象传递给映射的方法范围?
我服务中的代码如下所示:
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);
return v.onTouchEvent(event);
}
答案 1 :(得分:0)
对不起延迟,我就是这样做的:
<强> auth.service.ts 强>
export class AuthService {
authChanged: EventEmitter<any> = new EventEmitter();
postLogin(f: ILoginForm) {
return this.http.post('/login', f)
.map(res => res.json())
.subscribe(data => this._checkLoginResponse(data));
}
/**
* Check Login Result
* @param data
*/
private _checkLoginResponse(data: any) {
// If Successful Login
if (data.data && data.meta && data.meta.token) {
// Set User & Token
localStorage.setItem('inctoken', data.meta.token);
localStorage.setItem('incuser', JSON.stringify(data.data));
// Emit Auth & User Events
this.authChanged.emit(this.getUser());
// Show OK Login Flash Message
this.flash.success('You have been logged in successfully.');
// Navigate Home
this.injector.get(Router).navigate(['/']);
}
}
/**
* Logout of Interface
* @returns boolean
*/
logout(withMsg = false): boolean {
// # Remove Token & User from LS
localStorage.removeItem('inctoken');
localStorage.removeItem('incuser');
// Emit Auth Events
this.authChanged.emit(false);
// Show Flash Message
if (withMsg)
this.flash.info('You have been logged out.', 'OK.');
// Redirect to Login Page
this.injector.get(Router).navigate(['/login']);
return true;
}
}
然后任何组件都可以注入 AuthService 并知道authedUser何时更改,注销等。以我的Navbar为例:
<强> navbar.component.ts 强>
export class NavbarComponent {
/**
* Authed User
*/
authedUser: IUser;
constructor(private authService: AuthService) {
this.authService.authChanged
.subscribe((user?: IUser) => {
// user will be false if logged out
// or user object if logged in.
this.authedUser = user;
});
}
}
然后在我的导航栏模板中,我可以选择根据身份验证状态显示内容:
<nav class="navbar">
<!-- Truncated -->
<ul class="menu-item"
*ngIf="authedUser">
<li><img [src]="authedUser.avatar"></li>
<!-- Whatever -->
</ul>
<ul class="menu-item"
*ngIf="!authedUser">
<li><a [routerLink]="['/login']">Login</a></li>
<!-- Whatever -->
</ul>
</nav>
显然,为简洁起见,很多这些类都被截断了。
如果您对如何在标题中发送令牌感到好奇,这里是我创建的HttpClient类的一个简单示例(为简洁而截断):
<强> http.service.ts 强>
export class HttpClient {
constructor(private http: Http) {
// ...
}
/**
* Get
* @param url
* @returns {Observable<any>}
*/
get(url): Observable<any> {
// Create New Headers
let headers = new Headers();
// Set Authorization Header
this._createAuthorizationHeader(headers);
// Create Observable to Return to Calling Service.
// We Dont Just Return the HTTP Observable Because
// We Need to Subscribe Here to Catch The Errors That
// May Be Thrown, Otherwise, Every Service Would Need
// To Call The Handle Errors Method
return Observable.create((observer) => {
// Fire Http GET Request, Subscribe & Catch Errors
return this.http.get(this.baseUrl + url, {
headers: headers
}).subscribe(
data => observer.next(data), // Emit Data Returned
err => this.handleError(err), // Catch Errors
() => observer.complete() // Emit Completed
);
});
}
/**
* Create Authorization Header
* @param {Headers} headers
*/
private _createAuthorizationHeader(headers: Headers) {
// If We Have A Token, Append It. The
// API Server Will Determine Its Validity
if (localStorage.getItem('inctoken')) {
headers.append('Authorization', 'Bearer: ' + localStorage.getItem('inctoken'));
}
}
}
然后在我的其他组件中,我可以注入我的HttpClient类并使用它来自动将标记放在标题中,I.E。
<强> some.component.ts 强>
export class SomeComponent {
constructor(private http: HttpClient) {
// ...
}
private _getSomeData() {
return this.get('/someurl')
.map(res => res.json();
}
}
答案 2 :(得分:0)
了解这个解决方案 - &gt; http://plnkr.co/edit/KfcdDi?p=info
//alert.service.ts
import { Injectable } from '@angular/core';
import { Router, NavigationStart } from '@angular/router';
import { Observable } from 'rxjs';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class AlertService {
private subject = new Subject<any>();
private keepAfterNavigationChange = false;
constructor(private router: Router) {
// clear alert message on route change
router.events.subscribe(event => {
if (event instanceof NavigationStart) {
if (this.keepAfterNavigationChange) {
// only keep for a single location change
this.keepAfterNavigationChange = false;
} else {
// clear alert
this.subject.next();
}
}
});
}
success(message: string, keepAfterNavigationChange = false) {
this.keepAfterNavigationChange = keepAfterNavigationChange;
this.subject.next({ type: 'success', text: message });
}
error(message: string, keepAfterNavigationChange = false) {
this.keepAfterNavigationChange = keepAfterNavigationChange;
this.subject.next({ type: 'error', text: message });
}
getMessage(): Observable<any> {
return this.subject.asObservable();
}
}
&#13;
//login.component
private loggedIn(user1: user) {
this.currentUser = user1;
this._alertService.alert("login", true);
}
&#13;
//app.component
ngOnInit(): void {
this.authenticated = this._authService.isLoggedIn();
this._alertService.getMessage().subscribe(data => this.setData(data));
}
private setData(data: any) {
if (!this.authenticated) {
if (data && (data.type === 'login') && data.success === true) {
this.authenticated = true;
}
else {
this.authenticated = false;
}
}
}
&#13;
<!-- app.html -->
<nav class="navbar navbar-color">
<div class="container-fluid" id="nav_center">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed nav-expand-button"
data-toggle="collapse" data-target="#navbar-collapse1" aria-expanded="false"
*ngIf="authenticated">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<button type="button" class="nav-features nav-expand-button"
(click)="isCollapsed = !isCollapsed" *ngIf="authenticated">
<span class="sr-only">Navigate features</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Outili</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="navbar-collapse1" *ngIf="authenticated">
<!--*ngIf="showNotification">-->
<ul class="nav navbar-nav navbar-right">
<li class="navbar-icons">
<a href="#" class="navbar-a">
<span class="glyphicon glyphicon-inbox navbar-icons"></span>
</a>
</li>
<li class="dropdown navbar-icons">
<a href="#" class="dropdown-toggle navbar-a" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-user navbar-icons"></span>
<span class="caret navbar-icons"></span>
</a>
<ul class="dropdown-menu">
<li><a href="#">Profile</a></li>
<li><a href="#">Settings</a></li>
<li role="separator" class="divider"></li>
<li (click)="logout()"><button type="button" class="btn">Logout</button></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
&#13;
这里的提醒服务完全符合我的要求。