Vue 2 v-if not working after input changed - vue.js

Maybe I'm doing it wrong but while binding v-if to two distinct input fields it only works if the input values hasn't changed.
var app = window.app = new Vue({
el: '#admin-app',
data() {
return {
language: "en"
}
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.common.js"></script>
<div id="admin-app">
<select id="language" name="language" class="form-control" v-model="language">
<option value="ro">Romanian</option>
<option value="en">English</option>
</select>
<input type="text" class="form-control" value="Test RO" v-if="language == 'ro'" />
<input type="text" class="form-control" value="Test EN" v-if="language == 'en'" />
</div>
As soon as one of the input fields has changed the v-if does not seem to work anymore. Although the "language" value changes when another option is selected.

VueJS appears to be extrapolating the inline input value as needing to be bound. I suspect that the input value is bound to the language prop. As a result, you can no longer safely evaluate your if condition once a value has been changed.
A workaround to this is to give both inputs explicit models via v-model. This correctly allows for both your conditional display and your input binding.
var app = window.app = new Vue({
el: '#admin-app',
data() {
return {
language: "en",
test1: "Test RO",
test2: "Test EN"
}
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.common.js"></script>
<div id="admin-app">
<select id="language" name="language" class="form-control" v-model="language">
<option value="ro">Romanian</option>
<option value="en">English</option>
</select>
<input type="text" class="form-control" v-model="test1" v-if="language == 'ro'" />
<input type="text" class="form-control" v-model="test2" v-if="language == 'en'" />
</div>

Related

Show/hide next input field based on dropdown selection

I am new to Vue.js. I want to know how to show next input field based on previous dropdown menu selection. I have checked other forums and tried to implement but that didn't work.
Here is my code:
<select v-model="receive_method" id="">
<option value="cheque">Cheque</option>
<option value="eftn">EFTN</option>
<option value="cash">CASH</option>
</select>
<div v-if="receive_method === 'Cheque' ">
<input type="integer" v-model="cheque_number" placeholder="Cheque Number">
</div>
If I select cheque option from the dropdown list the next input field will appear else it will remain hidden.
Please help.
You need to reference the value of the options element.
If value="cheque" is lowercase, v-if="receive_method === 'cheque'" should too.
This works:
<script setup>
import { ref } from 'vue'
const receive_method = ref()
const cheque_number = ref()
</script>
<template>
<select v-model="receive_method" id="">
<option value="cheque">Cheque</option>
<option value="eftn">EFTN</option>
<option value="cash">CASH</option>
</select>
<div v-if="receive_method === 'cheque'">
<input type="integer" v-model="cheque_number" placeholder="Cheque Number">
</div>
</template>
If using Options API
<script>
export default {
data() {
return {
receive_method: undefined,
cheque_number: undefined
}
}
}
</script>

Modify checkbox behavior in vue js

I have this checkbox
<div class="form-check form-check-inline col-lg-2">
<input v-model="propertyData.fitness_centre" type="checkbox" class="form-check-input" id="dc_li_u" />
<label class="form-check-label" for="dc_li_u">Fitness Centre</label>
</div>
and i am saving the state in a database so when editing the state is restored and displays whether the checkbox was checked or not.
However, i need the checkbox to have a string value that is saved to the database when the checkbox is clicked such that when a checkbox has a string value, its checked and when the string value is empty the checkbox is not checked.
I have many checkboxes and so, i wanted the entire logic to be contained inside the checkbox. How can i modify the checkbox to do this?
You can use true-value and false-value attributes, to assign specific values when checking/unchecking.
new Vue({
el: "#app",
data: {
fitness_centre: "true value"
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="form-check form-check-inline col-lg-2">
<input v-model="fitness_centre" true-value="true value" false-value="" type="checkbox" class="form-check-input" id="dc_li_u" />
<label class="form-check-label" for="dc_li_u">Fitness Centre</label>
<div>Value: {{ fitness_centre }}</div>
</div>
</div>
You could use a change-event handler to set propertyData.fitness_centre to the desired value based on the checked state. Also bind <input>.checked to propertyData.fitness_centre so that the checked state is bound to the model's truthiness (empty string is false, otherwise true).
<template>
<input type="checkbox"
#change="onChange"
:checked="propertyData.fitness_centre"
value="fitness_centre">
</template>
<script>
export default {
data() {
return {
propertyData: { fitness_centre: '' }
}
},
methods: {
onChange(e) {
this.propertyData.fitness_centre = e.target.checked ? e.target.value : ''
}
}
}
</script>
demo

vue.js 2 inputs number and percentage how to bind the model

I have a downpayment form that have two inputs. One for dollar amount and one for percentage. I also have a slider that changes the percentage.
<div class="form-group">
<label for="">Down Payment</label>
<div class="flex-row d-flex">
<input class="form-control" type="text" v-model="downPaymentComputed" />
<input class="form-control" type="text" v-model="dpPercent">
</div>
<div class="mt-3 pt-4">
<vue-slider
v-model="dpPercent"
:tooltip="'always'"
:min="0"
:max="100"
:tooltip-formatter="formatter1"
></vue-slider>
</div>
</div>
in the script
let app = new Vue({
el: '#app',
delimiters: ['${', '}'],
components: {
VueSlider: window['vue-slider-component']
},
data: {
formatter2: v => `$${('' + v).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}`,
formatter1: '{value}%',
payment:null,
downPayment: {{ property.price*0.2 }},
dpPercent:'20',
price: {{ property.price }}
},
computed:{
downPaymentComputed(){
return this.price*(this.dpPercent/100)
}
},
In this configuration when I use the slider or enter the percentage, the downpayment changes. But when I enter new downpayment, nothing happens.
How do I bind so that when I change either the downpayment or the percent or the slider all inputs get updated?
EDIT: Thanks Phil, you pointed me in the right direction. I binded the values and then used on:change methods to update the other values
<input class="form-control" type="text" v-on:keyup="updateDP()" v-model="price" />
<input class="form-control" type="text" v-on:keyup="updatePercent()" v-model="downPayment" />
<input type="text" class="form-control" v-on:keyup="updateDP()" v-model="dpPercent">

Refresh v-model

I'm developing question paper application.
Once I type a question and hit the "+" button, the question goes to the question paper array and counter increased by one.
The problem is after I hit the "+" button, then also the question which I have entered previously is still in the fields of the UI. Because of I use v-model to bind the data fields.
What I want is a method to clear those previous question data in UI.
This is something similar to reset button function.
<template>
<div>
<div class="container" v-if="counter<=5">
<h2>Question {{counter}}</h2><hr>
<textarea rows="7" cols="75" v-model="question"></textarea><br><br>
1. Answer <input type="text" v-model="answer1"> <input type="radio" name="q1answer" value="1" v-model="correctAnswer"><br><br>
2. Answer <input type="text" v-model="answer2"> <input type="radio" name="q1answer" value="2" v-model="correctAnswer"><br><br>
3. Answer <input type="text" v-model="answer3"> <input type="radio" name="q1answer" value="3" v-model="correctAnswer"><br><br>
4. Answer <input type="text" v-model="answer4"> <input type="radio" name="q1answer" value="4" v-model="correctAnswer"><br>
<hr>
Knowledge Area <select v-model="knowledgeArea">
<option value="Maths">Mathematics</option>
<option value="Language">Language Skills</option>
<option value="gk">General Knowledge</option>
<option value="other">Other</option>
</select><br><br>
<button type="button" class="btn" #click="pushToArray" >
<span class="glyphicon glyphicon-plus"></span></button>
</div>
<div v-if="counter>5">
<button type="button" class="btn btn-primary" #click="onSubmit">Save Question Paper</button>
</div>
</div>
</template>
<script>
import axios from 'axios';
var questionPaper = [];
export default {
data () {
return {
question:'',
answer1:'',
answer2:'',
answer3:'',
answer4:'',
correctAnswer:'',
knowledgeArea:'',
counter:1,
show:true
}
},
methods: {
onSubmit () {
},
pushToArray(){
const formData = {
question: this.question,
correctAnswer: this.correctAnswer,
answer1: this.answer1,
answer2: this.answer2,
answer3: this.answer3,
answer4: this.answer4,
knowledgeArea:this.knowledgeArea
}
this.counter++;
questionPaper.push(formData);
}
}
}
</script>
Create a template data variable to use as a reset. For example
const templateData = {
question:'',
answer1:'',
answer2:'',
answer3:'',
answer4:'',
correctAnswer:'',
knowledgeArea:''
}
export default { // ...
use that to set your initial data
data() {
return {
counter: 1,
show: true,
...templateData
}
}
Now you can easily reset your data in the pushToArray method, eg
questionPaper.push(formData);
Object.assign(this, templateData);

vuejs set a radio button checked if statement is true

I am trying to make a radio button checked using vuejs v-for only if my if-statement is true. Is there a way to use vuejs' v-if/v-else for this type of problem?
in php and html I can achieve this by doing the following:
<input type="radio" <? if(portal.id == currentPortalId) ? 'checked="checked"' : ''?>>
Below is what I have so far using vuejs:
<div v-for="portal in portals">
<input type="radio" id="{{portal.id}}" name="portalSelect"
v-bind:value="{id: portal.id, name: portal.name}"
v-model="newPortalSelect"
v-on:change="showSellers"
v-if="{{portal.id == currentPortalId}}"
checked="checked">
<label for="{{portal.id}}">{{portal.name}}</label>
</div>
I know the v-if statement here is for checking whether to show or hide the input.
Any help would be very much appreciated.
You could bind the checked attribute like this:
<div v-for="portal in portals">
<input type="radio"
id="{{portal.id}}"
name="portalSelect"
v-bind:value="{id: portal.id, name: portal.name}"
v-model="newPortalSelect"
v-on:change="showSellers"
:checked="portal.id == currentPortalId">
<label for="{{portal.id}}">{{portal.name}}</label>
</div>
Simple example: https://jsfiddle.net/b4k6tpj9/
Maybe someone finds this approach helpful:
In template I assign each radio button a value:
<input type="radio" value="1" v-model.number="someProperty">
<input type="radio" value="2" v-model.number="someProperty">
Then in the component I set the value, i.e:
data: function () {
return {
someProperty: 2
}
}
And in this case vue will select the second radio button.
You can follow below option if you can adjust with your logic:
<div class="combination-quantity">
<input type="radio" value="Lost"
v-model="missing_status">
<label for="lost">Lost</label>
<br>
<input type="radio" value="Return Supplier" v-model="missing_status">
<label for="return_supplier">Return Supplier</label>
</div>
Value for missing_status could be "Lost" or "Return Supplier" and based on the value radio option will be get selected automatically.
Below is an example of keeping track of the selected radiobutton, by
applying a value binding to the object (:value="portal") and
applying a v-model binding to the currently selected object (v-model="currentPortal").
The radiobutton will be checked automatically by Vue, when the two match (no :checked binding necessary!).
Vue 3 with composition API
Vue.createApp({
setup() {
const portals = [{
id: 1,
name: "Portal 1"
}, {
id: 2,
name: "Portal 2"
}];
const currentPortal = portals[1];
return {
portals,
currentPortal
}
}
}).mount("#app");
<script src="https://unpkg.com/vue#next"></script>
<div id="app">
<template v-for="portal in portals">
<input
type="radio"
:id="portal.id"
name="portalSelect"
:value="portal"
v-model="currentPortal">
<label :for="portal.id">{{portal.name}}</label>
</template>
</div>
I would like to point out a few options when dealing with radios and vue.js. In general if you need to dynamically bind an attribute value you can use the shorthand binding syntax to bind to and calculate that value. You can bind to data, a computed value or a method and a combination of all three.
new Vue({
el: '#demo',
data() {
return {
checkedData: false,
checkedGroupVModel: "radioVModel3", //some defaul
toggleChecked: false,
recalculateComputed: null
};
},
computed: {
amIChecked() {
let isEven = false;
if (this.recalculateComputed) {
let timeMills = new Date().getMilliseconds();
isEven = timeMills % 2 === 0;
}
return isEven;
}
},
methods: {
onToggle() {
this.toggleChecked = !this.toggleChecked;
return this.toggleChecked;
},
mutateComputedDependentData() {
this.recalculateComputed = {};
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="demo">
<div>
<div>
<span>Simple Radio Group - Only one checked at a time. Bound to data.checkedData</span><br>
<label>Radio 1 - inverse of checkedData = {{!checkedData}}
<input type="radio" name="group1" value="radio1" :checked="!checkedData">
</label><br>
<label>Radio 2 - checkedData = {{checkedData}}
<input type="radio" name="group1" value="radio2" :checked="checkedData">
</label><br>
<span>Understanding checked attribute: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-checked</span>
</div>
<br>
<div>
<span>Simple Radio - Checked bouned to semi-random computed object</span><br>
<label>Radio 1: {{amIChecked}}
<input type="radio" :checked="amIChecked">
</label>
<label>Recalculate Computed Value
<button type="button" #click="mutateComputedDependentData">Click Me Several Times</button>
</label>
</div>
<br>
<div>
<span>Simple Radio Group - v-model bound value = {{checkedGroupVModel}}</span><br>
<label>Simple Radio 1:
<input type="radio" name="vModelGroup" value="radioVModel1" v-model="checkedGroupVModel">
</label><br>
<label>Simple Radio 2:
<input type="radio" name="vModelGroup" value="radioVModel2" v-model="checkedGroupVModel">
</label><br>
<label>Simple Radio 3:
<input type="radio" name="vModelGroup" value="radioVModel3" v-model="checkedGroupVModel">
</label>
</div>
<br>
<div>
<span>Simpe Radio - click handler to toggle data bound to :checked to toggle selection</span><br>
<label>Toggle Radio = {{toggleChecked}}
<input type="radio" :checked="toggleChecked" #click='onToggle()'>
</label>
</div>
</div>
</div>