我已经制作了一个组件 - 让它称之为CUSTOMSELECT,它需要一些输入,例如下拉列表,默认选项,标签等选项列表。
我想在某些页面上多次使用此组件。例如,我需要一个CUSTOMSELECT员工,在页面的嵌套组件中,我需要一个CUSTOMSELECT部门和另一个角色。
好的,到目前为止一切都很好。每个实例都正确显示所需的数据。现在我想在CUSTOMSELECT的实例中发布任何选择更改,以便我可以订阅它。例如,当选择员工时,我想刷新页面的其余部分。
我为此创建了一项服务。我将CUSTOMSELECT中的click事件链接到一个函数,该函数将所选值发布到服务。在父组件中,我订阅了主题'这样我就可以改变员工的行为。
有效。
但是,如果我随后使用嵌套组件的部门CUSTOMSELECT更改选择,则会发布此值,并且父组件的员工订阅者将获取更改并对其进行处理。不是我想要发生的事情。完全没有!
那么,我怎样才能告诉观察者只关注他们感兴趣的信息?即,我如何向适当的观察者发布:员工实例不需要知道部门实例已经更改了值,依此类推。
感谢您的帮助 - 到目前为止,整整一天都试图解决这个问题。
查看组件树可能会有所帮助:
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>
选择-dropdown.component.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);
}
选择-dropdown.service.ts
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.ts - 摘录(这是父组件)
import { SelectDropdownService } from 'common/services/select-dropdown.service';
constructor(
private activatedRoute : ActivatedRoute,
private sabreAPIService : SabreAPIService,
private selectDropdownService: SelectDropdownService
) { }
ngOnInit() {
this.enableEmployeeFilter = true;
this.apiEmployeeProfile = new EmployeeProfile(this.sabreAPIService, null);
this.readParameters();
this.listEmployees();
this.observeEmployeeDropdown();
}
/**
* Read URL parameters
*/
private readParameters() {
this.activatedRoute.params
.subscribe((params: Params) => {
this.selectedEmployeeID = params['id'];
});
}
/**
* subscribe to change of emplyee dropdown
*/
observeEmployeeDropdown() {
this.selectDropdownService.getServiceObservable()
.subscribe(selectedEmployeeID => {
this.selectedEmployeeID = selectedEmployeeID;
this.refreshRequired();
})
}
employee-roles.component.html - extract
<app-select-dropdown [enablefilter]="enableEmployeeFilter" label="Employees" [selected]="selectedEmployeeID" [list]="employeeList">
</app-select-dropdown>
employee-roles-form.component.html - extract (2个自定义组件实例)
<app-select-dropdown label="Department" [list]="payrollDepartmentsList" [selected]="selectedDeptID"></app-select-dropdown>
<app-select-dropdown label="Role" [list]="businessRolesList" [selected]="selectedBroleID"></app-select-dropdown>
employee-roles-form.component.ts (摘录)
import { SelectDropdownService } from 'common/services/select-dropdown.service';
constructor(
private formBuilder: FormBuilder,
private sabreAPI: SabreAPIService,
private selectDropdownService: SelectDropdownService
) { }
ngOnInit() {
this.apiEmployeeRole = new EmployeeRole(this.sabreAPI, null);
this.generateFormControls();
this.listBusinessRoles();
this.listPayrollDepartments();
this.observeDepartmentDropdown();
}
observeDepartmentDropdown() {
this.selectDropdownService.getServiceObservable()
.subscribe(selectedDeptID => {
this.selectedDeptID = selectedDeptID;
})
}
答案 0 :(得分:1)
根据您的前提条件,有几个选项:
如果您可以区分所选下拉值的类型,则只能
然后只需在.filter
前加.subscribe
。例如如果员工ID总是小于100:
this.selectDropdownService.getServiceObservable()
.filter((selectedId: number) => selectedId <= 100)
.subscribe(selectedEmployeeID => {
this.selectedEmployeeID = selectedEmployeeID;
this.refreshRequired();
});
如果您只能按ID确定类型。那么您需要发出的不仅仅是ID。在服务中创建一个接口,该接口也包含一个类型:
interface SelectedItem {
id: number;
itemType: "employee" | "department";
}
然后将您的Subject<number>
更改为Subject<SelectedItem>
,将您的服务方法更改为:
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
}
现在当您运行this.selectDropdownService.getServiceObservable()
时,只需将相应的itemType
放入参数:this.selectDropdownService.getServiceObservable("employee")
或this.selectDropdownService.getServiceObservable("department")
当然,您必须了解select组件中的类型,您只需将类型作为输入传递即可...
答案 1 :(得分:0)
我不确定不同选择的潜在价值究竟是什么,但您是否有可能对价值进行某种逻辑检查以区分您的情景?
例如
subscribe(selectedDeptID => {
if (regex.test(selectedDeptID)) {
this.selectedDeptID = selectedDeptID;
}
})
其中regex
可能是您的匹配条件,或者用某种值映射替换该逻辑等。