Last active
November 13, 2019 03:08
-
-
Save tabishiqbal/fa3c69c1dc2f9a0e2f985b6e04dcdf7f to your computer and use it in GitHub Desktop.
How to submit a form in Vue via Rails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="lg:w-4/5 w-full"> | |
<form method="post" v-on:submit.prevent="submitForm"> | |
<div class="bg-white py-5 px-6 mb-6 rounded shadow"> | |
<div class="pb-8"> | |
<div class="text-base font-medium">General Information</div> | |
</div> | |
<div class="flex flex-wrap -mx-3 mb-6"> | |
<div class="w-full md:w-1/2 px-3 mb-6 md:mb-0"> | |
<label class="block uppercase tracking-wide text-grey-darker text-xs mb-2" for="tool-model"> | |
Model | |
</label> | |
<input | |
name="post[name]" | |
v-model="post.name" | |
class="block w-full form-control" | |
type="text" | |
placeholder="Some post info" | |
v-validate="'required'" | |
:class="{'border border-red': errors.has('post[name]')}" | |
> | |
<span class="text-red" v-show="errors.has('post[name]')">Name is required</span> | |
</div> | |
</div> | |
<div class="flex flex-wrap -mx-3 mb-6"> | |
<div class="w-full md:w-1/2 px-3"> | |
<label class="block uppercase tracking-wide text-grey-darker text-xs mb-2" for="brand"> | |
Options Example | |
</label> | |
<div class="relative"> | |
<select name="post[option]" class="form-control select2-selection" v-model="selectedOption" v-validate="'required'" :class="{'border border-red': errors.has('post[option]')}"> | |
<option disabled value="">Select an option</option> | |
<option v-for="(option, index) in options" :key="index" v-bind:value="option">{{ option.name }}</option> | |
</select> | |
<div class="pointer-events-none absolute pin-y pin-r flex items-center px-2 text-grey-darker"> | |
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/></svg> | |
</div> | |
</div> | |
<span class="text-red" v-show="errors.has('post[option]')">Please select an option</span> | |
</div> | |
</div> | |
</div> | |
<div class="bg-white py-5 px-6 mb-6 rounded shadow"> | |
<div class="pb-8"> | |
<div class="text-base font-medium">Upload Image</div> | |
</div> | |
<div class="flex flex-wrap -mx-3 mb-6"> | |
<div class="w-full px-3 mb-6 md:mb-0"> | |
<input | |
name="post[image]" | |
id="post_image" | |
accept="image/*" | |
type="file" | |
data-direct-upload-url="/rails/active_storage/direct_uploads" | |
direct_upload="true" | |
@change="onImageSelected" | |
/> | |
</div> | |
</div> | |
</div> | |
<div class="flex justify-end"> | |
<button @click.prevent="cancel" class="text-black px-8 ml-2 focus:outline-none hover:underline">Cancel</button> | |
<button v-if="!loading" @click.prevent="submitForm" class="btn-primary-dark text-white px-8 ml-2">Save</button> | |
<button v-if="loading" class="btn-primary-dark text-white px-8 ml-2">Saving...</button> | |
</div> | |
</form> | |
</div> | |
</template> | |
<script> | |
import axios from 'axios'; | |
import VeeValidate from 'vee-validate'; | |
export default { | |
props: { | |
post: Object, | |
required: true | |
}, | |
data() { | |
return { | |
loading: false, | |
selectedImage: '', | |
selectedOption: '', | |
} | |
}, | |
methods: { | |
cancel() { | |
window.location.href = '/posts'; | |
}, | |
onImageSelected(event) { | |
this.selectedImage = event.target.files[0]; | |
this.selectedImageValue = 'post.cached_image_data'; | |
}, | |
submitForm() { | |
this.$validator.validate().then(result => { | |
this.loading = true; | |
let formData = new FormData(); | |
formData.append('post[name]', this.post.name) | |
formData.append('post[option]', this.selectedOption) | |
// below are examples of passing null values so you don't have empty strings in your table | |
if (this.selectedImage) { | |
formData.append('post[image]', this.selectedImage) | |
} | |
axios.post('/posts.json', formData) | |
.then(resp => { | |
if (resp) { | |
let id = resp.data.public_uid; | |
window.location.href = `/posts/${id}` | |
} | |
}) | |
.catch((error) => { | |
let errors = error.response.data; | |
let that = this; | |
_.forEach(errors, function(value, key) { | |
that.errorMsg = _.capitalize(key) + ' ' + value | |
}); | |
this.loading = false; | |
}); | |
}); | |
this.loading = false; | |
} | |
} | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="mx-8 h-64px my-3"> | |
<div class="pb-12"> | |
<div class="text-2xl py-4">Add New Tool</div> | |
<% if @post.errors.any? %> | |
<% @post.errors.full_messages.each do |message| %> | |
<li><%= message %></li> | |
<% end %> | |
<% end %> | |
<add-post | |
:current-account="<%= current_user.account.id.to_json %>" # you can pass current account as well if you need it! | |
:post="<%= @post.to_json %>" | |
> | |
</add-post> | |
</div> | |
</div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment