我正在尝试复制Fabric样式下拉列表的外观,以便在Angular 2中使用.我正在努力解决两个重要问题:
>我正在使用ngModel
>下拉组件在查询之前不知道其子项.下拉项目将出现在其他模板中,因为它是“其他东西”,它将需要插入数据.
这是我到目前为止下拉和dropdownItem组件的内容:
@Component({ selector: "dropdown",template: ` <div class="ms-Dropdown" [ngClass]="{'ms-Dropdown--open': isOpen}"> <span class="ms-Dropdown-title" (click)="toggleDropdown()"> {{selectedName}} </span> <ul class="ms-Dropdown-items"> <ng-content></ng-content> </ul> </div>`,providers: [QueryList] }) export class FabricDropdownComponent extends AbstractValueAccessor implements AfterContentInit { public selectedName: string; public isOpen: boolean; private subscriptions: Subscription[]; constructor( @ContentChildren(FabricDropdownItemComponent) private items: QueryList<FabricDropdownItemComponent>) { super(); this.subscriptions = []; this.selectedName = "Filler text,this should be replaced by 'Thing'"; this.isOpen = false; } // HERE'S THE PROBLEM: this.items is an empty array,so I can't find any child components. public ngAfterContentInit() { this.items.changes.subscribe((list: any) => { // On every change,re-subscribe. this.subscriptions.forEach((sub: Subscription) => sub.unsubscribe()); this.subscriptions = []; this.items.forEach((item: FabricDropdownItemComponent) => { this.subscriptions.push(item.onSelected.subscribe((selected: INameValuePair) => { this.value = selected.value; this.selectedName = selected.name; this.isOpen = false; })); }); }); // During init,display the *name* of the selected value. // AGAIN: items is empty,can't set the initial value. What's going on? this.items.forEach((item: FabricDropdownItemComponent) => { if (item.value === this.value) { this.selectedName = item.name; } }) } public toggleDropdown() { this.isOpen = !this.isOpen; } } @Component({ selector: "dropdownItem",template: `<li (click)="select()" class="ms-Dropdown-item" [ngClass]="{'ms-Dropdown-item--selected': isSelected }">{{name}}</li>` }) export class FabricDropdownItemComponent implements OnInit { @Input() public name: string; @Input() public value: any; @Output() public onSelected: EventEmitter<INameValuePair>; public isSelected: boolean; constructor() { this.onSelected = new EventEmitter<INameValuePair>(); this.isSelected = false; } public ngOnInit() { if (!this.name) { this.name = this.value.toString(); } } public select() { this.onSelected.emit({ name: this.name,value: this.value }); this.isSelected = true; } public deselect() { this.isSelected = false; } }
(AbstractValueAccessor来自this other answer.)
这就是我在应用程序中实际使用它们的方式:
<dropdown [(ngModel)]="responseType" ngDefaultControl> <dropdownItem [value]="'All'"></dropdownItem> <dropdownItem *ngFor="let r of responseTypes" [value]="r.value" [name]="r.name"></dropdownItem> </dropdown>
我的问题是@ContentChildren的下拉列表的QueryList始终为空,因此当我点击其中一个dropdownItem时它不会得到通知.为什么QueryList为空,我该如何解决?我错过了什么? (我想我可以使用服务在dropdown和dropdownItem之间进行通信,而不是QueryList,但这不是我在这里问的问题 – 为什么QueryList为空?)
我尝试过使用@ViewChildren,但这不起作用.我尝试将FabricDropdownItemComponent添加到下拉列表的指令中,但这只是给出了一个不同的错误:错误:组件’FabricDropdownComponent’视图上的意外指令值’undefined’
Plunker:https://plnkr.co/edit/D431ihORMR7etrZOBdpW?p=preview