Angular 自定义组件的角度2可观察

Angular 自定义组件的角度2可观察,angular,rxjs,observable,Angular,Rxjs,Observable,我制作了一个组件——我们称之为CUSTOMSELECT,它需要一些输入,例如下拉列表的选项列表、默认选中的选项、标签等等 我想在某些页面上多次使用此组件。例如,我需要一个CUSTOMSELECT的员工,在页面上的嵌套组件中,我需要一个CUSTOMSELECT的部门和另一个角色 好的,到目前为止一切都很好。每个实例都正确显示了所需的数据 现在,我想在CUSTOMSELECT实例中发布选择的任何更改,以便我可以订阅它。例如,当选择一名员工时,我希望刷新页面的其余部分 我为此创建了一个服务。我将CUS

我制作了一个组件——我们称之为CUSTOMSELECT,它需要一些输入,例如下拉列表的选项列表、默认选中的选项、标签等等

我想在某些页面上多次使用此组件。例如,我需要一个CUSTOMSELECT的员工,在页面上的嵌套组件中,我需要一个CUSTOMSELECT的部门和另一个角色

好的,到目前为止一切都很好。每个实例都正确显示了所需的数据

现在,我想在CUSTOMSELECT实例中发布选择的任何更改,以便我可以订阅它。例如,当选择一名员工时,我希望刷新页面的其余部分

我为此创建了一个服务。我将CUSTOMSELECT中的click事件链接到一个将所选值发布到服务的函数。在父组件中,我已订阅“主题”,以便我可以对员工的变更采取行动

这很有效

但是,如果我随后使用嵌套组件的department CUSTOMSELECT更改选择,则会发布该值,并且父组件的员工订户会拾取该更改并对其进行处理。不是我想发生的事。一点也不

那么,我怎样才能告诉观察者只关注他们感兴趣的信息呢?也就是说,我如何向适当的观察者发布:employee实例不需要知道department实例的值已更改,等等

谢谢你的帮助,到目前为止,我花了一整天的时间试图解决这个问题

可以这样查看组件树:

employee-roles.component
  select-dropdown.component (employees)
  employee-roles-form.component
    select-dropdown.component (departments)
    select-dropdown.component (roles)
这是密码

选择dropdown.component.html

<div style="margin-top: 12px" class="input-group">
<span class="input-group-addon" style="height:30px">{{label}}</span>
<input type="text" class="form-control" style="height:30px" 
(change)="filterTextChanged($event.target.value)" placeholder="Enter a 
value to search for ..." />
</div>
<div style="margin-top: -6px" class="input-group">
<select class="form-control" (click)="publishChange($event)" size="5">
<option>Please select an option ...</option>
<option *ngFor="let item of list" 
  [selected]="item.dropdownValue==selected"
  [value]="item.dropdownValue"
  >{{item.dropdownText}}</option>
</select>
</div>
选择下拉列表.service.ts

import { Component, EventEmitter, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { SelectDropdownService } from 'common/services/select-dropdown.service';
import { SelectModule } from 'ng2-select';
import * as _ from 'lodash';

@Component({
  inputs: ['enablefilter', 'label', 'list', 'selected'],
  outputs: ['filterTextChanged'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => SelectDropdownComponent),
      multi: true
    }
  ],
  selector: 'app-select-dropdown',
  templateUrl: './select-dropdown.component.html',
  styleUrls: ['./select-dropdown.component.scss']
})
export class SelectDropdownComponent implements ControlValueAccessor {

  propagateChange = (_: any) => { };
  private enablefilter: boolean;
  private label       : string;
  private list        : string[];
  private originalList: string[];
  private value       : any = {};

  /**
   * TODO: Need to review the methods in this class which have been copied from the web
   */
  constructor(
    public selectDropdownService: SelectDropdownService
  ) {
    this.enablefilter = false; // please do not change as would affect many forms!
  }

