Autofill input fields - vue.js

I need following to work. I have an input field (in my Code number1) and I need to autofill (not autocomplete) the other input fields (in my Code autofill1 + autofill2).
I'm working with Bootstrap Vue (Bootstrap 4.6 and Vue.js 2).
Here is my code:
<template>
<div class="m-2 mt-3">
<table class="table table-striped mt-2">
<tbody>
<h5 class="ml-1">Informations</h5>
<tr>
<div class="row">
<div class="col-md-6 m-1">
<div class="mt-2">number1</div>
<b-form-input class="form-control" placeholder="1234567" id="number1" />
</div>
</div>
<div class="row">
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">autofill1</div>
<b-form-select id="autofill1"> </b-form-select>
</div>
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">autofill2</div>
<b-form-select id="autofill2"> </b-form-select>
</div>
<div class="row">
<div class="col-md-3 mt-2 ml-1">
<b-button variant="success" type="submit"><b-icon icon="check-circle-fill"></b-icon> Save Changes</b-button>
</div>
</div>
</div>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
};
</script>
<style scoped>
</style>
So my goal is to load some data (first guess was an json file) into my script and after I write a matching number (also possible that its a text) in input field number1 the other two fields will be autofilled.
Thanks in advance for helping me out!
Structure json data:
[
{ "number": 1234567, "autofill1": "Hello", "autofill2": "Goodbye" },
{ "number": 9876543, "autofill1": "Ciao", "autofill2": "Arrivederci" },
{ "number": 1346795, "autofill1": "Hallo", "autofill2": "Tschuess" }
]

Something like this would work: Example
<template>
<div>
<input type="number" placeholder="1234567" v-model.number="number1" />
<input type="text" :value="getAutofill.autofill1" />
<input type="text" :value="getAutofill.autofill2" />
</div>
</template>
<script>
export default {
computed: {
getAutofill(){
if (!this.data.find(item => item.number == this.number1)) return ["",""]
return this.data.find(item => item.number == this.number1)
}
},
data() {
return {
number1: undefined,
data: [
{ "number": 1234567, "autofill1": "Hello", "autofill2": "Goodbye" },
{ "number": 9876543, "autofill1": "Ciao", "autofill2": "Arrivederci" },
{ "number": 1346795, "autofill1": "Hallo", "autofill2": "Tschuess" }
]
}
}
};
</script>

you need to add some things to the data and than watch for the variable number1 to change...
<template>
<div class="m-2 mt-3">
<table class="table table-striped mt-2">
<tbody>
<h5 class="ml-1">Informations</h5>
<tr>
<div class="row">
<div class="col-md-6 m-1">
<div class="mt-2">number1</div>
<b-form-input class="form-control" placeholder="1234567" id="number1" v-model="number1" />
</div>
</div>
<div class="row">
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">autofill1</div>
<b-form-input class="form-control" id="autofill1" v-model="autofill1" />
</div>
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">autofill2</div>
<b-form-input class="form-control" id="autofill2" v-model="autofill2" />
</div>
<div class="row">
<div class="col-md-3 mt-2 ml-1">
<b-button variant="success" type="submit"><b-icon icon="check-circle-fill"></b-icon> Save Changes</b-button>
</div>
</div>
</div>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data(){
return {
number1: "",
autofill1: "",
autofill2: "",
jsonDATA: {...}
}
},
methods: {
findData(key) {
for(let i=0; i < this.jsonDATA.length; i++){
if(this.jsonDATA[i]['number'] === key) return element[i]
}
// add somthing when no data in array...
}
},
watch: {
number1(){
try {
let tmp = this.findData(this.number1)
this.autofill1 = tmp['autofill1']
this.autofill2 = tmp['autofill2']
}
}
}
};
</script>
<style scoped>
</style>
I havent tested this but this should work... This is not complete, you need to add some behaviour what to do when no data is found...

Related

