在角度2中跨组件共享事件驱动变量

时间:2017-05-25 19:47:18

标签: javascript angular

我有一个包含数据表的组件,我使用管道进行过滤,

我触发并向管道发送新参数的方式是输入标记上的输入事件,我捕获'targetInput'变量中的输入,

以上设置有效,下面是它的样子:

        <tr >
            <td  *ngFor="let column of currentView.columns">
                <div *ngIf="column.label">
                    <input placeholder="{{column.label}}" id="{{column._devName}}" type="text"
                           (input)="targetInput = {targetValue:$event.target.value,targetId:$event.target.id,currentFilterMap:currentFilterMap}">
                </div>
            </td>
        </tr>

        <ng-container *ngFor="let task of (currentView.tasks | countryPipe:targetInput); let i=index">
            <tr class="worktask" (click)="setCurrentTask($event, task)" (dblclick)="openWindowNewTab(getOpenTaskURL(task, currentView.process))"
                id="workspace_table_wo_{{ task.workOrderId }}_task_{{ task.taskId }}"
                [class.table-active]="isSelected(task)">
                <td *ngFor="let column of currentView.columns">{{task[column.devName]}}</td>
            </tr>

现在我决定,我想要一个单独的输入标签组件,所以我拆分html并进行父子设置并使用@Input装饰器传递共享变量,

这是新设置的外观, 父html:

    <tr >
        <td  *ngFor="let column of currentView.columns">
            <filterTagBox [taskCol] = "column" [currentFilterMap] = "currentFilterMap"></filterTagBox>
        </td>
    </tr>
    <ng-container *ngFor="let task of (currentView.tasks | countryPipe:targetInput); let i=index">
        <tr class="worktask" (click)="setCurrentTask($event, task)" (dblclick)="openWindowNewTab(getOpenTaskURL(task, currentView.process))"
            id="workspace_table_wo_{{ task.workOrderId }}_task_{{ task.taskId }}"
            [class.table-active]="isSelected(task)">
            <td *ngFor="let column of currentView.columns">{{task[column.devName]}}</td>
        </tr>

现在我似乎无法将targetInput从子组件传递回输入事件的父组件,不确定这是否是我应该实现的方式,或者是否有更好的方法。

3 个答案:

答案 0 :(得分:1)

我认为在你的情况下,parent是Parent html,child是filterTagBox。如果您想要从父母转移到孩子,您需要使用 @input

如果您想要从子级转移到父级,则需要使用 EventEmitter @Output

更多信息。 https://angular.io/docs/ts/latest/cookbook/component-communication.html

答案 1 :(得分:1)

我使用BehaviorSubject来通知订阅它的任何组件(您的情况中的父组件)。这是一种特殊类型的可观察物。消息服务可以为您完成。定义消息模型(如果您愿意,甚至可以使用简单的字符串)并创建消息服务:

import {Observable, BehaviorSubject} from 'rxjs/Rx'; // 
import {Message} from "../../models/message";        // Your model

... inside your message service class:

private _newMessage = new BehaviorSubject<Message>(new Message);
getMessage = this._currentUser.asObservable();
sendMessage(message: Message) { this._newMessage.next(message) }

在某个组件中(例如在父组件中),您可以按以下方式订阅getMessage主题:

this.messageService.getMessage.subscribe(
message => {
    // a message received, do whatever you want
    if (message == "so important message")
      this.list = newList;
    // ... so on
});

这样,多个组件可以订阅此BehaviorSubject,并且使用sendMessage方法的任何组件/服务中的任何触发器都可以立即更改这些订阅组件。对你来说,这可能是一个儿童组成部分:

... you successfully made something in your
... child component, now use the trigger:

this.messageService.sendMessage(new Message("so important message", foo, bar));

答案 2 :(得分:0)

感谢您的回答,我确实弄清楚我是如何做到这一点的,虽然我发现使用行为服务很有趣但我决定使用输出变量将子组件的数据发送到父组件,这将最终发送到管道,

这是我做的:

子组件HTML:

                <div *ngIf="taskCol.label">
                    <div id="{{taskCol._devName}}_tagBox"></div>
                    <input placeholder="{{taskCol.label}}" id="{{taskCol._devName}}" type="text"
             <!-- Call childComponent.onInput passing event parameters -->              

   (input)="onInput({targetValue:$event.target.value,targetId:$event.target.id})"> 
                </div>

Child component.ts:

@Component({
  selector: 'filterTagBox',
  template: require('./filterTagBox.component.html')
})
export class FilterTagBox{

  private colValues:string[];
  public containsQueries:boolean;
  private regex:RegExp;
  @Input() public taskCol:TaskColumn;                          

  @Output() onItemInput = new EventEmitter<any>();   // bound event to the parent component

  // constructor and other hidden methods...

  onInput(targetInput : any){
    this.onItemInput.emit(targetInput);            //trigger  onItemInput event on inputBox input 
  }


}

父组件html:

<tr >
                <td  *ngFor="let column of currentView.columns">
                     <!-- Catch custom onItemInput event which was triggered in the child -->
                    <filterTagBox (onItemInput)="filterBoxPipeData = {targetValue:$event.targetValue,targetId:$event.targetId,currentFilterMap:currentFilterMap}"  [taskCol] = "column" ></filterTagBox>
                </td>
            </tr>

            <!--sent the data retrieve from the input i.e filterBoxPipeData to the pipe i.e tagBoxFilterPipe along with data to be filtered i.e currentView.task -->
            <ng-container *ngFor="let task of (currentView.tasks | tagBoxFilterPipe:filterBoxPipeData); let i=index">
                <tr> 
                <!--hidden html -->
                </tr>