Dynamic calculation using Vuetify - vue.js

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;
}
}
}

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 do I watch for onChange of specific select menu that was dynamically generated?

I have a row of 3 inputs. It lay out like this:
Attribute (select) > Operators (select) > Value (text)
UI look like this:
Code for that:
<v-row v-for="(rule, index) in rules" :key="index">
<v-col cols="12" sm="6" md="3">
<v-select
dense
outlined
item-text="name"
item-value="id"
label="Attribute"
v-model="form.values.attributes"
:items="attributes"
></v-select>
</v-col>
<v-col cols="12" sm="6" md="2">
<v-select
outlined
dense
item-text="name"
item-value="id"
label="Operator"
v-model="rule.operator"
:items="operators"
></v-select>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
dense
outlined
label="Values"
v-model="rule.value"
></v-text-field>
</v-col>
</v-row>
The operator menu is dynamically populated based on API based on the selected attribute.
I have v-model="form.values.attributes", and my watch to call the API for the operators
watch: {
'form.values.attributes'() {
let data = {
$root: 'rules'
}
axios.defaults.headers['Content-Type'] = 'application/json'
axios.post(window.MTS_URL, data).then((response) => {
this.operators = response.data.operators
})
}
}
This works great with one row.
But when I clicked Add, I appended another row, and I need to support multiple rows.
How do I watch for onChange of specific select menu ?
I was thinking to move my
v-model="form.values.attributes"
to
v-model="rule.attribute"
but is it the right thing to do ?
You can try remodeling your data to experience the power of Vue.
Your template:
<template>
<v-app>
<v-row v-for="(rule, index) in rules" :key="index">
<v-col cols="12" sm="6" md="3">
<v-select
dense
outlined
item-text="name"
item-value="id"
label="Attribute"
:items="rule.attributes"
#change="onChange($event, rule, index)"
></v-select>
</v-col>
<v-col cols="12" sm="6" md="2">
<v-select
outlined
dense
item-text="name"
item-value="id"
label="Operator"
:items="rule.operators"
></v-select>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field dense outlined label="Values"></v-text-field>
</v-col>
</v-row>
</v-app>
</template>
Notice how everything is rendered in the rules data. Here the rules data will be an array containing all the rows:
rules = [
{
attributes: ["11", "22"],
operators: []
}
]
Your script should look like below:
<script>
import axios from "axios"
export default {
name: "App",
data() {
return {
rules: [{
attributes: ["11", "22", "33"],
operators: [],
}],
};
},
methods: {
async onChange(changed, rule, index) {
// where:
// `changed` is the value selected
// `rule` is the attributes and rule in the selected row
// `index` is the index in the rules array that just got changed
console.log(changed, rule, index);
const operators = await this.fetchApiData(changed);
this.$set(this.rules, index, { ...rule, operators: operators });
},
},
async fetchApiData(data) {
const response = await axios.post(window.MTS_URL, data);
return response.data.operators;
},
};
</script>
if you want to add more rows, you just need to push an object to the rules data:
this.rules.push({
attributes: ["new attribute 1", "new attribute 2"],
operators: []
})

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.

How can I get country code on vue tel input?

