How to add custom validation which calls an API in vuetify forms? - vuetify.js

I am trying to add custom validation to a form to test for duplicate entry.
How can I do it using only vuetify validation. I want to show a inline error message if the user input is duplicate.

Yes you can validate the name from customer input with api call and throw error to user, if the name already exist or duplicate name found
You can use rules property in vuetify text fields, it takes an array of functions and expect true(validation true, in your case name not exists) or string(if valdation false, name exists in db)
Here is the working codepen: https://codepen.io/chansv/pen/eYYdPzQ?editors=1010
<div id="app">
<v-app id="inspire">
<v-form
ref="form"
v-model="valid"
>
<v-text-field
v-model="name"
:counter="10"
:rules="[checkDuplicate, rules.required]"
label="Name"
required
></v-text-field>
<v-btn #click="submitbtn">submit</v-btn>
</v-form>
</v-row>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
valid:true,
name: '',
rules: {
required: v => !!v || 'this field is required',
}
}),
methods: {
checkDuplicate(val) {
// write your api call and return the below statement if it already exist
if (val == 'test') {
return `Name "${val}" already exist`;
} else {
return true;
}
},
submitbtn() {
this.$refs.form.validate();
},
},
})

Related

nuxt,js vue,js how to fetch data inside of table

i am new in vuetify and nuxt.js
i am getting data from database but i want to show that in vuetify table.
Laravel API Controller
public function businesslist() {
$businesslist = Business::paginate(2)->toJson(JSON_PRETTY_PRINT);
return response($businesslist);
}
}
MY Laravel API
Route::get('/businesslist', 'BusinessController#userlist')->name('businesslist');
MY Nuxt.js vue page
<template>
<v-card>
<v-card-title>
Nutrition
<v-spacer></v-spacer>
<v-text-field
v-model="search"
append-icon="mdi-magnify"
label="Search"
single-line
hide-details
></v-text-field>
</v-card-title>
<v-data-table
:headers="headers"
:items="businessuser"
:search="search"
></v-data-table>
</v-card>
</template>
<script>
export default {
data() {
return {
search: '',
headers: [{
text: 'Name',
value: 'name'
},
{
text: 'Mobile ',
value: 'mobile_number'
},
{
text: 'Location ',
value: 'location'
},
{
text: 'Join Date ',
value: 'registration_date'
},
{
text: 'Renewal Date ',
value: 'registration_renewal_date'
},
],
businessuser: [
],
}
},async asyncData({$axios}) { let {data} = await $axios.$get('/businesslist')
return {
businesslist: data
} },
}
}
</script>
You should use created event, in this event, call your businesslist API and in the response, you should assign received data to your businessuser vue js variable.
Let see here one example.
created () {
this.initialize();
},
methods: {
initialize () {
this.businessuser = businesslistApiCalling();
}
}
businesslistApiCalling(); is just an example you should call here the API method to receive Json data from the Server.

How to display records from Laravel via Vuetify v-data-table component