  /**
   * Let the parent component know that an option has been selected
   * @param event 
   */
  public publishChange(event) {
    // let target = event.target;
    let selectedValue = event.target.value;
    this.propagateChange(selectedValue);
    this.selectDropdownService.sendSelectedValue(selectedValue);
  }
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class SelectDropdownService {

  className: string = this.constructor['name'];
  private dropdownValueSubject: Subject<number> = new Subject<number>();

  constructor() { }

  sendSelectedValue(id: number) {
    this.dropdownValueSubject.next(id);
  }

  getServiceObservable(): Observable<number> {
    return this.dropdownValueSubject.asObservable();
  }
}
employee-roles.component.html-提取

<app-select-dropdown [enablefilter]="enableEmployeeFilter" label="Employees" [selected]="selectedEmployeeID" [list]="employeeList">
</app-select-dropdown>

我不确定不同选择的潜在值到底是什么,但您是否可以对该值进行某种逻辑检查,以区分不同的场景

比如说

subscribe(selectedDeptID => {
    if (regex.test(selectedDeptID)) {
        this.selectedDeptID = selectedDeptID;
    }
})

其中,
regex
可能是您的匹配条件,或者用某种值映射替换该逻辑,等等。

根据您的先决条件,有几个选项:

如果您只能通过其ID来区分所选下拉值的类型 然后在每个
.subscribe
前面放一个
.filter
。e、 g.如果员工ID始终小于100:

this.selectDropdownService.getServiceObservable()
    .filter((selectedId: number) => selectedId <= 100)
    .subscribe(selectedEmployeeID => {
        this.selectedEmployeeID = selectedEmployeeID;
        this.refreshRequired();
    });
然后将您的
主题
更改为
主题
,并将您的服务方法更改为:

sendSelectedValue(id: number, type: string) {
    this.dropdownValueSubject.next({id: id, itemType: type});
}

getServiceObservable(type: string): Observable<number> {
    return this.dropdownValueSubject.asObservable()
           .filter((item: SelectedItem) => item.itemType === type) //filter by type
           .map((item: SelectedItem) => item.id); // only return the id
}
sendSelectedValue(id:number,type:string){
this.dropdownValueSubject.next({id:id,itemType:type});
}
getServiceObservable(类型:string):可观察{
返回此.dropdownValueSubject.asObservable()
.filter((项目:SelectedItem)=>item.itemType==类型)//按类型筛选
.map((item:SelectedItem)=>item.id);//只返回id
}
现在,当您运行
this.selectDropdownService.getServiceObservable()
时,只需将相应的
itemType
放入参数中:
this.selectDropdownService.getServiceObservable(“员工”)
this.selectDropdownService.getServiceObservable(“部门”)


当然,您必须知道select组件中的类型,您只需将类型作为输入传递即可…

除非您共享代码,否则您可能希望获得很少的帮助,我的朋友:)啊,很公平,thankshow是@AJT_82吗?更好,不幸的是,我没有时间深入研究那么多代码,这是再现问题的最低限度的代码吗?不是故意刁难,只是想帮忙;)希望您现在有了代码后能得到一些帮助。@AJT_82通知您很抱歉来到这里,因为我只能在这里通知您。我认为这(带有接口)为我巧妙地解释了一个好的解决方案。非常感谢。:)
subscribe(selectedDeptID => {
    if (regex.test(selectedDeptID)) {
        this.selectedDeptID = selectedDeptID;
    }
})
this.selectDropdownService.getServiceObservable()
    .filter((selectedId: number) => selectedId <= 100)
    .subscribe(selectedEmployeeID => {
        this.selectedEmployeeID = selectedEmployeeID;
        this.refreshRequired();
    });
interface SelectedItem {
    id: number;
    itemType: "employee" | "department";
}
sendSelectedValue(id: number, type: string) {
    this.dropdownValueSubject.next({id: id, itemType: type});
}

getServiceObservable(type: string): Observable<number> {
    return this.dropdownValueSubject.asObservable()
           .filter((item: SelectedItem) => item.itemType === type) //filter by type
           .map((item: SelectedItem) => item.id); // only return the id
}