Validation Required in Vue - vue.js

I'm using vee-validate in my VueJS and I wonder how can i add a validation that if form.order == 1 then the it would be required
<ValidationProvider rules="v-if="form.order == 1 ? required: ''" v-slot="{ errors }" name="Entity">
<v-col md="4">
<v-text-field
label="First Name"
v-model="form.first_name"
outlined
hide-details="auto"
:error-messages="errors[0]"
></v-text-field>
</v-col>
</ValidationProvider>

May I suggest you move #Phymo's answer into a computed property so you keep your template clean, readable, and extendable. that way, you can swap the implementation anytime. i.e.
<template>
<ValidationProvider :rules="applyRules" v-slot="{ errors }" name="Entity">
<v-col md="4">
<v-text-field
label="First Name"
v-model="form.first_name"
outlined
hide-details="auto"
:error-messages="errors[0]"
></v-text-field>
</v-col>
</ValidationProvider>
</template>
<script>
export default {
data: () => ({
form: {
// form structure
}
}),
computed: {
applyRules() {
return this.form.order === 1 ? 'required' : ''
}
}
}
</script>

try this.
:rules="form.order == 1 ? 'required' : ''"

Related

Modify drop down value with preset value

I'm designing a form that can both used to create and edit something.
The form has a dropdown, which isn't initialized when created, but is set with a value when used for editing.
I want to be able to modify the value of the drop down, both for creating & updating, yet is only working when the mode is CREATE.
Here's my template:
<template>
<v-row justify="center">
<v-form ref="form" v-model="valid" lazy-validation>
<v-text-field v-model="title" label="Title*" :rules="rules.fieldRules" prepend-icon="mdi-text">
</v-text-field>
<v-text-field v-model="website_link" label="URL" prepend-icon="mdi-web">
</v-text-field>
<h3>Description</h3>
<text-editor #update:modelValue="getValue" :rules="rules.fieldRules" :modelValue="description">
</text-editor>
<br />
<v-select v-model="selectedState" :readonly="false" :items="items" filled label="Which state?*" prepend-icon="mdi-help"></v-select>
<v-file-input v-model="files" prepend-icon="mdi-camera" multiple label="File input"></v-file-input>
<v-layout v-for="file of files" :key="file">
<v-img :src="generateUrl(file)" max-width="10%" max-height="10%">
</v-img>
</v-layout>
<v-combobox v-model="tags" prepend-icon="mdi-lightbulb" label="Tags" chips clearable multiple filled
rounded></v-combobox>
<v-btn :disabled="mode == 'EDIT' ? false : !valid" color="success" class="mr-4" #click="validate">
Validate
</v-btn>
<v-btn color="blue" class="mr-4" #click="backToProfile">
Back
</v-btn>
</v-form>
</v-row>
</template>
selectedState is a computed method described as below here:
selectedState: {
get() {
if (this.mode == 'CREATE') {
return this.state
} else {
const state = this.items.filter((item) => item.value = this.currentConcept.state)[0].title;
this.setState(state);
return this.state;
}
},
set(value) {
console.log(`value: ${value}`)
this.state = value;
}
}
Am I missing something?
TIA

How can i switch my cursor by using arrow keys when i have multiple input fields in Vuejs

