【问题标题】:Transferring data between non-nested components在非嵌套组件之间传输数据
【发布时间】:2017-03-06 06:52:03
【问题描述】:

基本上,我想要的是传输数据 b/w 组件。

我在母版页上有一个 angular2 组件,用于部分查看登录 -

<loginpartial></loginpartial>

这最初是通过这个带有子组件的html模板呈现的-

<ul [hidden]="!item.isAuthenticated">
    <li><a href="javascript:;">Hello! {{item.userName}}</a></li>
    <li><a href="javascript:;">LogOff</a></li>
</ul>
<ul [hidden]="item.isAuthenticated">
    <li><a href="javascript:;">Hello! User</a></li>
    <li><a href="javascript:;">Log In</a></li>
</ul>

子组件 -

@Component({
    selector: 'loginpartial',
    templateUrl: '../Templates/LoginPartial.html'
})

export class LoginPartialComponent implements OnInit {
    public item: any = { isAuthenticated: false, userName: ' ' }
    constructor() {
        this.item.isAuthenticated = false;
    }

    ngOnInit() {
        this.item.isAuthenticated = false;
    }
}

我希望这直到现在才有意义。现在我需要的是,一旦用户登录,我想在这个从父组件传输的局部视图中获取用户名。

父组件

import { Component, ChangeDetectionStrategy, OnInit} from '@angular/core';
import {LoginPartialComponent} from '../loginpartialview/loginpartial.component.ts';
import {SharedService} from '../sharedService/app.sharedService.ts';

@Component({
    selector: 'loginmodel',
    templateUrl: '../Templates/Login.html',
    changeDetection: ChangeDetectionStrategy.OnPush,
    providers: [LoginPartialComponent,SharedService]
})
export class LoginComponent implements OnInit {
    item: any = {
        isAuthenticated: false, userName: ' '
    };
    constructor(private sharedService: SharedService,
        private loginComp: LoginPartialComponent) {
    }

    onSubmit(item: any): void {
        if (this.myForm.valid) {
            var userObject = {
                email: item.email,
                password: item.password
            };
            this.sharedService.getLogin(userObject).map(response => response.json())
                .subscribe(
                data => this.handleResult(data),
                error => console.log(error)
                );
        }
    }

    private handleResult(data) {
        if (data.success) {
            this.item.isAuthenticated = true;
            this.item.userName = data.userName;
            this.item = this.loginComp.item;
        }
        else {

        }
    }
}

从这个父组件中可以看出,当调用onSubmit 函数时,这是我的登录表单提交,我正在调用handleResult,这是从共享服务的ajax 调用设置数据。

这不会让子组件 - LoginPartialComponent 刷新。我也尝试使用 @Input() 类型参数,但没有帮助。

更新 -

正如@Camaron 在他的回答中所说,我仅使用事件发射器为此登录目的创建了一个依赖项。但这不起作用。

LoginPartialComponent

import { Component, OnInit} from '@angular/core';
import {LoginPartialModel} from '../loginpartialview/loginpartial.model.ts';
import {SharedService} from '../sharedService/app.sharedService.ts';

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Component({
    selector: 'loginpartial',
    templateUrl: '../Templates/LoginPartial.html',
    providers: [SharedService]
})

export class LoginPartialComponent {
    item: LoginPartialModel = new LoginPartialModel();
    constructor(private service: SharedService) {
        this.service.onLoginSuccess.subscribe((loginData: any) => this.item == loginData.item);
    }

}

登录组件

import { Component, OnInit} from '@angular/core';
import {SharedService} from '../sharedService/app.sharedService.ts';

@Component({
    selector: 'loginmodel',
    templateUrl: '../Templates/Login.html',
    providers: [SharedService]
})
export class LoginComponent {

    constructor(private sharedService: SharedService) {
    }

    onSubmit(item: any): void {
            var userObject = {
                email: item.email,
                password: item.password
            };
            this.sharedService.getLogin(userObject).map(response => response.json())
                .subscribe(
                data => this.handleResult(data),
                error => console.log(error)
                );
    }
    private handleResult(data) {
        if (data.success) {
            this.close();
            this.sharedService.onLoginSuccess.emit(data);
        }
        else {

        }
    }
}

共享服务(依赖)

import { Component, Injectable, EventEmitter} from '@angular/core';

@Injectable()
export class SharedService {

    onLoginSuccess: EventEmitter<any> = new EventEmitter<any>();
    constructor() {
    }

    notifyLoginSuccess(item: any): void {
        this.onLoginSuccess.emit({ item: item });
    }
}

这不起作用。

【问题讨论】:

  • 在你的handleResult函数内部,不应该是this.loginComp.item = this.item;而不是this.item = this.loginComp.item;
  • @camaron,是的,应该是这个。但这不会改变它。
  • 您是否尝试从两个组件中删除 changeDetection 策略?
  • @camaron,实际上这些组件没有嵌套。两者都是独立的。您认为删除 changeDetection 会有所帮助吗?
  • 检查这一行 this.service.onLoginSuccess.subscribe((loginData: any) =&gt; this.item == loginData.item) 有一个双 = 应该只有一个 =。

标签: angularjs angular typescript angularjs-directive angularjs-scope


【解决方案1】:

我相信 Angular 狂热的首选方式是在组件(我猜是服务,尽管我猜现在只是组件)中创建一个函数可观察并订阅它。

我觉得这篇文章讲得很好:

http://mean.expert/2016/05/21/angular-2-component-communication/

还要注意父 -> 子的输入和输出属性,反之亦然通信。

【讨论】:

  • 感谢您的宝贵时间,但事实是这些组件既不是父母也不是孩子。所以这不是嵌套组件的情况。这里的组件是独立的。
  • 解决方案不仅适用于父母和孩子。查看链接,它讨论了两者的解决方案。
【解决方案2】:

尝试使用subscribeLoginPartialComponent服务建立这种通信。

@Injectable()
export class LoginService {

    onLoginSuccess: EventEmitter<any>() = new EventEmitter<any>();

    constructor() {
    }

    notifyLoginSuccess(item:any):void {
        this.onLoginSuccess.emit({item: item});
    }

}

然后在两个组件上注入此服务。 在您的LoginPartialComponent 订阅此服务事件。

constructor(public loginService:LoginService) {
    this.loginService.onLoginSuccess.subscribe((loginData: any) => this.item = loginData.item);
}

然后在您的handleResult 函数中调用loginService.notifyLoginSuccess 并发送item

使用此解决方案,您可以删除组件的依赖关系,因此 LoginComponent 不需要知道存在 LoginPartialComponent

【讨论】:

  • 感谢您的宝贵时间,但事实是这些组件既不是父母也不是孩子。所以这不是嵌套组件的情况。这里的组件是独立的。
  • 这个例子并不重要,这个解决方案适用于组件之间的任何类型的关系以及那些没有关系的组件。在您的 ngmodule 提供程序上添加此服务,以便在两个组件上使用相同的服务实例。
  • 我按你说的试过了。让我编辑问题。我认为它没有调用 loginComponent 的构造函数。
  • this.sharedService.notifyLoginSuccess(data); 这称为共享服务事件,但不是部分组件的构造函数中的事件。
  • 这似乎是向组件注入服务的问题,您是否删除了提供者:两个组件上的 [SharedService] 并将 SharedService 添加为全局提供者对吗?
猜你喜欢
  • 1970-01-01
  • 2021-06-30
  • 2017-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-09
  • 2020-03-13
  • 2016-06-01
相关资源
最近更新 更多