Set Index in computed function

I have a v-for loop like following:
<div class="inputArea mt-2" v-for="(id, index) in inputs" :key="index">
<div class="row">
<div class="col-md-6 m-1">
<div class="mt-2">Input Number</div>
<b-form-input type="number" v-model="Number[index]"></b-form-input>
</div>
<div class="row">
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">Autofill 1</div>
<b-form-input type="text" :value="Autofill[index].autofill1" </b-form-input>
</div>
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">Autofill 2</div>
<b-form-input type="text" :value="Autofill[index].autofill2" </b-form-input>
</div>
</div>
</div>
</div>
How can I reference my index into a computed function:
computed: {
Autofill() { <!-- Autofill[index]() is not working -->
var returnelement = {};
if(this.json!= undefined) {
this.json.forEach(element => {
for(const item of this.Number) {
if (+element.number === +item)
returnelement = element;
}
});
}
return returnelement;
},
},
data() {
return {
inputs:[{}],
Number: [],
json: json, //imported before
}
}
Autofill[index] ( ) is not working, but I need this unique index in here..
Thanks for helping me out!
Try this
If you want to pass the index from the loop to Autofill, then you should use the methods.
You cannot pass data to a function from computed.
<div class="inputArea mt-2" v-for="(id, index) in inputs" :key="index">
<div class="row">
<div class="col-md-6 m-1">
<div class="mt-2">Number</div>
<b-form-input type="number" v-model="Number[index]"></b-form-input>
</div>
<div class="row">
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">Autofill 1</div>
<b-form-input type="text" :value="Autofill(index).autofill1" </b-form-input>
</div>
<div class="col-md-5 ml-1 mr-1">
<div class="mt-2">Autofill 2</div>
<b-form-input type="text" :value="Autofill(index).autofill2" </b-form-input>
</div>
</div>
</div>
</div>
<script>
export default {
//...
methods: {
Autofill(index) {
var returnelement = {};
if (this.json != undefined) {
this.json.forEach(element => {
for (const item of index) {
if (+element.number === +item)
returnelement = element;
}
});
}
return returnelement;
},
},
}
</script>

Cloning div with vue