I have a total of 5 textfields made by using v-text-field. i have give autofocus to textfield 3. how can i change my cursor position in other text fields with the help of arrow keys.
i have provided the code below which gives the output of the below image but there is no movement of the cursor when we hit arrow keys.
<script>
export default {
data() {
return {
currentItem: 3,
};
},
mounted() {
document.addEventListener("keyup", this.nextItem);
},
methods: {
nextItem(event) {
if (event.keyCode == 38 && this.currentItem > 1) {
this.currentItem -= 2;
} else if (event.keyCode == 40 && this.currentItem < 6) {
this.currentItem += 2;
} else if (event.keyCode == 37 && this.currentItem < 6) {
this.currentItem -= 1;
} else if (event.keyCode == 39 && this.currentItem < 6) {
this.currentItem += 1;
}
},
},
};
</script>
<template>
<div>
<v-container>
<div #keyup="nextItem">
<v-row>
<v-col cols="12" align-self="center">
<v-text-field class="move" label="1st" id="1"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-text-field
class="move"
label="2nd"
id="2"
placeholder="Placeholder"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-text-field
class="move"
autofocus
label="3rd"
id="3"
placeholder="Placeholder"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-text-field
class="move"
label="4th"
id="4"
placeholder="Placeholder"
></v-text-field>
</v-col>
<v-col cols="12" align-self="center">
<v-text-field class="move" label="5th" id="5"></v-text-field>
</v-col>
</v-row>
</div>
</v-container>
</div>
</template>
that requires manual DOM interaction to me.
set a ref on each field:
<v-text-field ref="first />
Accessing it via this.$refs.first will return you the component instance.
Accessing the component element via this.$refs.first.$el will return you the <div> containing the whole component's element (not the exact template but you get the point):
<div class="v-input v-text-field">
<div>
<div>
<input>
</div>
</div>
</div>
You only want the input. You can do:
const input = this.$refs.first.$el.querySelector('input')
Or, since Vuetify already set a ref for the input, you can just do:
const input = this.$refs.first.$refs.input
Then just focus it yourself:
input.focus()
Alternatively, you can also try calling the focus method declared on <VTextField>:
this.$refs.first.focus();
Docs regarding $refs and $el: https://v2.vuejs.org/v2/api/#Instance-Properties
Vuetify source code reference for VTextField's $refs.input: https://github.com/vuetifyjs/vuetify/blob/v2.6.3/packages/vuetify/src/components/VTextField/VTextField.ts#L415
Vuetify source code reference for VTextField's focus method: https://github.com/vuetifyjs/vuetify/blob/v2.6.3/packages/vuetify/src/components/VTextField/VTextField.ts#L247
You need to interact with the DOM focus event to change the active focus, I add a ref to each input with the name of input-${id}.
On keyup I check the key events and if that input ref exist I change the currentItem property, with that you can remove the >1 and <6 conditionals.
Because you want to change the focus every time the currentItem variable changes, I add a watcher with immediate true removing the unmounted.
Code Example
Template
<v-container>
<div #keyup="changeFocusInput">
<v-row>
<v-col cols="12" align-self="center">
<v-text-field
class="move"
label="1st"
id="1"
ref="input-1"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-text-field
class="move"
label="2nd"
id="2"
ref="input-2"
placeholder="Placeholder"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-text-field
class="move"
autofocus
label="3rd"
id="3"
ref="input-3"
placeholder="Placeholder"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3">
<v-text-field
class="move"
label="4th"
id="4"
ref="input-4"
placeholder="Placeholder"
></v-text-field>
</v-col>
<v-col cols="12" align-self="center">
<v-text-field
class="move"
label="5th"
id="5"
ref="input-5"
></v-text-field>
</v-col>
</v-row>
</div>
</v-container>
JS
data() {
return {
currentItem: 3,
};
},
watch: {
currentItem: {
handler(value, oldValue) {
if (value !== oldValue) {
this.focusInput(value);
}
},
immediate: true
}
},
methods: {
getInput(id) {
const input = this.$refs[`input-${id}`];
return input;
},
changeFocusInput(event) {
const key_code = {
left: 37,
up: 38,
right: 39,
down: 40
};
let nextItem = this.currentItem;
if (event.keyCode == key_code.up) {
nextItem -= 2;
} else if (event.keyCode == key_code.down) {
nextItem += 2;
} else if (event.keyCode == key_code.left) {
nextItem -= 1;
} else if (event.keyCode == key_code.right) {
nextItem += 1;
}
if (this.getInput(nextItem)) {
this.currentItem = nextItem;
}
},
focusInput(id) {
const input = this.getInput(id);
if (input) {
input.focus();
}
},
},

