rxjs#distinctUntilChanged TypeScript Examples
The following examples show how to use
rxjs#distinctUntilChanged.
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: 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 #2
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 #3
Source File: tab-context.service.ts From alauda-ui with MIT License | 6 votes |
constructor(
@Optional()
@SkipSelf()
readonly _parent: TabContextService,
) {
this.active$ = (
_parent
? combineLatest([_parent.active$, this.active$$]).pipe(
map(([a, b]) => a && b),
)
: this.active$$
).pipe(distinctUntilChanged());
}
Example #4
Source File: form.directive.ts From alauda-ui with MIT License | 5 votes |
labelWidth$: Observable<string> = this.labelWidth$$
.asObservable()
.pipe(distinctUntilChanged());
Example #5
Source File: form.directive.ts From alauda-ui with MIT License | 5 votes |
labelPosition$: Observable<LabelPosition> = this.labelPosition$$
.asObservable()
.pipe(distinctUntilChanged());
Example #6
Source File: form.directive.ts From alauda-ui with MIT License | 5 votes |
emptyAddon$: Observable<boolean> = this.emptyAddon$$
.asObservable()
.pipe(distinctUntilChanged());
Example #7
Source File: radio-group.component.ts From alauda-ui with MIT License | 5 votes |
size$: Observable<RadioSize> = this.size$$
.asObservable()
.pipe(distinctUntilChanged());
Example #8
Source File: radio-group.component.ts From alauda-ui with MIT License | 5 votes |
isPlain$: Observable<boolean> = this.isPlain$$
.asObservable()
.pipe(distinctUntilChanged());
Example #9
Source File: radio-group.component.ts From alauda-ui with MIT License | 5 votes |
name$: Observable<string> = this.name$$
.asObservable()
.pipe(distinctUntilChanged());
Example #10
Source File: fixed-size-table-virtual-scroll-strategy.ts From alauda-ui with MIT License | 5 votes |
scrolledIndexChange = this._indexChange.pipe(distinctUntilChanged());
Example #11
Source File: option.component.ts From alauda-ui with MIT License | 5 votes |
constructor(
private readonly cdr: ChangeDetectorRef,
@Inject(forwardRef(() => BaseSelect))
select: any, // FIXME: workaround temporarily
) {
this.isMulti = select.isMulti;
this.select = select;
this.selected$ = combineLatest([this.select.values$, this.value$$]).pipe(
map(([selectValue, selfValue]) =>
selectValue
?.map(this.select.trackFn)
.includes(this.select.trackFn(selfValue)),
),
distinctUntilChanged(),
tap(selected => {
this.selected = selected;
}),
publishRef(),
);
this.size$ = this.select.size$.pipe(
tap(size => {
this.size = size;
}),
);
this.visible$ = combineLatest([
this.select.filterString$,
combineLatest([this.label$, this.value$, this.labelContext$]).pipe(
map(([label, value, labelContext]) => ({ label, value, labelContext })),
),
]).pipe(
map(([filterString, option]) =>
this.select.filterFn(filterString, option),
),
distinctUntilChanged(),
tap(visible => {
this.visible = visible;
}),
publishRef(),
);
}
Example #12
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 #13
Source File: theme.service.ts From alauda-ui with MIT License | 5 votes |
readonly currentTheme$ = this.currentAppTheme$$
.asObservable()
.pipe(distinctUntilChanged());
Example #14
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 #15
Source File: state.ts From platyplus with MIT License | 5 votes |
addStateToDatabasePrototype = (proto: Database) => {
proto.isConfigReady$ = new Observable((subscriber) => {
readyTables.subscribe((tables) =>
subscriber.next(CONFIG_TABLES.every((name) => tables.includes(name)))
)
}).pipe(distinctUntilChanged<boolean>())
proto.isReady$ = new Observable((subscriber) => {
readyTables.subscribe((tables) =>
subscriber.next(PLATYPLUS_TABLES.every((name) => tables.includes(name)))
)
}).pipe(distinctUntilChanged<boolean>())
proto.jwt$ = new BehaviorSubject<string | null>(null)
proto.isAdmin$ = new BehaviorSubject<boolean>(false)
proto.isAuthenticated$ = new BehaviorSubject<boolean>(false)
proto.setAuthStatus = (
status: boolean | null,
newJwt: string | null,
admin: boolean
) => {
debug('db', 'setAuthStatus', status, !!newJwt)
if (typeof status === 'boolean') {
proto.isAuthenticated$.next(status)
proto.jwt$.next(newJwt)
proto.isAdmin$.next(status ? admin : false)
}
}
proto.isConnected$ = merge(
of(null),
fromEvent(window, 'online'),
fromEvent(window, 'offline')
).pipe(map(() => navigator.onLine))
proto.stop = async function (this: Database) {
this.setAuthStatus(false, null, false)
readyTables.next([])
for (const collection of Object.values(this.collections)) {
await collection.destroy()
}
}
}
Example #16
Source File: replicator.ts From platyplus with MIT License | 4 votes |
createReplicator = async <T>(
collection: RxCollection<T, unknown> & { replicator: Replicator<T> },
options: ReplicatorOptions<T>
): Promise<Replicator<T>> => {
const db = collection.database as unknown as Database
const headers = () =>
createHeaders(options.role, db.jwt$.getValue(), options.substituteRole)
const resetWs = () => {
if (wsClient) {
wsClient.unsubscribeAll()
wsClient.close()
}
}
let state: RxGraphQLReplicationState<T> | undefined
let wsClient: SubscriptionClient | undefined
let jwtSubscription: Subscription | undefined
let errorSubscription: Subscription | undefined
const setupGraphQLReplication = async () => {
const replicationState = collection.syncGraphQL({
url: options.url,
headers: headers(),
pull: {
queryBuilder: options.pull.queryBuilder,
modifier: options.pull.modifier
},
push: {
batchSize: options.batchSize || DEFAULT_BATCH_SIZE,
queryBuilder: options.push?.queryBuilder,
modifier: options.push?.modifier
},
live: true,
liveInterval: 1000 * 60 * 10, // 10 minutes
deletedFlag: DELETED_COLUMN,
waitForLeadership: true // defaults to true
})
// replicationState.initialReplicationComplete$.subscribe((active) =>
// active
// ? setReplicationReady(collection.name)
// : setReplicationBusy(collection.name)
// )
replicationState.canceled$.subscribe(() => {
debug(collection.name, `replication cancelled`)
jwtSubscription?.unsubscribe()
errorSubscription?.unsubscribe()
startOption?.()
resetWs()
})
return replicationState
}
const initWsSubscription = () => {
debug(collection.name, `initGraphQLSubscription`)
resetWs()
wsClient = new SubscriptionClient(httpUrlToWebSockeUrl(options.url), {
reconnect: true,
connectionParams: {
headers: headers()
},
timeout: 1000 * 60,
reconnectionAttempts: 10000,
inactivityTimeout: 10 * 1000,
lazy: true
})
const request = wsClient.request({
query: options.subscription.query,
variables: options.subscription.variables?.()
})
request.subscribe({
next: ({ data, ...rest }) => {
if (data) {
const contents = Object.values(data)[0]
debug(collection.name, `WS request emitted`, contents)
options.onWsReceive?.(contents)
state?.run()
} else {
debug(collection.name, `WS request emitted, but no data`, rest)
}
},
error: (error) => {
warn(collection.name, `WS request error`, error)
}
})
wsClient.onReconnected(() => {
info(collection.name, `WS reconnected`)
})
wsClient.onConnected(() => {
debug(collection.name, `WS connected`)
})
wsClient.onDisconnected(() => {
debug(collection.name, `WS disconnected`)
})
wsClient.onReconnecting(() => {
info(collection.name, `WS reconnecting`)
})
wsClient.onError((err) => {
info(collection.name, ` WS error`, err)
})
}
let startOption: undefined | (() => void)
const start = async (): Promise<void> => {
state = await setupGraphQLReplication()
startOption = options.onStart?.()
errorSubscription = state.error$.subscribe((data) => {
warn(collection.name, `replication error`, data)
})
jwtSubscription = db.jwt$.subscribe((jwt) => {
debug(collection.name, `new jwt received`)
if (jwt) {
state.setHeaders(headers())
initWsSubscription()
} else debug(collection.name, `new jwt received was null`)
})
state.awaitInitialReplication().then(() => {
debug(collection.name, `awaitInitialReplication OK`)
})
}
const stop = async (): Promise<void> => {
debug(collection.name, `stop replication`)
await state?.cancel()
}
const destroy = async (): Promise<void> => {
// TODO check if it is really solved: https://gitter.im/pubkey/rxdb?at=61391ec763dca818914c246e
// this should be part of _prepare() in https://github.com/pubkey/rxdb/blob/master/src/plugins/replication-graphql/index.ts
await setLastPullDocument(state.collection, state.endpointHash, null)
await setLastPushSequence(state.collection, state.endpointHash, 0)
await stop()
}
combineLatest([db.isConnected$, db.isAuthenticated$])
.pipe(
map(([connected, authenticated]) => connected && authenticated),
distinctUntilChanged<boolean>()
)
.subscribe(async (ok) => {
debug(collection.name, `auth/connection status change`, ok)
if (ok) await start()
else await stop()
})
collection.replicator = { start, stop, destroy, state }
return collection.replicator
}