# vue-computed-firestore

> Module to provide two-way binding between vue.js and Google firestore

Latest version **0.3.2** (published 2019-09-29) · ISC license · 0 weekly downloads

## Install

```sh
npm install vue-computed-firestore
pnpm add vue-computed-firestore
yarn add vue-computed-firestore
bun add vue-computed-firestore
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.3.2 |
| Published | 2019-09-29 |
| First published | 2019-08-23 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 6 |
| Unpacked size | 34.9 KB |
| Known vulnerabilities | 0 (+1 in 1 direct dependencies) |
| Install scripts | no |
| Author | nemovc |
| Maintainers | nemovc |
| Keywords | firestore, vue, binding |

## Links

- npm: https://www.npmjs.com/package/vue-computed-firestore
- Repository: https://bitbucket.org/nemovc/vue-computed-firestore
- Homepage: https://bitbucket.org/nemovc/vue-computed-firestore#readme
- npm.io page: https://npm.io/package/vue-computed-firestore

## Dependencies (6)

- [lodash.get](https://npm.io/package/lodash.get.md) ^4.4.2
- [lodash.set](https://npm.io/package/lodash.set.md) ^4.3.2
- [lodash.forown](https://npm.io/package/lodash.forown.md) ^4.4.0
- [lodash.isempty](https://npm.io/package/lodash.isempty.md) ^4.4.0
- [lodash.clonedeep](https://npm.io/package/lodash.clonedeep.md) ^4.5.0
- [lodash.clonedeepwith](https://npm.io/package/lodash.clonedeepwith.md) ^4.5.0

## Recent versions

- 0.3.2 (latest) — 2019-09-29
- 0.3.1 — 2019-09-28
- 0.2.0 — 2019-09-05
- 0.1.1 — 2019-08-30
- 0.1.0 — 2019-08-30
- 0.0.4 — 2019-08-23
- 0.0.3 — 2019-08-23
- 0.0.2 — 2019-08-23
- 0.0.1 — 2019-08-23

## README

# vue-computed-firestore

Simple two-way(ish) binding of firestore docs and collections to vue computed properties.

## Install
```sh
npm install vue-computed-firestore
```

## Usage
Somewhere in your apps boot process
```js
  const VueComputedFirestore = require('vue-computed-firestore');
  Vue.use(VueComputedFirestore, {firebase: appFirebase});

```
Component
```html
<template>
  <h3>{{user.name}}</h3><br>
  <input v-model.lazy="user.bio" />
  <div v-for="(todo, key) in todos" :key="key" >
    {{todo.text}}
  </div>
</template>
```
```js
<script>
export default {
  data(){
    return {
      currentUserID: 'abc123',
    },
  },
  computedFirestore(){
    return {
      user: ['user', '$currentUserID'],
      todos: ['user', '$currentUserID', 'todos'],
    }
  },
}
```
In the above example, the `user` and `todos` defined within computedFirestore become reactive properties on the vue instance root (just like computed or data objects) and will update whenever the database changes.

## Options
Options can be passed to this module in multiple ways
 * As the second parameter to `Vue.use`
 * As a object with the key `$config` within the `computedFirestore()` return object
 * As an object at index 0 within a property path array

### Available options
 * `firebase` Root firebase object to read from (required param for `Vue.use`)
 * `baseName = '$fs'` Internal property added to Vue prototype. Only changeable during install. Only modify this if there are conflicts.
 * `definitionName = 'computedFirestore'` String name of function called to create bindings. Only changeable during install.
 * `includeKey = '$key'` Whether to include the `id` of a document, and it's keypath if included. Set to a falsy value to not include, otherwise it will be included as a non-enumerable property on the document.
 * `includeMetadata = '$metadata'` Whether to include document snapshot metadata, and it's keypath if included. Set to a falsy value to not include, otherwise it will be included as a non-enumerable property on the document.
 * `collectionsAsObject = true` Whether to return collections and queries as objects (using document id's as keys) or arrays.

 * `handlers = {}` See section below on handlers.


### Property paths
The core of this modules use comes in defining property paths. Property paths are an array (optionally starting with a `config` object) of strings (document and collection IDs), arrays (`where` queries) and objects (`orderBy` and `limit` clauses).

Reactivity is added through property interpolation. Any place that can accept a string can be made to accept a reactive object by providing a string beginning with `'$'` e.g., To retrieve a doc matching a computed, prop, or data value `id`, you can use a property path like `['user', '$id']`. [lodash.get](https://www.npmjs.com/package/lodash.get) is used internally to access this property, so dot-notated paths are acceptable.

 * **Documents & Collections**

    Fetching documents and collections by ID is done by passing a string containing the ID to fetch. This can obviously be nested as required.

    ```js
    ['users','$id','todos']`
    ```
     would fetch the todos collection on the current user document

 * **Where**

    Where-style queries are performed by using an array in the property path. The three elements of this array correspond to the three parameters in a firestore where query.

    ```js
    ['users', '$id', 'todos', ['due', '<', Date.now()], ['completed', '==', '$showCompleted'] ]
    ```
     would show the users todos that were due in the past either (depending on the value of `this.showCompleted` ) been completed or were not completed.

 * **OrderBy and Limit**

    OrderBy and limit clauses are performed by using an object in the property path. This object can have one or both of `orderBy` and `limit` keys. `limit` must be a number (or link to a reactive property which is a number), while `orderBy` can be a string (field name) or array (field name and ordering).

    ```js
    ['users', '$id', 'todos', ['completed', '==', false ]{ orderBy: ['due', 'asc'], limit: '$numberToShow'}]
    ```
     will only show `this.$numberToShow` uncompleted todos, order by the date they're due

 * **Per-property config**
  
    If the first element of the property path is an object, it is treated as a config object, which overwrites any global or component-scope config, but only for this property path.

    ```js
      [{includeKey: false}, 'users', '$id']
    ```
    would return the users document, but without the non-enumerable `$key` field included.

