Skip to content

Commit beb1ecb

Browse files
committed
feat(vuexfire): add wait option
1 parent 85d2ac8 commit beb1ecb

File tree

5 files changed

+59
-12
lines changed

5 files changed

+59
-12
lines changed

packages/documentation/docs/api/vuexfire.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,14 @@ Can contain the following properties:
6868

6969
- `maxRefDepth`: How many levels of nested references should be automatically bound. Defaults to 2, meaning that References inside of References inside of documents bound with `bindFirestoreRef` will automatically be bound too.
7070
- `reset`: Allows to define the behavior when a previously bound reference is unbound. Defaults to `true`, which resets the property in the vue instance to `null` for documents and to an empty array `[]` for collections. It can also be set to a function returning a value to customize the value set. Setting it to `false` will keep the data as-is when unbinding.
71+
- `wait`: Waits for the binding to be completely resolved before setting the value in data. This will also force `reset: false` unless `reset` is provided as a function.
7172
- `serialize`: a function to provide a custom serialization strategy when a
7273
document from firebase is set on the Vue instance. This allows to customize
7374
the `id` key, to transform data, etc. See [Vuefire plugin options for examples](./vuefire.md#options-serialize)
7475

7576
### unbindFirestoreRef
7677

77-
`unbindFirestoreRef(key: string): void`
78+
`unbindFirestoreRef(key: string, reset?: FirestoreOptions['reset']): void`
7879

7980
Unsubscribes from updates for a given key.
8081

@@ -112,12 +113,13 @@ Returns a promise that is resolved once the data is fetched and the state is in
112113
Can contain the following properties:
113114

114115
- `reset`: Allows to define the behavior when a previously bound reference is unbound. Defaults to `true`, which resets the property in the vue instance to `null` for properties bound as objects and to an empty array `[]` for properties bound as arrays. It can also be set to a function returning a value to customize the value set. Setting it to `false` will keep the data as-is when unbinding.
116+
- `wait`: Waits for the binding to be completely resolved before setting the value in data. This will also force `reset: false` unless `reset` is provided as a function.
115117
- `serialize`: a function to provide a custom serialization strategy when a
116118
document from firebase is set on the Vue instance. This allows to customize
117119
the `id` key, to transform data, etc. See [Vuefire plugin options for examples](./vuefire.md#options-serialize-2)
118120

119121
### unbindFirebaseRef
120122

121-
`unbindFirebaseRef(key: string): void`
123+
`unbindFirebaseRef(key: string, reset?: RTDBOptions['reset']): void`
122124

123125
Unsubscribes from updates for a given key.

packages/vuexfire/__tests__/firestore.spec.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Vuex from 'vuex'
22
import { vuexfireMutations, firestoreAction } from '../src'
33
import { db, tick, Vue, delayUpdate } from '@posva/vuefire-test-helpers'
44
import { firestore } from 'firebase'
5+
import { FirestoreOptions } from '@posva/vuefire-core/dist/packages/@posva/vuefire-core/src'
56

67
Vue.use(Vuex)
78

@@ -34,9 +35,14 @@ describe('firestoreAction', () => {
3435
},
3536
})
3637

37-
const setItems = (collection: firestore.CollectionReference | firestore.Query) =>
38+
const setItems = (
39+
collection: firestore.CollectionReference | firestore.Query,
40+
options?: FirestoreOptions
41+
) =>
3842
// @ts-ignore
39-
store.dispatch('action', ({ bindFirestoreRef }) => bindFirestoreRef('items', collection))
43+
store.dispatch('action', ({ bindFirestoreRef }) =>
44+
bindFirestoreRef('items', collection, options)
45+
)
4046
const setItem = (document: firestore.DocumentReference) =>
4147
// @ts-ignore
4248
store.dispatch('action', ({ bindFirestoreRef }) => bindFirestoreRef('item', document))
@@ -168,6 +174,18 @@ describe('firestoreAction', () => {
168174
expect(store.state.items).toEqual([{ text: 'foo' }, { text: 'foo' }])
169175
})
170176

177+
it('can unbind without resetting', async () => {
178+
await setItems(collection)
179+
await collection.add({ text: 'foo' })
180+
await store.dispatch(
181+
'action',
182+
// @ts-ignore
183+
({ unbindFirestoreRef }) => unbindFirestoreRef('items', false)
184+
)
185+
186+
expect(store.state.items).toEqual([{ text: 'foo' }])
187+
})
188+
171189
it('does not throw there is nothing to unbind', async () => {
172190
await setItems(collection)
173191
await store.dispatch(
@@ -197,4 +215,26 @@ describe('firestoreAction', () => {
197215
expect(this._vm).toBeInstanceOf(Vue)
198216
})
199217
})
218+
219+
it('does not reset if wait: true', async () => {
220+
// @ts-ignore
221+
const col2: firestore.CollectionReference = db.collection()
222+
await setItems(collection)
223+
await collection.add({ text: 'foo' })
224+
const p = setItems(col2, { wait: true, reset: true })
225+
expect(store.state.items).toEqual([{ text: 'foo' }])
226+
await p
227+
expect(store.state.items).toEqual([])
228+
})
229+
230+
it('wait + reset can be overriden with a function', async () => {
231+
// @ts-ignore
232+
const col2: firestore.CollectionReference = db.collection()
233+
await setItems(collection)
234+
await collection.add({ text: 'foo' })
235+
const p = setItems(col2, { wait: true, reset: () => ['foo'] })
236+
expect(store.state.items).toEqual(['foo'])
237+
await p
238+
expect(store.state.items).toEqual([])
239+
})
200240
})