<template>
<b-form #submit.prevent="Submit" class="mb-5">
<div class="inputArea" v-for="input in inputs" :key="input.id">
<b-form-group label-cols-sm="2" label="Solution (EN)">
<ckeditor :editor="ckeditor" v-model="form.body.en" :config="ckeditorConfig"></ckeditor>
<div v-if="errors['body.en']">
<div v-for="err in errors['body.en']" :key="err">
<small class="text-danger">{{ err }}</small>
</div>
</div>
</b-form-group>
<b-form-group label-cols-sm="2" label="Body (FR)">
<ckeditor :editor="ckeditor" v-model="form.body.np" :config="ckeditorConfig"></ckeditor>
<div v-if="errors['body.np']">
<div v-for="err in errors['body.np']" :key="err">
<small class="text-danger">{{ err }}</small>
</div>
</div>
</b-form-group>
<b-form-group label-cols-sm="2" label="Body (IT)">
<ckeditor :editor="ckeditor" v-model="form.body.in" :config="ckeditorConfig"></ckeditor>
<div v-if="errors['body.in']">
<div v-for="err in errors['body.in']" :key="err">
<small class="text-danger">{{ err }}</small>
</div>
</div>
</b-form-group>
</div>
<b-form-group label="" label-cols-sm="2">
<b-button type="button" class="text-white" variant="dark" #click="addRow">Add row</b-button>
</b-form-group>
<b-form-group label="" label-cols-sm="2">
<b-button type="submit" class="text-white" variant="dark">Submit</b-button>
</b-form-group>
</b-form>
</template>
<style lang="scss">
</style>
<script>
import CKEditor from '#ckeditor/ckeditor5-vue2'
import ClassicEditor from '#ckeditor/ckeditor5-build-classic'
export default {
name: 'Interaction',
components: {
ckeditor: CKEditor.component
},
data(){
return{
counter: 0,
inputs: [
{
en: '',
np: '',
in: '',
}],
form: {
body: [
{
en: '',
np: '',
in: '',
}
],
},
errors: {},
ckeditorData: '<p></p>',
ckeditorConfig: {
// The configuration of the editor
},
ckeditor: ClassicEditor
}
},
methods: {
Submit(){
this.storing = true
this.errors = {}
var self = this
axios.post('/this-is-a-post-url', this.form)
.then(function(response){
console.log(response)
})
},
addRow() {
this.inputs.push({
en: '',
it: '',
fr: '',
id: `${++this.counter}`,
value: '',
});
}
}
}
</script>
I will have array coming in the body name so I am trying to to clone the clone body on a click of a button which has a function AddRow. I want to clone the three fields en,np,in and I want it work like normal html works in this. Example when we clone html form it create input field like so <input name="body['en'][0]"> and when we clone another time it creates something like this <input name="body['en'][1]">.
I have the above code, it clones the body but it also clones the added text before cloning. I want to add an empty field while cloning and also want to update v-model. How can I do that?
Refer below example:
https://codepen.io/telen/pen/OeNZVV
<main class="container">
<form id="app" data-apartments='[{ "price": "23000", "rooms": "12" }, { "price": "42000", "rooms": "32" }]'>
<h1>
Dynamic apartment forms
</h1>
<hr>
<div class="row">
<div class="col-xs-2">
<button type="button" v-on:click="addNewApartment" class="btn btn-block btn-success">
Add +
</button>
</div>
<div class="col-xs-10">
Would you like add more apartments?
</div>
</div>
<div v-for="(apartment, index) in apartments">
<div class="row">
<div class="col-xs-2">
<label> </label>
<button type="button" v-on:click="removeApartment(index)" class="btn btn-block btn-danger">
Rem -
</button>
</div>
<div class="form-group col-xs-5">
<label>Price (HUF)</label>
<input v-model="apartment.price" type="number"
name="apartments[][price]" class="form-control" placeholder="Price">
</div>
<div class="form-group col-xs-5">
<label>Rooms (PCS)</label>
<input v-model="apartment.rooms" type="number"
name="apartments[][rooms]" class="form-control" placeholder="Rooms">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2">
<button type="submit" v-on:click.prevent="sumbitForm" class="btn btn-block btn-primary">
Submit
</button>
</div>
<div class="col-xs-10">
Open the console (F12) and see the result
</div>
</div>
<hr>
<pre>{{ $data }}</pre>
</form>
JS:
window.app = new Vue({
el: '#app',
data: {
apartment: {
price: '',
rooms: ''
},
apartments: [],
},
mounted: function () {
/*
* The "data-apartments" could come from serverside (already saved apartments)
*/
this.apartments = JSON.parse(this.$el.dataset.apartments)
},
methods: {
addNewApartment: function () {
this.apartments.push(Vue.util.extend({}, this.apartment))
},
removeApartment: function (index) {
Vue.delete(this.apartments, index);
},
sumbitForm: function () {
/*
* You can remove or replace the "submitForm" method.
* Remove: if you handle form sumission on server side.
* Replace: for example you need an AJAX submission.
*/
console.info('<< Form Submitted >>')
console.info('Vue.js apartments object:', this.apartments)
window.testSumbit()
}
}
})
/*
* This is not Vue.js code, just a bit of jQuery to test what data would be submitted.
*/
window.testSumbit = function () {
if (!window.jQuery) {
console.warn('jQuery not present!')
return false
}
console.info('Submitted (serverside) array:', jQuery('form').serializeJSON())
}

How to pass data which is coming as response from backend to the another component in vue.js?

