我正在寻找实现这一目标的方法:
我有一个列表视图组件,其中有一个子列表。 子级列表可能会随着时间而变化(例如由于过滤器) 列表视图组件具有可观察到的渲染项。
孩子有一个附加的list-item指令, 这样,可以通过该指令从父组件中查询它们(因此,在列表中呈现哪种类型的组件都没有关系,它们只需要应用该指令即可)
该指令已选择“可观察的” $
现在如何在包含当前选定项目的列表组件内部获得一个可观察对象?
我在stackblitz上做了一个例子,为简便起见,我的应用程序组件是此处的listview组件:
https://stackblitz.com/edit/angular-rktm99
更新 我正在寻找一种方法来组合流以使用选定的ListViewItemDirectives到达流。其他事情起作用,我被这个特殊的事情所困扰: 我有一个可观察的contentChildren流,每个孩子都有一个可观察的属性selected $。我正在研究如何将它们组合在一起(我想我需要像mergeMap或switchMap这样的运算符?)
答案 0 :(得分:0)
我猜想指令选择器出了点问题,因为 length 即将 0 this.items
@ViewChildren(ListViewItemDirective)
items: QueryList<ListViewItemDirective>;
constructor() {
setInterval(() => {
console.log('aaaaavvvv');
console.log(this.items);
}, 1000);
}
现在将选择器更改为
@Directive({
selector: 'li'
})
长度正在增加
QueryList {dirty: false, _results: Array[138], changes: {…}, length: 138…}
changes: EventEmitter
dirty: false
first: ListViewItemDirective
last: ListViewItemDirective
length: 138
_results: Array[138]
答案 1 :(得分:0)
首先,我认为我们可能有一个更好的解决方案,因为当前的情况看起来像是黑客。
删除ListViewItemDirective中的重复项。
@Directive({
selector: '[list-view-item]'
})
export class ListViewItemDirective {
selected$: Subject<boolean> = new BehaviorSubject(false);
@Input('list-view-item') listViewItem;
@HostBinding('class.selected')
get isSelectedClass() {
return this.selected$.getValue();
}
@HostListener('click')
clickEvent() {
this.selected$.next(!this.selected$.getValue());
}
}
将ContentChildren
更改为ViewChildren
,并将其“转换”为Observable。
当ViewChildren
发出时,我们将得到Observable<directive[]>
,请使用directiveToObservable
得到Observable<Observable<listViewItem>[]>
。
combineLatest
会将其解包到Observable<listViewItem[]>
function directiveToObservable(directive) {
return directive
.selected$
.pipe(map(selected => selected ? directive.listViewItem : null))
}
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterContentInit {
name = 'Angular';
options = [];
listItems = new BehaviorSubject([]);
selectedItems$ = this.listItems.pipe(
// hack ExpressionChangedAfterHasBeenChacked, as a changes in child will change parent
delay(0),
switchMap(
directives => combineLatest(
directives.map(directiveToObservable),
),
),
map(list => list.filter(el => !!el)),
);
data$ = timer(0, 2000).pipe(
tap((i) => this.options.push('option ' + i)),
map(i => this.options)
);
@ViewChildren(ListViewItemDirective)
set items(items: QueryList<ListViewItemDirective>) {
this.listItems.next(items.toArray())
}
}