UNPKG

vue-easy-rest

Version:

Advanced model layer for a VueJS app with a REST API

139 lines (94 loc) 6.73 kB
# vue-easy-rest by @Destygo ## What is vue-easy-rest Vue-easy-rest is a NPM package for VueJs for managing data served by a CRUD REST API. ## Why we created it We created vue-easy-rest because existing packages did not fit our needs : - HTTP clients (VueResource, Axios, ..) : They are good at providing functions to read/write a data, but they return plain objects, for which all the business logic of maintaining them must be handeled manually. - Model vue packages (vue-model, vue-mc, ...) or wrappers around other collection based packages (Backbone collections/models, ...) : They force us to maintain a descriptive state of the data and the relations in the front-end, which has to be in implicit sync with the backend. Moreover, most of them do not actually provide automatic gestion of relations between resources (Backbone schema is an exception, but is not easily compatible with VueJS). What we want is to have a model layer which adresses these issues : 1. We want to READ a "high level" resource in one chunck (with nested resources inside it). This enables us to retrieve a form without having to make several requests and reconnect the results together. 2. We want to be able to UPDATE/CREATE/DESTROY each resource individually, regardless of how that resource was read alone or as being nested in a "bigger" resource. 3. We want to be able to UPDATE/CREATE/DESTROY *links* between resources without having to know in the front-end how the link is actually represented in the database (for instance, we use polymorphic tables for some relationships, which require a slightly different data than just `[key]_id`, but VueJS should not have to care about that). 4. We want to be able to do all of that without knowing in advance the structure of the data (if the structure of the data changes, we need to update the backend and the components of the VM layer only, NOT the model layer, NOT the update logic) 5. We want objects exposed by our model layer to behave like plain objects and be as close as possible to 'pure state', so we can use them directly and very easily in our templating. ## NPM Package https://www.npmjs.com/package/vue-easy-rest # Core concepts They are 2 main classes you will work with with vue-easy-rest : `ResourceType` and `Resource`. A `Resource` represents an individual object in the API, and a `ResourceType` is just a collection of resources. # How to use ## `ResourceType` The `ResourceType` (or `Collection`), is a list of items representing resources in the API (and most of the time lines in the database). ### Declare a `ResourceType` The constructor of `ResourceType` takes two parameters : * `route` _(string)_: URL of the collection (absolute or relative) * `options` _(Object, optional)_: Accepted keys => - `scope` : The scope of the collection, which is an object of parameters that will be sent to the API when getting the collection on the index route. No parameters if left empty. - `autosaveDisabled` : Boolean to trigger off the autosave functionanlity (default : `false`) Examples : ```js answers = new ResourceType(`${window.location.origin}/answers`, { scope: {by_machine_node: 13} }) livechecks = new ResourceType(`/vue_api/livechecks`, { autosaveDisabled: true }) ``` ### Get the list of items in a collection The method `fetch` of a `ResourceType` makes a `GET` HTTP call on the index route of the collection. Upon getting a response, all local resources will be erased and replaced by the result of the request. Examples : * With async/await : ```js await answers.fetch() try { await livechecks.fetch() } catch (e) { console.warn('Livechecks unavailable') } ``` * With promises : ```js answers.fetch().then(reponse => { etc... }) livechecks.fetch().then(reponse => { etc... }).catch(err => { console.warn('Livechecks unavailable') }) ``` ### Access the list of items of a collection Examples : * `answers.models` (returns a javascript Array of `Resource`) * `for (let answer of answers.models)` * `<div v-for="answer of answers.models" :key="answer.id">` ### Create a new object (high level resource) Examples : * `let instance = await instances.create({name: "New instance"})` * `let case_statement = await case_staments.create({name: "My super case statement", answer_id: 12})` ### Create a new object (nested sub-resource) Example : `let input = await answers.inputs.push({name: "My super input"})` ## `Resource` ### Test whether the data of a Resource has been loaded or not When fetching a `ResourceType`, for each resource, we only get the data that the index route sends. Most of the time, the individual `GET` route of a resource will send more information which is not sent in the index to prevent the response from being too big. To test whether the resource has been individually loaded or not : `answer.fullyLoaded()` (returns uan boolean) ### Fetch a resource Exemple : `await answer.fetch()` ### Delete a resource Exemples : * `await answer.delete()` * `await answer.destroy()` (exact same result, `destroy` is just an alias for `delete`) *Pro tip* : Be careful not to use `.delete()` in the template of a vue component. You could be surprised. Now I know you will try. Go ahead ### Set a resource data Exemples : * `answer.name = 'New name'` * `answer.inputs[2].reference = 'other'` * `<input v-model="answer.name">` `PUT` requests are automatically performed by vue-easy-rest, except if the `autosaveDisabled` option has been declared. In that case, the `saveAll` method will force saving the object with all its children. ### Call a custom endpoint `Resource` and `ResourceType` provide a `call` method that enable to make a call to a custom non-CRUD route Exemples : * `answer.call('check_integrity', 'GET', { anAdditionalParam: 42 }` * `(new ResourceType('instances')).call('all_available_languages', 'GET')` * `imageTemplate.call('deploy', 'PUT')` ### Fetch a resource without fetching the collection Sometimes, you already know which resource you need, but you don't need to actually perform a `GET` to the index of that resource and THEN fetch the resource individually. Exemples : ```js let answers = new ResourceType('/vue_api/answers'); let answer = answers.createModel({id: 12}); await answer.fetch(); ``` `createModel` locally pushes a new resource in the `ResourceType` with the given attributes. Simillarily, there is a local `findOrCreateModel`. ## Vue-mc Now that you know more about vue-easy-rest, it's time for you to know that it's a wrapper around vue-mc. `Resource` is an extension of `Model` and `ResourceType` is an extension for `Collection`. That means you also have access to methods provided by vue-mc in their documentation : http://vuemc.io/#introduction