I am developing one page which is responsible for placing order Cart.vue which contains two api calls, handleMail() method is sending email and generating a orderID and i am getting response from backend in network section like this.
{
"message":"order created successfully",
"orderID":87450588
}
i am catching that orderID and stored as a orderNumber,Now i want to pass that orderNumber to another component called orderPlace.vue and i want to display that orderNumber inside template section.for this i am creating Event bus it's not working ,please help me to pass orderNumber to another component ...
Cart.vue
<template>
<div class="main">
<div class="first-section">
<div class="content">
<h5>My Cart({{books.length}})</h5>
</div>
<div v-for="book in books" :key="book.id" class="container">
<div class="mid-section">
<img class="img-section" v-bind:src="book.file" alt="not found">
<p class="title-section">{{book.name}}</p>
</div>
<div class="author-section">
<p class="author-name">by {{book.author}}</p>
</div>
<div class="price-section">
<h6>Rs.{{book.price}}</h6>
</div>
<div class="icons">
<i class="fas fa-minus-circle"></i>
<input class="rectangle" value=1>
<i class="fas fa-plus-circle"></i>
</div>
</div>
<div class="btn-grps">
<button class="btn" v-on:click="flip()" v-if="hide==true" type="submit">Place Order</button>
</div>
</div>
<div class="second -section">
<div class="details-box">
<input type="text" v-if="hide==true" class="initial-btn" placeholder="Customer Details" />
</div>
<div v-if="hide==false" class="fill-details">
<form #submit.prevent="" class="address">
<h4 class="heading">Customer Details</h4>
<div class="name">
<input type="name" required pattern="[A-Za-z]{3,10}" v-model="name">
<label class="label">Name</label>
</div>
<div class="name">
<input type="text" required v-model="phoneNumber">
<label class="label">Phone Number</label>
</div>
<div class="pin">
<input type="text" required v-model="pincode">
<label class="label">PinCode</label>
</div>
<div class="pin">
<input type="text" required v-model="locality">
<label class="label">Locality</label>
</div>
<div class="address-block">
<input class="address" type="text" required v-model="address">
<label id="Add" class="label">Address</label>
</div>
<div class="city-landMark">
<input type="text" required v-model="city">
<label class="label">City/Town</label>
</div>
<div class="city-landMark">
<input type="text" required v-model="landmark">
<label class="label">LandMark</label>
</div>
<div class="Radio-Buttons">
<p>Type</p>
<div class="radio-btns flex-container">
<div>
<input type="radio" id="Home" value="Home" name="type" v-model="type">
<div class="first-radio"> <label class="home" for="Home">Home</label></div>
</div>
<div>
<input class="work-round" type="radio" id="Work" value="Work" name="type" v-model="type">
<div class="second-radio"> <label for="Work" class="work-label">Work</label></div>
</div>
<div>
<input class="other-round" type="radio" id="Other" value="Other" name="type" v-model="type">
<div class="third-radio"><label class="other-label" for="Other">Other</label></div>
</div>
</div>
<div class="btn-continue">
<button type="submit" #click="handlesubmit();handleMail();" class="continue">continue</button>
</div>
</div>
</form>
</div>
</div>
</div>
</template>
<script>
import service from '../service/User';
import { EventBus } from "./event-bus.js";
export default {
created() {
if (localStorage.getItem("reloaded")) {
localStorage.removeItem("reloaded");
} else {
localStorage.setItem("reloaded", "1");
location.reload();
}
service.userDisplayCart().then(response => {
this.books = response.data;
})
},
data() {
return {
flag: true,
hide: true,
booksCount: 0,
name: '',
phoneNumber: '',
pincode: '',
locality: '',
city: '',
address: '',
landmark: '',
type: '',
books: [],
cart:'MyCart',
nameField:'Name',
phoneField:'Phone Number',
pincodeField:'PinCode',
AddressField:'Address',
localityField:'Locality',
cityField:'CityTown',
landmarkField:'LandMark',
orderNumber:''
}
},
methods: {
flip() {
this.hide = !this.hide;
},
Togglebtn() {
this.flag = !this.flag;
},
handlesubmit() {
let userData = {
name: this.name,
phoneNumber: this.phoneNumber,
pincode: this.pincode,
locality: this.locality,
city: this.city,
address: this.address,
landmark: this.landmark,
type: this.type,
}
service.customerRegister(userData).then(response => {
return response;
}).catch(error=>{
alert("invalid customer address");
return error;
})
},
// handleMail(){
// service.confirmMail().then(response=>{
// alert("order placed successfully");
// let orderNumber= response.data.orderID;
// this.$router.push({path: '/ordersuccess'});
// console.log(response);
// return orderNumber;
// }).catch(error=>{
// alert("Error in sending email");
// return error;
// })
// }
handleMail(){
service.confirmMail().then(response=>{
alert("order placed successfully");
let orderNumber= response.data.orderID;
console.log("my num",orderNumber);
EventBus.$emit("emitting-order", orderNumber);
this.$router.push({path: '/ordersuccess'});
console(response);
return orderNumber;
})
},
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/Cart.scss";
</style>
OrderPlace.vue
<template>
<div class="order-place">
<div class="image-container">
<img src="../assets/success.png" alt="not found" />
</div>
<div class="title-container">
<p>Order placed Successfully</p>
</div>
<div class="message-section">
<p>Hurray!!!your order is confirmed {{orderNumber}} and placed successfully contact us in below details
for further communication..</p>
</div>
<div class="title-section">
<div class="email-us">
<p>Email-us</p>
</div>
<div class="contact-us">
<p>Contact-us</p>
</div>
<div class="address">
<p>Address</p>
</div>
</div>
<div class="email-sec">
<p>admin#bookstore.com</p>
</div>
<div class="contact-sec">
<p>+918163475881</p>
</div>
<div class="address-sec">
42, 14th Main, 15th Cross, Sector 4 ,opp to BDA complex, near Kumarakom restaurant, HSR Layout, Bangalore 560034
</div>
<div class="button">
<router-link to="/dashboard" class="btn">Continue Shopping</router-link>
</div>
</div>
</template>
<script>
import { EventBus } from "./event-bus.js";
export default {
name: 'OrderPlace',
data(){
return{
successTitle:'Order placed Successfully',
adminEmailSection:'Email-us',
adminContactSection:'Contact-us',
adminAddressSection:'Address',
adminEmail:'admin#bookstore.com',
adminMobNum:'+918163475881',
orderNumber: ''
}
},
mounted() {
EventBus.$on("emitting-order", orderNo=> {
this.orderNumber = orderNo;
console.log(`Oh, that's great ${orderNo})`);
return orderNo;
});
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/OrderPlace.scss";
</style>
event-bus.js
import Vue from 'vue';
export const EventBus = new Vue();
If the orderPlace.vue component is not active when you do the emit. It cannot receive the element.
You can try to register your order number, in the localStorage. Or call orderPlace.vue as a child component and pass the order number to the props

Using same .vue component twice in same parent component - how to differentiate

I want to use the same component twice from a parent component; all that was stopping me was the use of an ID for a dropdown in the subcomponents! So I currently have duplicated the subcomponent.
My parent component:
<template>
<div id="compare-page">
<div class="row">
<div class="col-md-12">
<div class="row campaign-overview">
<div class="col-md-4">
<h2>{{ campaign.name }}</h2>
<strong>Published</strong>
<strong>Starts: {{ campaign.start_date }} - Ends: {{ campaign.end_date }}</strong>
</div>
<div class="col-md-4 text-right">
<select name="daterange" id="" #change="onChangeDaterange($event)">
<option v-for="(daterange, index) in dateranges" v-bind:key="daterange.index" :value="index" :data-start="daterange.start" :data-end="daterange.end" :selected="daterange.optionSelected == 1">{{ index }}</option>
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<left-device ref="leftDevice"></left-device>
</div>
<div class="col-md-6">
<right-device ref="rightDevice"></right-device>
</div>
</div>
</div>
</template>
<script>
import left from './compared_device_component_left.vue';
import right from './compared_device_component_right.vue';
export default {
components: {
'left-device': left,
'right-device': right,
},
mounted() {
this.fetchCampaignData().then(result => {
});
},
data() {
return {
campaign_id: this.$route.params.campaign_id,
campaign: [],
dateranges: [],
leftDevice: '',
rightDevice: ''
}
},
methods: {
fetchCampaignData() {
return this.$http.get('/api/portal/campaign/' + this.campaign_id + '/campaign?' + this.axiosParams)
.then(function(data){
return data.json();
}).then(function(data){
this.campaign = data.campaign;
this.dateranges = data.dateranges;
});
},
onChangeDaterange(event) {
this.$router.push('?range=' + event.target.value);
this.$refs.leftDevice.onChangeDaterange(event);
this.$refs.rightDevice.onChangeDaterange(event);
},
},
computed: {
axiosParams() {
const params = new URLSearchParams();
if(this.$route.query.range) params.append('range', this.$route.query.range);
return params;
}
},
}
</script>
<style lang="scss">
</style>
One of my subcomponents
<template>
<div>
<div class="row device-overview">
<div class="col-md-4">
<select name="devices" id="deviceLeft" #change="onChangeDevice($event)">
<option v-for="(device, index) in devices" v-bind:key="device.index" :value="index" :data-device_id="device.device_id" :data-address="device.address" :selected="device.optionSelected == 1">{{ device.device_id }} | {{ device.address }}</option>
</select>
</div>
</div>
<div class="row totals">
<div class="col-md-4 card">
<div class="card-body">
<h5 class="card-title">Total Interactions</h5>
<p class="card-text">{{ total_interactions }}</p>
</div>
</div>
<div class="col-md-4 card">
<div class="card-body">
<h5 class="card-title">Average Interactions Per Day</h5>
<p class="card-text">{{ average_daily_interactions }}</p>
</div>
</div>
<div class="col-md-4 card">
<div class="card-body">
<h5 class="card-title">Total Average Dwell Time</h5>
<p class="card-text">{{ average_dwell_time }}s</p>
</div>
</div>
</div>
<div class="row interactions">
<div class="col-md-12">
<h5>Total Interactions Per Product</h5>
<table class="table table-condensed table-hover">
<tbody>
<tr>
<td class="">Tag</td>
<td class="">Mapped Product</td>
<td class="">Lifts</td>
</tr>
<tr v-for="interaction in table_product_interactions">
<td class="">{{ interaction.tag }}</td>
<td class="">{{ interaction.mapping }}</td>
<td>{{ interaction.tag_count }}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-12">
<h5>Total Interactions Per Day</h5>
<div class="chart" ref="chartdaily"></div>
</div>
</div>
<div class="row interactions">
<div class="col-md-8">
<h5>Total Interactions Per Hour</h5>
<div class="chart" ref="charthourly"></div>
</div>
</div>
</div>
</template>
<script>
import * as am4core from "#amcharts/amcharts4/core";
import * as am4charts from "#amcharts/amcharts4/charts";
import am4themes_animated from "#amcharts/amcharts4/themes/animated";
am4core.useTheme(am4themes_animated);
export default {
mounted() {
this.fetchData(null).then(result => {
this.chartTotalPerDay();
this.chartTotalPerHour();
});
},
data() {
return {
campaign_id: this.$route.params.campaign_id,
campaign: [],
dateranges: [],
device: [],
devices: [],
total_interactions: '',
average_daily_interactions: '',
average_dwell_time: '',
interaction_type: '',
chart_daily_interactions: [],
chart_hourly_interactions: [],
table_product_interactions: []
}
},
methods: {
fetchData(deviceID) {
// Use JS to get by ID!
var device = document.getElementById("deviceLeft");
// ... call to API
},
chartTotalPerDay() {
// ...
},
chartTotalPerHour() {
// ...
},
onChangeDaterange(event) {
// Use JS to get by ID!
var device = document.getElementById("deviceLeft");
// st cookie
document.cookie = "deviceLeft="+device.value;
this.fetchData(device.value).then(result => {
this.chartTotalPerDay();
this.chartTotalPerHour();
});
},
onChangeDevice(event) {
// st cookie
document.cookie = "deviceLeft="+event.target.value;
this.fetchData(event.target.value).then(result => {
this.chartTotalPerDay();
this.chartTotalPerHour();
});
}
},
created() {
},
computed: {
axiosParams() {
const params = new URLSearchParams();
if(this.$route.query.range) params.append('range', this.$route.query.range);
return params;
}
},
filters: {
},
directives: {
},
}
</script>
<style lang="scss">
.interactions {
h5 {
text-align: center;
}
}
.chart {
min-height: 550px;
}
</style>
I am currently using
var device = document.getElementById("deviceLeft");
...in my duplicated left/right subcomponents (this is 'left' and I also have 'right').
Should I use a 'ref' for my devices dropdown, so that each instance of the subcomponent is looking at the devices dropdown relative to that instance? Currently if I merge these into one the devices dropdown ID is the same for both instances and therefore I get incorrect ID in one of the instances!
Any helpful pointers would be much appreciated.
Thanks,
K...

vuejs :disabled doesn't work

I have a problem on reactivating the button even if the conditional statement works.
it looked like the v-model wasn't communicating with the data but with a simple interpolation the value was updated.
I don't really know where I'm doing wrong on the code.
<template>
<div class="col-sm-6 col-md-4">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">{{stock.name}}
<small>(Price: {{stock.price}})</small>
</h3>
</div>
<div class="panel-body">
<div class="pull-left">
<input v-model="quantity" type="number" class="form-control" placeholder="Quantity">
</div>
<div class="pull-right">
<button class="btn btn-success" #click="buyStock" :disabled="isDisabled">Buy</button>
</div>
<p>{{quantity}}</p>
</div>
</div>
</div>
</template>
<script>
export default {
props: [
"stock",
],
data() {
return {
quantity: 0,
}
},
methods: {
buyStock() {
const order = {
stockId: this.stock.id,
stockPrice: this.stock.price,
quantity: this.quantity
};
console.log(order);
this.$store.dispatch("buyStock", order);
this.quantity = 0;
}
},
computed: {
isDisabled() {
if (this.quantity <= 0 || !Number.isInteger(this.quantity)) {
return true;
} else {
return false;
}
}
}
}
</script>
By default, the v-model directive binds the value as a String. So both checks in your isDisabled computed will always fail.
If you want to bind quantity as a number, you can add the .number modifier like so:
<input v-model.number="quantity" type="number" ... >
Here's a working example:
new Vue({
el: '#app',
data() {
return { quantity: 0 }
},
computed: {
isDisabled() {
return (this.quantity <= 0 || !Number.isInteger(this.quantity))
}
}
})
<template>
<div class="col-sm-6 col-md-4">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">{{stock.name}}
<small>(Price: {{stock.price}})</small>
</h3>
</div>
<div class="panel-body">
<div class="pull-left">
<input v-model="quantity" type="number" class="form-control" placeholder="Quantity">
</div>
<div class="pull-right">
<button class="btn btn-success" #click="buyStock" :disabled="isDisabled">Buy</button>
</div>
<p>{{quantity}}</p>
</div>
</div>
</div>
</template>
<script>
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<div id="app">
<input v-model.number="quantity" type="number">
<button :disabled="isDisabled">Foo</button>
</div>