### Available operations

  Several firestore functions are made available.

  * **Document**

    `set`, `update` and `delete` are made available as non-enumerable methods on each document (`$set`, `$update` and `$delete` respectively).  
    ```js
    this.todos[completedID].$update({ completed: true });
    ```
    would mark a todo as completed. 

  * **Document property**
  
    Document properties can be used directly with `v-model`, which will trigger `$update` when changed. This can also be set programmatically.

    ```html
    <q-input v-model.lazy="user.bio">
    ```
    ```js
    changeName(newName) {
      this.user.name = newName;
    }
    ```
    Note that this functionality is not debounced - to reduce the number of writes you perform, you may add debouncing functionality yourself.
    
    You may also use v-model directly with documents - both documents retrieved directly and those accessed through collections. 
    ```js
      computedFirestore(){
        user: ['users', '$id'];
      },
      methods: {
        setUser(name, age, bio){
          this.user = { name, age, bio };
        },
      },
    ```
    ```js
      computedFirestore(){
        users: ['users'],
      },
      methods: {
        updateUser(id, newUserDocument){
          this.users[id] = newUserDocument;
        },
      },
    ```
    Attempting to set a document which doesn't exist will create a new document.

  * **Collection**

    `add` is made available as a non-enumerable method `$add` on each collection (but not on queries or collections that have been ordered or limited)  
    ```js
    this.todos.$add({ completed: false, text: newTodoText, due: newTodoDueTimestamp });
     ```
    would add a new todo

### Handlers
  Handlers are added as subkeys of the option key `handlers`. If you pass a single handler to a hook, all previous (higher) handlers for that hook are removed for any descendant configs. If you pass an array (even just an array with one handler), all previous higher handlers will still be invoked. The available hooks are:

   * `error` Called whenever there is a firebase error. Receives the error as a parameter.
   * `once` Called on the first snapshot event after component `created` lifecycle hook.
   * `populated` Called when all properties have received their first snapshot event after component `created` lifecycle hook. Can only be registered at the install or component level.
   * `added`  Called whenever a document is added. Receives the new document(s) as a parameter. Only valid for collection-type bindings.
   * `removed` Called whenever a document is deleted. Recieves an array containing the ID's of the deleted documents. Only valid for collection-type bindings.
   * `modified` Called whenever a document is modified. Receives the new document(s) as a parameter.
   * `updated` Called whenever one of the previous three would be called. Receives the relevant document(s) as a parameter.
   * `changed` Called whenever the document or query ref changes - meaning this runs whenever one of the reactive variables you're depending on changes. Receives the relevant documents as a parameter.

  All of the above callbacks, when passing multiple documents (including collections or queries with only one document), will pass either an Object or Array depending on the value of `config.collectionsAsObject`.

---
_Source: https://npm.io/package/vue-computed-firestore · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
