Skip to content

Instantly share code, notes, and snippets.

@d1manson
Last active February 10, 2017 17:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d1manson/fd0b4d5b9c6c18622b7860b3cfaefbf9 to your computer and use it in GitHub Desktop.
Save d1manson/fd0b4d5b9c6c18622b7860b3cfaefbf9 to your computer and use it in GitHub Desktop.
like polymer's ajax component
/*
Example basic usage is something like this:
<div id="vue-mount">
<vue-fetch endpoint="/example" :id="exampleId" :model="exampleModel"></vue-fetch>
{{exampleId}} {{exampleModel.thing}} {{exampleModel.other}}
</div>
<script>
new Vue({
el: "#vue-mount"
data: {
exampleId: "999",
exampleModel: { }
}
});
</script>
Whenever the id value is changed the model is populated with data from the server.
The model you provide should just be a plain object, and can be used as such.
The model includes the following special properties:
fetching - true during a request
fetchError - a string/object relating to the last change made to id
stale - true if the data in model does not correspond to data on the server for the given id.
this is true if the id is null, during the fetch and under the same conditions that fetchError is set.
Note that following a successful fetch, existing properties are overwritten, but no
values are deleted (if they were present in a previous fetch but not the current one).
Suggestions:
Could add a hook for custom parsing (like backbone). This would simply require a function call
before doing the setting.
Currently this only works for reading from the server, not writing to it..but you
could add a {deep: true} watch on model and save back to the server.
*/
import Vue from 'vue2';
Vue.component('vue-fetch', {
name: "vue-fetch",
template: "<div hidden>vue-fetch</div>",
props: {
endpoint: {type: String, required: true},
id: {type: String},
model: {type: Object},
baseURL: {type: String, default: window.API_URL}
},
mounted: function(){
this.augmentModel();
this.doFetch();
},
methods: {
doFetch: function(){
if(!this.model){
return;
}
this.model.stale = true;
this.model.fetchError = '';
if(!this.id){
this.model.fetching = false;
this.model.stale = true;
return;
}
this.model.fetching = true;
fetch(this.baseURL + this.endpoint + '/' + this.id)
.then(resp => {
if(resp.ok){
return resp.json();
} else {
throw {status: resp.status, statusText: resp.statusText};
}
})
.then(json => {
for(var k in json){
k in this.model ? this.model[k] = Object.freeze(json[k])
: this.$set(this.model, k, Object.freeze(json[k]));
}
this.model.fetching = false;
this.model.stale = false;
})
.catch(err => {
this.model.fetchError = err;
this.model.fetching = false;
});
},
augmentModel: function(){
if(!this.model){
return;
}
this.$set(this.model, 'fetching', false);
this.$set(this.model, 'fetchError', false);
this.$set(this.model, 'stale', true);
}
},
watch: {
model: function(){
this.augmentModel();
this.doFetch();
},
id: function(){
this.doFetch();
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment