【问题标题】:Angular2 : How to communicate from parent component to child?Angular2:如何从父组件到子组件通信?
【发布时间】:2016-11-10 09:03:11
【问题描述】:

我在标签之间加载了一些 div。如下所示。

这是我的 index.html

<html>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>

<!-- 3. Display the application -->

<body>
<my-app>Loading...</my-app>
</body>
</html>

app.module.ts

@NgModule({
imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule
],
declarations: [
    AppComponent,
    LoginComponent,
    HomeComponent,
    NewsfeedComponent,
    TopBarComponent,
    SideMenuComponent
],
providers : [
    AuthGaurd
],
bootstrap: [
    AppComponent
] })
export class AppComponent {}

home.component.ts

@Component({
    selector: 'home',
    moduleId: module.id,
    templateUrl: 'home.component.html',
    providers : [
        LoginService
    ]
})

export class HomeComponent implements OnInit{
isLoggedin : boolean;
constructor (private loginService : LoginService) { }
ngOnInit(): void {
    this.loginService.getLogged().subscribe((isLoggedIn: boolean) => {
        this.isLoggedin = isLoggedIn;
    }); }
}

home.component.html

<side-menu *ngIf='isLoggedin'></side-menu>
<top-bar *ngIf='isLoggedin'></top-bar>
<router-outlet></router-outlet>

auth.gaurd.ts

@Injectable()
export class AuthGaurd implements CanActivate{
    constructor(private router : Router) {
    }
    canActivate(){
        if (localStorage.getItem('isLogin')){
            return true;
        }
        this.router.navigate(['/login'])
        return false;
    }
}

login.service.ts

@Injectable()
export class LoginService {
    private subject: Subject<boolean> = new Subject<boolean>();
    constructor(private router : Router) {
    }
    login(){
        this.setLogged(true);
        localStorage.setItem("isLogin","true");
        this.router.navigate(['/news-feed']);
    }
    logout(){
        this.setLogged(false);
        localStorage.removeItem("isLogin");
        this.router.navigate(['/login']);
    }
    getLogged(): Observable<boolean> {
        return this.subject.asObservable();
    }
    setLogged(val : boolean): void {
        this.subject.next(val);
    }
}

login.component.ts

@Component({
    selector: 'login',
    moduleId: module.id,
    templateUrl: 'login.component.html'
})

export class LoginComponent {
    constructor (private loginService : LoginService) {
    }

    login(){
        this.loginService.login()
    }
}

login.component.html

<input type="number” #mobileNumber />
<input type="password" #password />
<input type="button" (click)="login()">

newsfeed.component.ts

@Component({
    selector: 'newsfeed',
    moduleId: module.id,
    templateUrl: 'newsfeed.component.html',
})

export class NewsfeedComponent {

}

newsfeed.component.html

一些 html 文本....!!!!

app-routing.module.ts

@NgModule({
imports: [
    RouterModule.forRoot([
        {
            path : 'login',
            component : LoginComponent
        },
        {
            path : 'news-feed',
            component : NewsfeedComponent,
            canActivate : [AuthGaurd]
        },
        {
            path : '',
            redirectTo : '/news-feed',
            pathMatch : 'full'
        }
        {
            path: '**',
            component: LoginComponent
        }
    ])
],
exports: [
    RouterModule
]
})
export class AppRoutingModule {}

实际上,当我使用点击时它工作正常。喜欢它的启动比点击登录按钮更完美,它转发到新闻源并显示预期的结果。但是当我从浏览器 url 开始时,它不会从 home.html 加载侧边栏和顶部栏组件

【问题讨论】:

  • 需要使用共享服务与路由器angular.io/docs/ts/latest/cookbook/…添加的组件通信
  • 我试过这个。它对点击工作正常,但在我浏览浏览器 url 时不起作用。
  • 您需要提供更多信息。我不知道您要完成什么或尝试了什么或问题可能出在哪里。
  • 不,请提供适当的信息,这样很容易提供解决方案。
  • 是的,我正在编辑我的问题

标签: angularjs angular routing angular-ui-router


【解决方案1】:

我遇到了这个问题。这是我解决这种情况的方法;

  • 创建具有可观察字段的共享服务,如官方 Angular 文档中所述
  • 在您的导航栏组件中,订阅来自共享服务的值以显示导航栏
  • 在登录和注销页面中,更新值。由于您已经订阅了该值,因此订阅者会自行处理这种情况
  • 创建身份验证服务。添加一个类似这样的方法来询问你的后端,请求是否经过身份验证;
//method parameters depend on what you want
isAuthorized(url: string, errorCallback: (any) => void) {
        let body = JSON.stringify(url)
        return this.http.post('account/isauthorized', body)
            .map((response: Response) => {
                //update value to display navigation bar if user is authenticated
                yourSharedService.observableField.next(true);
                return true;
            })
            .catch((response: Response) => {
                errorCallback(response.status);
                return Observable.of(false);
            });
    }
  • canActivatecanLoadCanActivateChild中创建一个身份验证保护并调用isAuthorized方法。

  • 在您的回调中,处理未经授权的请求。您可以将用户重定向到错误页面或删除导航栏,以及任何您想要的。

希望对你有帮助!

【讨论】:

  • 如果你根据我的回答用你已经尝试过的东西创建一个plunker,我可以做出改变并提供更好的帮助。
【解决方案2】:

我不确定这是否能解决所有问题,但我认为您想先从 localstorage 读取值以获取最近存储的状态,如果您使用 BehaviorSubject,如果之前调用了 this.subject.emit(),侦听器也会获得最后一个状态订阅者正在订阅。

@Injectable()
export class LoginService {
    //private subject: Subject<boolean> = new Subject<boolean>(false);
    private subject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(); // <<< changed
    constructor(private router : Router) {
      this.sublect.next(logalStorage.getItem('isLogin')); // <<< added
    }
    login(){
        this.setLogged(true);
        localStorage.setItem("isLogin","true");
        this.router.navigate(['/news-feed']);
    }
    logout(){
        this.setLogged(false);
        localStorage.removeItem("isLogin");
        this.router.navigate(['/login']);
    }
    getLogged(): Observable<boolean> {
        return this.subject.asObservable();
    }
    setLogged(val : boolean): void {
        this.subject.next(val);
    }
}

【讨论】:

  • 由于以下行私有主题而导致运行时错误: BehaviorSubject = new BehaviorSubject(); //
  • 那么应该是new BehaviorSubject&lt;boolean&gt;(false);
  • 以上一个删除了运行时错误,但没有给出预期的输出。
  • 那我不知道。
猜你喜欢
  • 2016-07-18
  • 2017-12-20
  • 2018-04-08
  • 1970-01-01
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
相关资源
最近更新 更多