packages/vuexfire/__tests__/rtdb.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ describe('RTDB: firebaseAction', () => {
140140
})
141141
})
142142

143-
it('can prevent resetting the value when unbinding', async () => {
143+
it('can unbind without resetting', async () => {
144144
await setItem(document)
145145
document.set({ text: 'foo' })
146146
await store.dispatch(

packages/vuexfire/src/firestore.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ function bind(
5151

5252
// unbind if ref is already bound
5353
if (key in sub) {
54-
unbind(commit, key)
54+
unbind(
55+
commit,
56+
key,
57+
options.wait ? (typeof options.reset === 'function' ? options.reset : false) : options.reset
58+
)
5559
}
5660

5761
return new Promise((resolve, reject) => {
@@ -82,11 +86,11 @@ function bind(
8286
})
8387
}
8488

85-
function unbind(commit: CommitFunction, key: string) {
89+
function unbind(commit: CommitFunction, key: string, reset?: FirestoreOptions['reset']) {
8690
const sub = subscriptions.get(commit)
8791
if (!sub || !sub[key]) return
8892
// TODO dev check before
89-
sub[key]()
93+
sub[key](reset)
9094
delete sub[key]
9195
}
9296

@@ -148,9 +152,10 @@ export function firestoreAction<S, R>(
148152
// @ts-ignore
149153
ref,
150154
ops,
151-
options
155+
Object.assign({}, firestoreOptions, options)
152156
),
153-
unbindFirestoreRef: (key: string) => unbind(commit, key),
157+
unbindFirestoreRef: (key: string, reset?: FirestoreOptions['reset']) =>
158+
unbind(commit, key, reset),
154159
},
155160
payload
156161
)

packages/vuexfire/src/rtdb.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function bind(
3232
key: string,
3333
ref: database.Reference | database.Query,
3434
ops: OperationsType,
35-
options?: RTDBOptions
35+
options: RTDBOptions
3636
): Promise<database.DataSnapshot> {
3737
// TODO check ref is valid
3838
// TODO check defined in state
@@ -118,7 +118,7 @@ export function firebaseAction<S, R>(
118118
key: string,
119119
ref: database.Reference | database.Query,
120120
options?: RTDBOptions
121-
) => bind(state, commit, key, ref, ops, options),
121+
) => bind(state, commit, key, ref, ops, Object.assign({}, rtdbOptions, options)),
122122
unbindFirebaseRef: (key: string, reset?: RTDBOptions['reset']) =>
123123
unbind(commit, key, reset),
124124
},

0 commit comments

Comments
 (0)