Dynamic calculation using Vuetify

I'm trying to create dynamic calculator using Vuetify. Here's my code
<v-row class="mt-8 align-self-center">
<v-col cols="2">
<v-text-field :value="weight" label="Weight (kg)" placeholder="Type here" filled rounded></v-text-field>
</v-col>
<v-col cols="2">
<v-text-field :value="distance" label="Distance (km)" placeholder="Type here" filled rounded></v-text-field>
</v-col>
</v-row>
<v-card v-model="result" height="100" width="500">
Estimated shipping cost is: {{result}}
</v-card>
and here's my script
export default {
data() {
return {
inputDistance: '',
inputWeight: '',
result: ''
}
},
computed: {
result: function(){
var totalCost = this.inputDistance * this.inputWeight *2000;
return totalCost;
}
}
}
I have tried using v-model too but it still doesn't work. Any idea on what I suppose to write?
Thanks!
replace :value with v-model in your v-text-field, use the variable names and then remove v-model from v-card.
<v-row class="mt-8 align-self-center">
<v-col cols="2">
<v-text-field v-model="inputWeight" label="Weight (kg)" placeholder="Type here" filled rounded></v-text-field>
</v-col>
<v-col cols="2">
<v-text-field v-model="inputDistance" label="Distance (km)" placeholder="Type here" filled rounded></v-text-field>
</v-col>
</v-row>
<v-card height="100" width="500">
Estimated shipping cost is: {{result}}
</v-card>
and then use parseFloat in computed
export default {
data() {
return {
inputDistance: '',
inputWeight: '',
/** removed result variable **/
}
},
computed: {
result: function(){
var totalCost = parseFloat(this.inputDistance, 10) * parseFloat(this.inputWeight,10) *2000;
return totalCost;
}
}
}

how to upload image in nuxt.js using laravel backend API

nuxt.js i searched lots of tutorial for image uploading using laravel api but i not get logic how to code image uploading things help me to solve this or give tutorial links .
how to make image uploading form in nuxt.js
i Created laravel API for image uploading.
my Router
Route::group(['middleware' => 'auth:api'], function() {
Route::post('/Employeeregister', 'EMPLOYEE_API\RegisterController#register')->name('Employeeregister');
});
CONTROLLER CODE
public function imageUploadPost(Request $request)
{
$request->validate([
'name' => 'required | string',
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$imageName = time().'.'.$request->image->extension();
$request->image->move(public_path('images'), $imageName);
return back()
->with('success','You have successfully upload image.')
->with('image',$imageName);
}
MY Nuxt code
<template>
<v-row justify="center">
<v-col cols="12" sm="6">
<form #submit.prevent="submit">
<v-card ref="form" >
<v-card-text>
<h3 class="text-center">Register</h3>
<v-divider class="mt-3"></v-divider>
<v-col cols="12" sm="12">
<v-text-field v-model.trim="form.name" type="text" label="Full Name" solo autocomplete="off"></v-text-field>
</v-col>
<v-col cols="12" sm="12"><v-file-field v-model.trim="form.image" type="file" label="image" solo autocomplete="off"></v-file-field>
</v-col>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<div class="text-center">
<v-btn rounded type="submit" color="primary" dark>Register</v-btn>
</div>
</v-card-actions>
</v-card>
</form>
</v-col>
</v-row>
</template>
< script >
export default {
middleware: ['guest'],
data() {
return {
form: {
name: '',image: '',
}
}
},
} <
/script>
There's a few things to consider.
First, your template form.
<form #submit.prevent="submit">
<v-card ref="form" >
<v-card-text>
<h3 class="text-center">Register</h3>
<v-divider class="mt-3"></v-divider>
<v-col cols="12" sm="12">
<v-text-field v-model.trim="form.name" type="text" label="Full Name" solo autocomplete="off"></v-text-field>
</v-col>
<v-col cols="12" sm="12">
<v-file-field v-model.trim="form.image" type="file" label="image" solo autocomplete="off"></v-file-field>
</v-col>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<div class="text-center">
<v-btn rounded type="submit" color="primary" dark>Register</v-btn>
</div>
</v-card-actions>
</v-card>
</form>
Your input fields are bound to form.name and form.image, which is correct. In order to submit the form, you have tied the submit button to a method named submit (#submit.prevent="submit"), but you haven't created that method. So nothing happens! (You'll see a warning in your console.)
To create the method, you add it to your component under the methods: property.
export default {
middleware: ['guest'],
data() {
return {
form: {
name: '',image: '',
}
}
},
methods: {
async submit() {
let rsp = await this.$axios.$post('/Employeeregister', this.form, {
'content-type': 'multipart/form-data'
})
console.log(rsp.response)
}
}
}
Sending the form data to your Laravel API is straight forward, but there are a few considerations. Where is your nuxt app and laravel API hosted? eg. http://localhost:3000, http://localhost:80 etc. I'll update this answer based on your response.

v-slot:badge and v-if does not work with a computed property

I'm working on a CMS project and I have an issue I can't figure out.
I Have a component where I'm showing IP's. On change I want a badge to appear, so the user knows "this field is changed".
But the thing is the badge won't show if I'm using "v-slot:badge".
In the v-if is a computed property, If I inspect the page with vue devtools ‘isStartIpValueChanged’ will be true on a change. So, it should work right?
Template
<v-list-item-content>
<v-form ref="form" v-model="valid">
<v-hover v-slot:default="{ hover }">
<v-row align-content="center" no-gutters>
<v-col>
<v-badge overlap color="red" right>
<template v-slot:badge v-if="isStartIpValueChanged">
<v-avatar color="red" size="6"></v-avatar>
</template>
<v-text-field
dense
:rules="apiIpRules"
v-model="apiIp.startIp"
#input="valueChanged()"
ref="startIp"
:class="hover ? 'hover-text-color' : ''"
placeholder="###.###.###.###">
</v-text-field>
</v-badge>
</v-col>
<v-col cols="1" class="text-center" align-self="center">
<p>-</p>
</v-col>
<v-col cols="1" class="text-center" align-self="center">
<v-btn v-show="hover" #click="deleteIp()" icon small color="red"><v-icon>mdi-minus-circle</v-icon></v-btn>
</v-col>
</v-row>
</v-hover>
</v-form>
Created and Computed (apiIp is a prop I get from the parent component)
created () {
this.apiIpsOriginalValueStartIp = this.apiIp.startIp
this.apiIpsOriginalValueEndIp = this.apiIp.endIp
this.apiIp.uuid = this.GenerateUUID()
},
computed: {
isStartIpValueChanged () {
return this.apiIp &&
(this.apiIp.startIp !== this.apiIpsOriginalValueStartIp ||
this.apiIp.uuid === null)
},
isEndIpValueChanged () {
return this.apiIp &&
(this.apiIp.endIp !== this.apiIpsOriginalValueEndIp ||
this.apiIp.uuid === null)
}
},
Anyone know what is going wrong here?
As according to Vuetify's own documentation, you should be using the v-model, directly on the v-badge, to show it only when you want it to.
<v-badge overlap color="red" right v-model="isStartIpValueChanged">
<template v-slot:badge>
<v-avatar color="red" size="6"></v-avatar>
</template>
<v-text-field
dense
:rules="apiIpRules"
v-model="apiIp.startIp"
#input="valueChanged()"
ref="startIp"
:class="hover ? 'hover-text-color' : ''"
placeholder="###.###.###.###">
</v-text-field>
</v-badge>
Doc: https://vuetifyjs.com/en/components/badges#show-on-hover