I have a project build in Laravel with Vue.js which work perfect statically, but I need convert it into dynamically to pull records from database table to v-data-table component.
I know Laravel and I know How these things works via Ajax/jQuery but I'm pretty new in Vue.js
Can someone explain to me how to display the results from the database in the v-data-table component.
Thanks.
Here is the Vue.js file:
<template>
<v-app>
<v-main>
<div>
<v-tab-item>
<v-card flat>
<v-card-text>
<v-card-title>
<v-spacer></v-spacer>
<v-text-field
v-model="search"
append-icon="mdi-magnify"
label="Search"
single-line
hide-details
></v-text-field>
</v-card-title>
<v-data-table
:headers="headers"
:items="items"
:items-per-page="5"
class=""
:search="search">
</v-data-table>
</v-card-text>
</v-card>
</v-tab-item>
</div>
</v-main>
</v-app>
</template>
<script>
export default {
data: () => ({
search: '',
items: [],
headers: [
{
text: '#',
align: 'start',
sortable: false,
value: 'id',
},
{ text: 'Name', value: 'name' },
{ text: 'Slug', value: 'slug' },
],
/*THIS IS A STATIC DATA*/
// items: [
// {
// id: 1,
// name: 'Test Name 1',
// slug: 'test-name-1',
// },
// {
// id: 2,
// name: 'Test Name 2',
// slug: 'test-name-2',
// },
// ],
/*THIS IS A STATIC DATA*/
}),
created () {
this.getItems();
},
methods: {
getItems() {
axios
.get('/test/vue')
.then((response) => {
this.items = response.data,
console.log(response.data)
})
.catch(error => console.log(error))
},
}
}
</script>
And Here is Blade file:
#extends('it-pages.layout.vuetify')
#section('content')
<div id="appContainer">
<software-template></software-template>
</div>
Output in the console is :
console.log
Response from axios is also Ok
response
My Controller :
public function showData()
{
$items = Category::select('id', 'name', 'slug')->where('order', 1)->get();
// dd($items);
return response()->json(['items' => $items]);
}
My route:
Route::get('test/vue', 'PagesController#showData');
console.log after changes axios lines
console-log
So there were multiple issues here:
The backend did you return a correct array
The frontend performed a post request instead of a get
The this context is not correct since you are using a function instead of arrow syntax
Make sure to look at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions and read about how this changes how this is elevated.
In your case, you need to change the code on the then part of your axios call:
.then((response) => {
this.items = response.data
})
I must to say that I solve the problem.
Problem was been in axios response.
Instead this.items = response.data I change to this.items = response.data.items and it work perfectly.
methods: {
getItems() {
axios
.get('/test/vue')
.then((response) => {
this.items = response.data.items
console.log(response.data.items)
})
.catch(error => console.log(error))
},
}

How to extract a <form> element from Vuetify's <v-form> component

I have a Vuetify form with a ref, like this
<v-form ref="form" method="post" #submit.prevent="handleSubmit">
Onto it I attached a default-preventing submit handler whose method is as follows:
window.fetch(`${this.$store.state.apiServer}/some-url`, {
method: 'post',
body: new FormData(this.$refs.form)
}).then(response => {
// Do stuff with the response
}).catch(() => {
// HCF
});
The problem is new FormData() only accepts a pure HTML <form> element, while this.$refs.form is a VueComponent. Is there a way I can grab the <form> from inside a <v-form>?
You can get the form element using this.$refs.form.$el
Here is the working codepen: https://codepen.io/chansv/pen/OJJOXPd?editors=1010
<div id="app">
<v-app id="inspire">
<v-form
ref="form"
v-model="valid"
lazy-validation
>
<v-text-field
v-model="name"
:counter="10"
:rules="nameRules"
label="Name"
required
></v-text-field>
<v-text-field
v-model="email"
:rules="emailRules"
label="E-mail"
required
></v-text-field>
<v-btn type="submit" #click="formSubmit">submit</v-btn>
</v-form>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
valid: true,
name: '',
nameRules: [
v => !!v || 'Name is required',
v => (v && v.length <= 10) || 'Name must be less than 10 characters',
],
email: '',
emailRules: [
v => !!v || 'E-mail is required',
v => /.+#.+\..+/.test(v) || 'E-mail must be valid',
],
}),
methods: {
formSubmit() {
console.log(this.$refs.form.$el);
}
},
})

Vue component does not render and ignores props

I am having a problem with a Vue component which should just show a simple dialog, the component looks like this:
<template>
<v-layout row justify-center>
<v-dialog
v-model="show"
max-width="290"
:persistent="persistent"
>
<v-card>
<v-card-title class="headline grey lighten-2">{{header}}</v-card-title>
<v-card-text v-html="text">
{{text}}
</v-card-text>
<v-card-actions>
<v-layout>
<v-flex xs6 md6 lg6 class="text-xs-center">
<v-btn block
color="primary"
flat
#click="closeDialog(true)"
>
{{agree_button_text}}
</v-btn>
</v-flex>
<v-flex xs6 md6 lg6 class="text-xs-center">
<v-btn block
color="warning"
flat
#click="closeDialog(false)"
>
{{abort_button_text}}
</v-btn>
</v-flex>
</v-layout>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
export default {
props:
{
persistent:
{
type: Boolean,
required: false,
default: false
},
header:
{
type: String,
required: false,
default: ""
},
text:
{
type:String,
required: false,
default:""
},
abort_button_text:
{
type: String,
required: false,
default:"Avbryt"
},
agree_button_text:
{
type: String,
required: false,
default: "OK"
},
value:
{
}
},
data ()
{
return {
show: this.value
}
},
methods:
{
closeDialog:
function(retval)
{
this.show = false;
this.$emit('close-dialog-event',retval);
}
}
}
</script>
In app.js I have added the following:
require('./bootstrap');
import babelPolyfill from 'babel-polyfill';
import Vuetify from 'vuetify'
window.Vue = require('vue');
var vueResource = require('vue-resource');
window.socketIo = require('vue-socket.io');
Vue.use(vueResource);
Vue.use(Vuetify);
Vue.http.headers.common['X-CSRF-TOKEN'] = $('meta[name="csrf-token"]').attr('content');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('simple-dialog', require('./components/common/SimpleDialog.vue'));
And on the page where I use the component I have:
<div id="overview">
<simple-dialog show="true"
:header="dialog_header"
:text="dialog_message"
#close-dialog-event="display_dialog = false"></simple-dialog>
<v-app>
<v-content>
<v-container>
FOO AND BAR
</v-container>
</v-content>
</v-app>
</div>
I don't get any errors that the component is not loaded.
And if I try to change the name of the component in the app.js file and then try to load the component it throws an error that the component can not be found. So in others words it seems that it loads successfully. However, if I change the name of the props, e.g. changing
<simple-dialog show="true"
:header="dialog_header"
:text="dialog_message"
#close-dialog-event="display_dialog = false"></simple-dialog>
to
<simple-dialog show_bla="true"
:asdasd="dialog_header"
:asdasd="dialog_message"
#close-dialog-event="display_dialog = false"></simple-dialog>
it does not care. It does not even throw an error about that those props either does not exists or are invalid. The javascript used by the page:
var app = new Vue({
el: '#overview',
data:
{
display_dialog:true,
dialog_header:'',
dialog_message:'',
},
methods:
{
}
});
What could the problem be? Thanks for any help!
Well, When you're sending the value to the component and your prop show is initialized as an empty object.
replace
value: {}
to
value
or
the pass default value to false
value: {
type: Boolean
default: false
}
Hope this helps!

Laravel/vuejs Change boolean value from 0 to 1

I have a question I need to create a 2 factor authentication only now the value of a colum in the database will be set to true. He is default to false. I know the database adds this as tinyint so the value should be switched to 1.
So i have try something but didnt work.. im very new with laravel and vuejs. so its hard for me. I hope one of you can help me out of this struggle
My 2 factor vue. So you can see the v-switch thats the button..
<template>
<v-container class="user-form-lime" fluid grid-list-xl>
<v-form>
<v-layout row wrap>
<v-flex xs12 md6>
<v-switch v-model="tfaEnabled"
label="Tweefactor authenticatie"
name="tfaEnabled"
prepend-icon="lock"
#change="change" />
</v-flex>
<v-flex xs12 md6>
<v-text-field v-if="tfaEnabled"
v-model="google2fa.token"
label="Token"
:rules="[rules.required]"
type="text" />
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs12>
<v-btn color="success" #click="submit">
Opslaan
</v-btn>
</v-flex>
</v-layout>
</v-form>
</v-container>
</template>
<script>
export default {
name: 'UserForm2fa',
props: {
id: { type: Number, required: true }
},
data() {
return {
tfaEnabled: false,
google2fa: {
token: '',
},
rules: {
required: val => !!val || 'Dit veld mag niet leeg zijn',
}
};
},
methods: {
changeStatus() {
this.$emit( 'change', this.tfaEnabled );
},
submit() {
this.$emit('submit', this.token)
}
}
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
My controller function:
public function update2faStatus( Update2faStatus $request ) {
$user = User::findOrFail( $request->id );
$tfaEnabled = $request->input('tfaEnabled', false);
$user->tfaEnabled = $tfaEnabled;
$user->save();
}
and my Method for this:
toggle2fa( status ) {
this.$store.dispatch( 'update2faStatus' )
.then( () => this.$store.dispatch('addMessage', { success: true, content: ['2 Factor authenticatie is ingeschakeld.'] } ) )
.catch( error => this.$store.dispatch( 'addMessage', { success: false, content: error.response.data} ))
},
Its because you have not defined any method with name change(). #change event expects a method named change() in your code. But I guess you are trying to execute changeStatus() method when toggle button is changed. Changing your code to #change="changeStatus()" should fix the problem.

Resources