My component
<v-form>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="3">
<vue-tel-input v-model="phone"></vue-tel-input>
</v-col>
</v-row>
</v-container>
<v-btn
color="success"
#click="submit"
>
submit
</v-btn>
</v-form>
When I click submit, I just get phone. How can I get country code too?
[Reference] https://www.npmjs.com/package/vue-tel-input-vuetify
[Codepen] https://codepen.io/positivethinking639/pen/YzzjzWK?&editable=true&editors=101
It seems like vue-tel-input provides a country-changed event. According to the docs it's even fired for the first time and it returns an object:
Object {
areaCodes: null,
dialCode: "31",
iso2: "NL",
name: "Netherlands (Nederland)",
priority: 0
}
So this event handler can be added to the component and the country code can be stored in the component as you already do for the phone value.
HTML part
<div id="app">
<v-app id="inspire">
<v-form>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="3">
<vue-tel-input v-model="phone" v-on:country-changed="countryChanged"></vue-tel-input>
</v-col>
</v-row>
</v-container>
<v-btn
color="success"
#click="submit"
>
submit
</v-btn>
</v-form>
</v-app>
</div>
JS Part
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
phone: null,
country: null
}
},
methods: {
countryChanged(country) {
this.country = country.dialCode
},
submit() {
console.log(this.phone);
console.log(this.country);
}
}
});
Here you can see a working version:
https://codepen.io/otuzel/pen/PooBoQW?editors=1011
NOTE: I don't use Vue on daily basis so I am not sure if this the best practice to modify the data via the event handler.
<vue-tel-input v-model="phone" v-bind="bindProps"></vue-tel-input>
data() {
return {
phone: null,
bindProps:{
mode: 'international'
}
}
}
It's achievable in vue-tel-input#3.1.1 by setting prop mode: 'international', in this case, the phone number will always be converted to +123 123 123...

reset a vuetify stepper

I'm looking for a function who can resetting my stepper made with vuetify.
the e1 is set as 0 but if I make a function who reset this value to 0, it doesn't work and the stepper set as the same screen.
It is possible to reset a stepper to default state
Find the working codepen here: https://codepen.io/chansv/pen/wvvzddP?editors=1010
<div id="app">
<v-app id="inspire">
<v-stepper v-model="step" vertical>
<v-stepper-header>
<v-stepper-step step="1" :complete="step > 1">Your Information</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step step="2" :complete="step > 2">Your Address</v-stepper-step>
<v-divider></v-divider>
<v-stepper-step step="3">Misc Info</v-stepper-step>
</v-stepper-header>
<v-stepper-items>
<v-stepper-content step="1">
<v-text-field label="Name" v-model="registration.name" required></v-text-field>
<v-text-field label="Email" v-model="registration.email" required></v-text-field>
<v-btn color="primary" #click.native="step = 2">Continue</v-btn>
</v-stepper-content>
<v-stepper-content step="2">
<v-text-field label="Street" v-model="registration.street" required></v-text-field>
<v-text-field label="City" v-model="registration.city" required></v-text-field>
<v-text-field label="State" v-model="registration.state" required></v-text-field>
<v-btn flat #click.native="step = 1">Previous</v-btn>
<v-btn color="primary" #click.native="step = 3">Continue</v-btn>
</v-stepper-content>
<v-stepper-content step="3">
<v-text-field label="Number of Tickets" type="number"
v-model="registration.numtickets" required></v-text-field>
<v-select label="Shirt Size" v-model="registration.shirtsize"
:items="sizes" required></v-select>
<v-btn flat #click.native="step = 2">Previous</v-btn>
<v-btn color="primary" #click.prevent="submit">Save</v-btn>
</v-stepper-content>
</v-stepper-items>
</v-stepper>
</v-app>
</div>
const defaultReg = Object.freeze({
name:null,
email:null,
street:null,
city:null,
state:null,
numtickets:0,
shirtsize:'XL'
});
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
step:1,
registration: Object.assign({}, defaultReg),
sizes:['S','M','L','XL']
}
},
methods:{
submit() {
this.registration = Object.assign({}, defaultReg);
this.step = 1;
}
}
})
A simpler approach at resetting your stepper is by using the key prop assigning to it a value and then in the function increasing this value. Something like this:
<template>
<v-stepper
:key="stepperKey"
v-model="e1"
>
...
</v-stepper>
</template>
<script>
export default {
data () {
return {
e1: 1,
stepperKey: 0
}
},
methods: {
increaseKey () { this.stepperKey++ }
}
}
</script>
The key prop or attribute is a build in Vue.js feature. Even if you don't see it it's been used on the back. Changing the key will trigger a re render.
If you have doubt about the key attribute/prop here is a nice article about it