简体   繁体   English

在角度2中的各个组件之间共享事件驱动的变量

[英]sharing event driven variable across component in angular 2

I have a component which has a data table which I filter using a pipe, 我有一个包含数据表的组件,该数据表是使用管道过滤的,

The way I trigger and sent new argument to the pipe is on input-event on a input tag , I capture the input in 'targetInput' variable, 我触发并向管道发送新参数的方式是在input标签上的input-event上,我在'targetInput'变量中捕获输入,

The above setup works, here is how it looks like: 上面的设置有效,如下所示:

        <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>

Now I decide , that I want a separate component for the input tag , so I split the html and make a parent-child setup and pass the shared variable using @Input decorator, 现在,我决定要为input标签使用一个单独的组件,因此我拆分了html并进行了父子设置,并使用@Input装饰器传递了共享变量,

This is how the new setup looks , Parent html: 这是新设置的外观,父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>

Now I can't seem to pass the targetInput from the child component back to the parent on the input event, Not sure if this is the way I should implement this or if there is a better way. 现在,我似乎无法在输入事件中将targetInput从子组件传递回父组件,不知道这是应该实现的方式还是有更好的方式。

I think in your case parent is Parent html and child is filterTagBox. 我认为在您的情况下,parent是Parent html,child是filterTagBox。 if you want transfer value from parent to child you need use @input 如果要将值从父母转移到孩子,则需要使用@input

if you want transfer value from child to parent you need use EventEmitter and @Output 如果要将值从子级转移到父级,则需要使用EventEmitter@Output

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

I use BehaviorSubject to notify any component (the parent in your situation) that subscribes it. 我使用BehaviorSubject通知任何订阅该组件的组件(您所处的父组件)。 It's a special type of observables. 这是一种特殊的可观察性。 A message service can do it for you. 消息服务可以为您做这件事。 Define a message model (you can even use a simple string if you prefer) and create a message service: 定义消息模型(如果愿意,甚至可以使用简单的字符串)并创建消息服务:

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) }

In a component (eg in a parent), you can subscribe getMessage subject like this: 在组件中(例如在父组件中),您可以订阅getMessage主题,如下所示:

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

This way, multiple components can subscribe to this BehaviorSubject , and any trigger in any component/service that uses sendMessage method can change these subscribed components immediately. 这样,多个组件可以订阅此BehaviorSubject ,并且任何使用sendMessage方法的组件/服务中的任何触发器都可以立即更改这些订阅的组件。 For you, that can be a child component: 对您来说,这可以是子组件:

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

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

Thanks for the answers , I did figure out how I could do this ,and although I found using behaviour service interesting I decided to use a output variable to sent data form the child component to the parent which would ultimatedly sent to the pipe, 感谢您的回答,我确实弄清楚了如何做到这一点,尽管我发现使用行为服务很有趣,但我还是决定使用输出变量将数据从子组件发送到父组件,最终将其发送到管道,

Here is what I did : 这是我所做的:

Child component HTML: 子组件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.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 
  }


}

Parent component html : 父组件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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM