rxjs#switchMap TypeScript Examples
The following examples show how to use
rxjs#switchMap.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: base-select.ts From alauda-ui with MIT License | 6 votes |
ngAfterContentInit() {
this.customCreatedOptions$ = combineLatest([
this.values$,
(
this.contentOptions.changes as Observable<QueryList<OptionComponent<T>>>
).pipe(
startWith(this.contentOptions),
switchMap((options: QueryList<OptionComponent<T>>) =>
options.length > 0
? combineLatest(options.map(option => option.value$))
: of([] as T[]),
),
),
]).pipe(
map(([values, optionValues]) =>
values.reduce<Array<SelectFilterOption<T>>>((acc, value) => {
const included = optionValues
.map(value => this.trackFn(value))
.includes(this.trackFn(value));
if (!included) {
const label =
this.labelFn?.(value) || coerceString(this.trackFn(value));
if (label) {
acc.push({
label,
value,
});
}
}
return acc;
}, []),
),
publishRef(),
);
}
Example #2
Source File: publish-list.tsx From bext with MIT License | 6 votes |
Banner: FC<{ current: number; empty?: boolean }> = ({
current,
empty,
}) => {
const nextTime = useObservableState(
useObservable(
(input$) =>
input$.pipe(
pluckFirst,
switchMap((current) =>
timer(0, 1000).pipe(
map(() => current + REFRESH_DURATION - Date.now()),
),
),
),
[current],
),
REFRESH_DURATION,
);
return (
<Separator>
{empty ? '暂无' : ''}发布历史({' '}
{nextTime > 0 ? `${Math.floor(nextTime / 1000)} 秒后刷新` : '刷新中'})
</Separator>
);
}
Example #3
Source File: auth.ts From bext with MIT License | 6 votes |
octokit$
.pipe(
switchMap((octokit) =>
octokit
? from(octokit.rest.users.getAuthenticated()).pipe(
map(({ data, status }) =>
status === 200
? ({ status: 'complete', user: data } as const)
: ({ status: 'error' } as const),
),
startWith({ status: 'loading' } as const),
retry(2),
catchError(() => of({ status: 'error' } as const)),
)
: of({ status: 'unauth' } as const),
),
)
.subscribe(user$);
Example #4
Source File: tree-select.component.ts From alauda-ui with MIT License | 6 votes |
ngAfterViewInit() {
const hasVisibleChildNodes$ = this.childNodes.changes.pipe(
startWith(this.childNodes),
switchMap((nodes: QueryList<TreeNodeComponent<T>>) =>
nodes.length > 0
? combineLatest(nodes.map(node => node.visible$))
: of([false]),
),
map(visible => visible.some(Boolean)),
tap(hasVisibleChildren => (this.isLeaf = !hasVisibleChildren)),
);
this.visible$ = combineLatest([
this.selfVisible$,
hasVisibleChildNodes$,
]).pipe(
map(visible => visible.some(Boolean)),
publishRef(),
);
this.visible$.pipe(takeUntil(this.destroy$$)).subscribe(visible => {
this.visible = visible;
this.cdr.markForCheck();
});
this.selected$.pipe(takeUntil(this.destroy$$)).subscribe(selected => {
this.selected = selected;
this.cdr.markForCheck();
});
if (this.selected) {
requestAnimationFrame(() => {
this.scrollToNode(this);
});
}
}
Example #5
Source File: option-group.component.ts From alauda-ui with MIT License | 6 votes |
ngAfterContentInit() {
this.hasVisibleOption$ = this.options.changes.pipe(
startWith(this.options),
switchMap((options: QueryList<OptionComponent<T>>) =>
options.length > 0
? combineLatest(options.map(node => node.visible$))
: of([false]),
),
map(visible => visible.some(Boolean)),
publishRef(),
);
}
Example #6
Source File: multi-select.component.ts From alauda-ui with MIT License | 6 votes |
override ngAfterViewInit() {
super.ngAfterViewInit();
this.selectAllStatus$ = combineLatest([
this.allOptions$,
this.filterString$,
]).pipe(
switchMap(([allOptions]) =>
combineLatest([
...(allOptions ?? [])
.filter(({ visible, disabled }) => visible && !disabled)
.map(({ selected$ }) => selected$),
]),
),
map(statuses => {
const selected = statuses.filter(Boolean);
return selected.length === 0
? SelectAllStatus.Empty
: selected.length !== statuses.length
? SelectAllStatus.Indeterminate
: SelectAllStatus.Checked;
}),
startWith(SelectAllStatus.Empty),
tap(selectAllStatus => (this.selectAllStatus = selectAllStatus)),
publishRef(),
);
this.hasEnabledOptions$ = combineLatest([
this.allOptions$,
this.filterString$,
]).pipe(
map(
([allOptions]) =>
!!allOptions.filter(({ visible, disabled }) => visible && !disabled)
.length,
),
);
}
Example #7
Source File: interpreter.ts From platyplus with MIT License | 6 votes |
visit$(
node: ASTNode,
value$: Observable<ObjectType>
): Observable<ObjectType> {
return value$.pipe(
switchMap(
(value) =>
ACTIONS[node.type]?.(this, node, value) ||
throwError(() => new Error('Unknown node type: ' + node.type))
)
)
}
Example #8
Source File: search.ts From platyplus with MIT License | 6 votes |
search$ =
(
expression: string | Observable<string>,
options: SearchOptions = {}
): ((data$: Observable<ObjectType>) => Observable<ObjectType>) =>
(data$) => {
try {
const runtime = new Runtime()
const interpreter = new Intercepter(runtime, options)
runtime._interpreter = interpreter
return (isObservable(expression) ? expression : of(expression)).pipe(
switchMap((exp) => {
// ? Not ideal. Find a better workaround?
if (options.circularData && expression === '*')
throw new Error(
`Data schema is circular; The expression '*' is not allowed`
)
const node = compile(exp)
return interpreter.visit$(node, data$)
})
)
} catch (error) {
return throwError(() => new Error(error))
}
}
Example #9
Source File: form-item.component.ts From alauda-ui with MIT License | 6 votes |
ngAfterContentInit() {
this.hasError$ = this.ngControls.changes.pipe(
startWith(this.ngControls),
switchMap((controls: QueryList<NgControl>) =>
combineLatest(
controls.map(control => this.mapControlStatus(control)),
).pipe(map(statuses => statuses.some(Boolean))),
),
);
this.errorCount$ = this.errors.changes.pipe(
map(errors => errors.length),
startWith(this.errors.length),
);
this.hintCount$ = this.hints.changes.pipe(
map(hints => hints.length),
startWith(this.hints.length),
);
}
Example #10
Source File: back-top.component.ts From alauda-ui with MIT License | 6 votes |
isDisplayed$ = combineLatest([
this.target$$.asObservable().pipe(
map(target => this.getTarget(target)),
switchMap(target =>
fromEvent(target, 'scroll').pipe(
// use default scheduler
throttleTime(50, undefined, { leading: true, trailing: true }),
map(() => this.getTargetScrollTop(target)),
),
),
),
this.visibilityHeight$$,
]).pipe(
map(([scrollTop, visibilityHeight]) => scrollTop >= visibilityHeight),
distinctUntilChanged(),
);
Example #11
Source File: suggestion-group.component.ts From alauda-ui with MIT License | 6 votes |
ngAfterContentInit() {
this.hasVisibleSuggestion$ = this.suggestions.changes.pipe(
startWith(this.suggestions),
switchMap((options: QueryList<SuggestionComponent>) =>
options.length > 0
? combineLatest(options.map(node => node.visible$))
: of([false]),
),
map(visible => visible.some(Boolean)),
publishRef(),
);
}
Example #12
Source File: suggestion.component.ts From alauda-ui with MIT License | 6 votes |
constructor(
private readonly cdr: ChangeDetectorRef,
@Inject(forwardRef(() => AutocompleteComponent))
autocomplete: any, // FIXME: workaround temporarily
) {
this.autocomplete = autocomplete;
this.selected$ = combineLatest([
this.autocomplete.directive$$.pipe(
switchMap(directive => directive.inputValue$),
),
this.value$$,
]).pipe(
map(([inputValue, selfValue]) => inputValue === selfValue),
tap(selected => {
this.selected = selected;
}),
publishRef(),
);
this.visible$ = combineLatest([
this.autocomplete.directive$$.pipe(
switchMap(directive => directive.filterFn$),
),
this.autocomplete.directive$$.pipe(
switchMap(directive => directive.inputValue$),
),
this.value$$,
]).pipe(
map(([filterFn, filterString, suggestion]) =>
filterFn(filterString, suggestion),
),
tap(visible => {
this.visible = visible;
}),
publishRef(),
);
}
Example #13
Source File: autocomplete.component.ts From alauda-ui with MIT License | 6 votes |
ngAfterContentInit() {
this.hasVisibleSuggestion$ = this.suggestions.changes.pipe(
startWith(this.suggestions),
switchMap((suggestions: QueryList<SuggestionComponent>) =>
suggestions.length > 0
? combineLatest(suggestions.map(suggestion => suggestion.visible$))
: of([] as boolean[]),
),
map(visible => visible.some(Boolean)),
withLatestFrom(this.directive$$),
map(([hasVisibleSuggestion, directive]) => {
if (hasVisibleSuggestion && directive.defaultFirstSuggestion) {
directive.autoFocusFirstSuggestion();
}
return hasVisibleSuggestion;
}),
distinctUntilChanged(),
debounceTime(0),
tap(() => this.cdr.markForCheck()),
publishRef(),
);
this.hasContent$ = combineLatest([
this.hasVisibleSuggestion$,
this.placeholder.changes.pipe(
startWith(this.placeholder),
map(
(list: QueryList<AutocompletePlaceholderComponent>) => !!list.length,
),
),
]).pipe(
map(
([hasVisibleSuggestion, hasPlaceholder]) =>
hasVisibleSuggestion || hasPlaceholder,
),
);
}
Example #14
Source File: app-shell.component.ts From scion-microfrontend-platform with Eclipse Public License 2.0 | 6 votes |
private installRouteActivateListener(): void {
this._routeActivate$
.pipe(
switchMap(() => Beans.get(ContextService).observe$<OutletContext>(OUTLET_CONTEXT)),
takeUntil(this._destroy$),
)
.subscribe(outletContext => {
const context = outletContext?.name ?? 'n/a';
console.debug(`[AppShellComponent::router-outlet:onactivate] [app=${this.appSymbolicName}, location=${window.location.href}, outletContext=${context}]]`);
});
}
Example #15
Source File: wowup-protocol.service.ts From WowUp with GNU General Public License v3.0 | 6 votes |
public initialize() {
this._electronService.customProtocol$
.pipe(
tap((prt) => console.log("WowUpProtocolService", prt)),
filter((prt) => getProtocol(prt) === APP_PROTOCOL_NAME && this.isInstallAction(prt)),
switchMap((prt) => this.onInstallProtocol(prt)),
catchError((e) => {
console.error(e);
return of(undefined);
})
)
.subscribe();
}
Example #16
Source File: options-addon-section.component.ts From WowUp with GNU General Public License v3.0 | 6 votes |
public constructor(
private _addonProviderService: AddonProviderFactory,
private _sensitiveStorageService: SensitiveStorageService,
private _translateService: TranslateService,
private _dialogFactory: DialogFactory,
private _linkService: LinkService
) {
this._addonProviderService.addonProviderChange$.subscribe(() => {
this.loadProviderStates();
});
this.preferenceForm.valueChanges
.pipe(
takeUntil(this.destroy$),
debounceTime(300),
switchMap((ch) => {
const tasks: Observable<any>[] = [];
if (typeof ch?.cfV2ApiKey === "string") {
tasks.push(from(this._sensitiveStorageService.setAsync(PREF_CF2_API_KEY, ch.cfV2ApiKey)));
}
if (typeof ch?.ghPersonalAccessToken === "string") {
tasks.push(
from(this._sensitiveStorageService.setAsync(PREF_GITHUB_PERSONAL_ACCESS_TOKEN, ch.ghPersonalAccessToken))
);
}
return combineLatest(tasks);
}),
catchError((e) => {
console.error(e);
return of(undefined);
})
)
.subscribe();
}
Example #17
Source File: options-addon-section.component.ts From WowUp with GNU General Public License v3.0 | 6 votes |
private onWagoEnable(option: MatListOption) {
const providerName: AddonProviderType = option.value;
const title: string = this._translateService.instant("DIALOGS.PERMISSIONS.WAGO.TOGGLE_LABEL");
const message: string = this._translateService.instant("DIALOGS.PERMISSIONS.WAGO.DESCRIPTION", {
termsUrl: AppConfig.wago.termsUrl,
dataUrl: AppConfig.wago.dataConsentUrl,
});
const dialogRef = this._dialogFactory.getConfirmDialog(title, message);
dialogRef
.afterClosed()
.pipe(
first(),
switchMap((result) => {
if (result) {
return from(this._addonProviderService.setProviderEnabled(providerName, option.selected));
} else {
option.selected = !option.selected;
}
return of(undefined);
}),
catchError((err) => {
console.error(err);
return of(undefined);
})
)
.subscribe();
}
Example #18
Source File: context-service.ts From scion-microfrontend-platform with Eclipse Public License 2.0 | 6 votes |
/**
* Observes the names of context values registered at any level in the context tree.
*
* @return An Observable that emits the names of context values registered at any level in the context tree.
* Upon subscription, it emits the names of context values currently registered, and then it emits whenever
* some value is registered or unregistered from a context. The Observable never completes.
*/
public names$(): Observable<Set<string>> {
if (Beans.get(IS_PLATFORM_HOST)) {
return concat(of(new Set<string>()), NEVER);
}
return this._contextTreeChange$
.pipe(
startWith(undefined as void),
switchMap(() => this.lookupContextNames$()),
);
}
Example #19
Source File: context-service.ts From scion-microfrontend-platform with Eclipse Public License 2.0 | 6 votes |
public observe$<T>(name: string, options?: ContextLookupOptions): Observable<T | T[] | null> {
if (Beans.get(IS_PLATFORM_HOST)) {
return concat(of(options?.collect ? [] : null), NEVER);
}
return this._contextTreeChange$
.pipe(
filter(event => event.name === name),
startWith(undefined as void),
switchMap(() => this.lookupContextValue$<T>(name, options)),
);
}
Example #20
Source File: plugin.ts From platyplus with MIT License | 5 votes |
options: SearchOptions<{ systemFields: boolean; deleted: boolean }> = {
getField: (value, key: string | number, options) => {
if (!options.systemFields && typeof key === 'string' && key.startsWith('_'))
return of(null)
if (isRxDocument(value)) {
const document: RxDocument = value
// TODO combineLatest as per getIdentity
return document.deleted$.pipe(
switchMap((deleted) => {
if (!options.deleted && deleted) return of(null)
if (typeof key === 'number') return of(value[key] ?? null)
const definition = value.collection.schema.jsonSchema.properties[key]
if (definition) {
if (definition.ref) {
return document
.get$(key)
.pipe(switchMap(() => document.populate(key)))
} else {
return document.get$(key)
}
} else return of(value[key] ?? null)
})
)
} else return of(value[key] ?? null)
},
getIdentity: (value, { systemFields }) => {
if (isRxDocument(value)) {
const document: RxDocument = value
return combineLatest([document.deleted$, document.$]).pipe(
map(([deleted, value]) => {
if (!options.deleted && deleted) return of(null)
else {
if (systemFields) return value
else return trimSystemFields(value)
}
})
)
} else return of(value)
},
circularData: true,
systemFields: false,
deleted: false
}
Example #21
Source File: select.tsx From platyplus with MIT License | 5 votes |
DocumentSelectField: FieldComponent = ({
role,
tableinfo,
document,
name,
edit,
editable,
property
}) => {
// TODO async - see https://rsuitejs.com/components/select-picker/#Async
const refTable = useTableInfo(
relationshipTableId(tableinfo, property.relationship)
)
const [data, setData] = useState<ContentsDocument>(null)
const collection = useContentsCollection(refTable, role)
useEffect(() => {
// ? use rxdb-utils view? -> document[name].$.subscribe...
if (collection && document && name in document) {
const subscription = document
.get$(name)
.pipe(
filter((id) => {
if (id) return true
else {
setData(null)
return false
}
}),
switchMap((id) => collection.findOne(id).$)
)
.subscribe((refDocument) => {
setData(refDocument)
})
return () => subscription.unsubscribe()
}
}, [document, name, tableinfo.id, role, collection])
const options = useOptions(refTable, role)
return editable && edit ? (
<FieldControl
style={{ minWidth: 300 }}
name={name}
readOnly={!edit}
data={options}
cleanable={edit}
accepter={SelectPicker}
/>
) : data ? (
<DocumentComponentWrapper
tableinfo={refTable}
role={role}
document={data}
componentName="tag"
edit={false}
/>
) : null
}
Example #22
Source File: wrapper.tsx From platyplus with MIT License | 5 votes |
CollectionField: CollectionFieldComponent = ({
document,
name,
property,
role,
edit,
editable,
tableinfo,
accepter: Accepter,
component = 'label'
}) => {
const refTable = shiftedTable(tableinfo, property.relationship)
const refCollection = useContentsCollection(refTable, role)
const [data, setData] = useState<ContentsDocument[]>([])
useEffect(() => {
// ? use rxdb-utils view? -> document[name].$.subscribe...
if (refCollection && name in document) {
const subscription = document
.get$(name)
.pipe(
filter((values) => values),
switchMap((values) => refCollection.findByIds$(values))
)
.subscribe((mapDocs: Map<string, ContentsDocument>) => {
setData([...mapDocs.values()])
})
return () => subscription.unsubscribe()
}
}, [document, name, refCollection, property])
const options = useOptions(refTable, role)
return editable && edit ? (
<FieldControl
tableinfo={tableinfo}
role={role}
style={{ minWidth: 300 }}
name={name}
readOnly={!edit}
data={options}
initial={data}
cleanable={edit}
accepter={Accepter}
/>
) : (
<CollectionComponentWrapper
tableinfo={refTable}
role={role}
data={data}
componentName={component}
edit={false}
/>
)
}
Example #23
Source File: index.ts From platyplus with MIT License | 5 votes |
createRxHasura = async (
name: string,
url: string,
password?: string
): Promise<Database> => {
addRxPlugin(RxDBReplicationGraphQLPlugin)
addRxPlugin(RxDBAjvValidatePlugin)
addRxPlugin(RxHasuraPlugin)
addPouchPlugin(require('rxdb/plugins/migration'))
addRxPlugin(require('rxdb/plugins/leader-election'))
addRxPlugin(require('rxdb/plugins/update'))
addPouchPlugin(require('rxdb/plugins/query-builder'))
if (process.env.NODE_ENV === 'development')
addPouchPlugin(require('rxdb/plugins/dev-mode'))
// * IMPORTANT: Do not use addRxPlugin to add pouchdb adapter, instead use addPouchPlugin
if (persist) addPouchPlugin(require('pouchdb-adapter-idb'))
else addPouchPlugin(require('pouchdb-adapter-memory'))
const settings: RxDatabaseCreator = {
name,
password,
multiInstance: false, // ! Causes errors when set to true. See notice in https://rxdb.info/leader-election.html
eventReduce: true, // <- eventReduce (optional, default: true))
options: {
url
},
storage: getRxStoragePouch(persist ? 'idb' : 'memory')
}
const db = (await createRxDatabase<DatabaseCollections>(
settings
)) as unknown as Database
debug('db', `created: ${settings.name}`)
if (process.env.NODE_ENV === 'development' || process.env.DEBUG)
window['db'] = db // write to window for debugging
// * When being connected, browse the roles and create table info accordingly
db.isAuthenticated$
.pipe(
distinctUntilChanged(),
filter((status) => status),
switchMap(() => db.isConfigReady$)
)
.subscribe(async (ready) => {
debug('db', 'first time authenticated. Is ready?', ready)
if (ready) addTableInfoCollection(db)
else await initConfigCollections(db)
})
db.isReady$
.pipe(
filter((ready) => ready && !!db.collections[TABLE_INFO_TABLE]),
switchMap(() => db.collections[TABLE_INFO_TABLE].find().$)
)
.subscribe((tables) => createContentsCollections(db, tables))
// * runs when db becomes leader
db.waitForLeadership().then(() => {
debug('db', 'took the leadership')
})
return db
}
Example #24
Source File: publish-list.tsx From bext with MIT License | 5 votes |
PublishList: FC = () => (
<div className="py-3">
{useObservableState(
useObservable(() =>
user$.pipe(
switchMap(({ status, user }) => {
switch (status) {
case 'loading':
return of(<Spinner />);
case 'complete':
const octokit = octokit$.getValue()!;
return timer(0, REFRESH_DURATION).pipe(
switchMap(() =>
from(
octokit.paginate(octokit.search.issuesAndPullRequests, {
q: `is:pr author:${user?.login} repo:${packageJson.metaRepository.owner}/${packageJson.metaRepository.repo}`,
sort: 'created',
order: 'desc',
}),
).pipe(
map((items) => (
<>
<Banner current={Date.now()} empty={!items.length} />
{items.length ? (
<List
items={items}
onRenderCell={(item) => <PrItem item={item!} />}
/>
) : null}
</>
)),
retry(2),
catchError(() =>
of(<div className="text-center">出错了...</div>),
),
),
),
);
default:
return of(
<div className="text-center">
<LoginLink /> 后查看发布历史
</div>,
);
}
}),
startWith(<Spinner />),
),
),
) || null}
</div>
)
Example #25
Source File: rxjsResourceStub.ts From slickgrid-universal with MIT License | 5 votes |
switchMap<T, O extends ObservableInput<any>>(project: (value: T, index: number) => O): OperatorFunction<T, ObservedValueOf<O>> {
return switchMap(project);
}
Example #26
Source File: rxjs.resource.ts From slickgrid-universal with MIT License | 5 votes |
/** Projects each source value to an Observable which is merged in the output Observable, emitting values only from the most recently projected Observable. */
switchMap<T, O extends ObservableInput<any>>(project: (value: T, index: number) => O): OperatorFunction<T, ObservedValueOf<O>> {
return switchMap(project);
}
Example #27
Source File: toc-container.directive.ts From alauda-ui with MIT License | 5 votes |
ngAfterContentInit() {
const actived$ = this._scrollTop$
.pipe(
startWith(this.scrollTop),
debounceTime(200),
map(scrollTop =>
this._contents.reduce(
this.isScrollEnd
? this.getMaxContent.bind(this)
: this.getMinContent(scrollTop),
),
),
map(actived => actived.auiTocContent),
)
.pipe(
tap(actived => {
this._contents.forEach(content => {
content.active = actived === content.auiTocContent;
});
this.cdr.detectChanges();
}),
);
const scrollTween$ = this._scrollTo$.pipe(
switchMap(name => {
const target = this._contents.find(
content => content.auiTocContent === name,
);
if (!target) {
return EMPTY;
}
const destination = this.getOffsetTop(target.nativeElement);
const start = performance.now();
const source = this.scrollTop;
const duration = 500;
return of(0).pipe(
observeOn(animationFrameScheduler),
repeat(),
map(() => (performance.now() - start) / duration),
takeWhile(t => t < 1),
endWith(1),
map(t => t * t * t),
map(t => source * (1 - t) + destination * t),
);
}),
takeUntil(this._onDestroy$),
);
this._subs.push(
actived$.subscribe(this.activedChange),
scrollTween$.subscribe(tweenValue => {
this.scrollTop = tweenValue;
}),
);
}
Example #28
Source File: select.component.ts From alauda-ui with MIT License | 5 votes |
override ngAfterContentInit() {
super.ngAfterContentInit();
this.selectedOption$ = combineLatest([
(
this.contentOptions.changes as Observable<QueryList<OptionComponent<T>>>
).pipe(
startWith(this.contentOptions),
switchMap(options =>
combineLatest(options.map(option => option.selected$)).pipe(
startWith(null as void),
map(() => options.find(option => option.selected)),
distinctUntilChanged(),
switchMap(option =>
option
? combineLatest([
option.value$,
option.label$,
option.labelContext$,
]).pipe(
map(([value, label, labelContext]) => ({
value,
label,
labelContext,
})),
)
: of(null as void),
),
),
),
),
this.model$,
]).pipe(
map(([option, value]) =>
option
? {
label:
option.label ||
this.labelFn?.(option.value) ||
coerceString(this.trackFn(option.value)),
// https://github.com/angular/angular/issues/24515
labelContext: {
...(option.labelContext as Record<string, unknown>),
},
}
: {
label: this.labelFn?.(value) || coerceString(this.trackFn(value)),
},
),
publishRef(),
);
this.hasSelected$ = this.selectedOption$.pipe(
map(({ label }) => !!label),
publishRef(),
);
}
Example #29
Source File: multi-select.component.ts From alauda-ui with MIT License | 5 votes |
override ngAfterContentInit() {
super.ngAfterContentInit();
this.selectedOptions$ = combineLatest([
this.model$,
(
this.contentOptions.changes as Observable<QueryList<OptionComponent<T>>>
).pipe(
startWith(this.contentOptions),
switchMap((options: QueryList<OptionComponent<T>>) =>
options.length > 0
? combineLatest(
options.map(option =>
combineLatest([
option.value$,
option.label$,
option.labelContext$,
option.disabled$,
]).pipe(
map(([value, label, labelContext, disabled]) => ({
value,
label,
labelContext,
disabled,
})),
),
),
)
: of([] as Array<SelectFilterOption<T>>),
),
),
]).pipe(
map(([values, options]) =>
values
.map(value => {
const option = options.find(
option => this.trackFn(option.value) === this.trackFn(value),
);
return option
? {
label:
option.label || coerceString(this.trackFn(option.value)),
labelContext: option.labelContext,
value: option.value,
disabled: option.disabled,
}
: {
label:
this.labelFn?.(value) || coerceString(this.trackFn(value)),
value,
};
})
// sort disabled options as first
.sort((a, b) => {
if (a.disabled) {
return -1;
}
if (b.disabled) {
return 1;
}
return 0;
}),
),
publishRef(),
);
}