VueJS show input field conditionally - vue.js

I have a button 'Add Field' and when I click it, I show a select box with several predefined options.
Now, below this select box I want to display another select box if the value selected in the select field is equal to, let's say, 'Hello', otherwise display an input field but I am struggling to achieve this.
Right now, my code looks like this:
<div v-for="option in folder.salary.fields" :key="option.id">
<b-form-group label="Select field" label-for="salaryOptionField">
<select
v-model="folder.salary.fields.name"
value-field="id"
#change="onOptionSelected"
>
<option :value="null" disabled>Select type</option>
<option v-for="(type, key) in salaryFields" :value="key">
{{ salaryFields[key] }}
</option>
</select>
<template v-if="folder.salary.fields.name === 'Hello'">
<b-form-group label="Name" label-for="name">
<input type="text"
name="name"
v-model="folder.salary.benefits.a"
required/>
</b-form-group>
</template>
</b-form-group>
</div>
<b-btn #click="addNewSalaryField" variant="primary">Add Field</b-btn>
addNewSalaryField(){
this.folder.salary.fields.push({
name: '',
amount: ''
})
}
data() {
return {
folder: {
pages: [],
salary: {
fields: [],
benefits: []
}
}
}
}
Right now, if I select 'Hello' from the select field, nothing happens. Appreciate your help.

Related

how to show a suggestion list on inputting a tag in bootstrap vue?

I am working on a Vue Assignment. For styling I am using BootstapVue. What I need to achieve is, whenever an user is entering a text in the input field, a filtered array that is containing the value should be displayed as dropdown. The User can either press Enter key stroke or select the value from dropdown. If the input text is not in the array, then the user should not be able to enter the value i.e. the tag might not be created. For example, whenever we are creating a question here in Stack Overflow, upon typing tags and entering or selecting from the suggestion cards. I I need similar functionality except that if the input text is not in the suggestion array, the user will not be able to create the tag
Here's what I have tried so far :
App.vue
<template>
<div>
<b-form-tags
v-model="value"
#input="resetInputValue()"
tag-variant="success"
:state="state"
>
<template v-slot="{ tags, inputId, placeholder, addTag, removeTag }">
<b-input-group>
<b-form-input
v-model="newTag"
list="my-list-id"
:id="inputId"
:placeholder="placeholder"
:formatter="formatter"
#keypress.enter="addTag(newTag)"
></b-form-input>
</b-input-group>
<b-form-invalid-feedback :state="state">
Duplicate tag value cannot be added again!
</b-form-invalid-feedback>
<ul v-if="tags.length > 0" class="mb-0">
<li
v-for="tag in tags"
:key="tag"
:title="`Tag: ${tag}`"
class="mt-2"
>
<span class="d-flex align-items-center">
<span class="mr-2">{{ tag }}</span>
<b-button
size="sm"
variant="outline-danger"
#click="removeTag(tag)"
>
remove tag
</b-button>
</span>
</li>
</ul>
<b-form-text v-else>
There are no tags specified. Add a new tag above.
</b-form-text>
</template>
</b-form-tags>
<datalist id="my-list-id">
<option>Manual Option</option>
<option v-for="(size, ind) in sizes" :key="ind">{{ size }}</option>
</datalist>
</div>
</template>
<script>
export default {
data() {
return {
newTag: "",
value: [],
sizes: ["Small", "Medium", "Large", "Extra Large"],
};
},
computed: {
state() {
// Return false (invalid) if new tag is a duplicate
return this.value.indexOf(this.newTag.trim()) > -1 ? false : null;
},
},
methods: {
resetInputValue() {
this.newTag = "";
},
formatter(value) {
if (this.sizes.includes(value)) {
return value.toUpperCase();
}
return ;
},
},
};
</script>
How can I achieve the same? Thanks
You can achieve it by using b-form-datalist with the use of <b-form-input> by adding a change event to reset the input value if there is no data in the dataList as per the search value.
Demo :
new Vue({
el: '#app',
data: {
sizes: ['Small', 'Medium', 'Large', 'Extra Large'],
tag: null
},
methods: {
checkTag(e) {
const tagsAvailable = this.sizes.filter((item) => item === e);
if (!tagsAvailable.length) {
this.tag = ''
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.21.2/bootstrap-vue.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.21.2/bootstrap-vue.min.css"/>
<div id="app">
<b-form-input list="my-list-id" v-model="tag" v-on:change="checkTag($event)"></b-form-input>
<datalist id="my-list-id">
<option>Manual Option</option>
<option v-for="size in sizes">{{ size }}</option>
</datalist>
</div>

How do you make default option with V-bind when using an object?

So I have the following code in vue.js:
<template>
...
<div v-for="guest in guests" :key="guest">
<label for="attendance">Will {{guest}} be attending? </label>
<select v-model="attendance[guest]" id='attendance'>
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
<br><br>
</div>
...
<script>
...
data() {
return {
guests: {},
numGuests: 0,
sleepOver: null,
attendance: { },
};
I am trying to make yes default. I've read other solutions that says the v-model overrides it. The solutions I have found seem not to apply to my specific code. I tried putting it in my attendance and it does not work. Any suggestions related to my code?
Hope it will help you fix the issue
Step 1: First correct your model. When you are going with v-for always model it should be an array. so guests should be an array which having the property on name and willBeAttending property
data () {
return {
guests: [{
name: 'Jeba',
willBeAttending: 'yes'
},
{
name: 'Suthan',
willBeAttending: 'no'
}],
numGuests: 0,
sleepOver: null,
}
}
Step 2: Template should be like below
<div v-for="(guest, $index)" in guests" :key="$index">
<label for="attendance">Will {{guest.name}} be attending? </label>
<select v-model="guest.willBeAttending" id='attendance'>
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
<br><br>
</div>
DEMO

Vue-Multiselect: How to autopopulate rest of input fields after first selection made?

I am using Vue-Multiselect plugin and want to know how I can auto populate additional input fields (customer_firstname and customer_email) when a user selects an item from the initial drop down?
Scenario: If the name exists in the database/drop-down list the user can then select that name and Vue will auto populate the rest of the input fields (taken from the options array). Else, if the name does not exist, the user can tag/create a new value for each additional input fields (e.g, customer_firstname, customer_email).
Here's my JSFIDDLE code with evertying working, just need help wiring up the ability to autopopulate the rest of the input fields based on the initial selection of the lastname dropdown.
Vue Template:
<div id="app">
<div>
Last Name:
<multiselect id="dontforget" v-model="customer_last_name" :options="options" placeholder="Select an existing customer or type to add a new one" label="lastname" :custom-label="customerSelectName" track-by="uid" :close-on-select="true" :clear-on-select="false" :hide-selected="true" :preserve-search="true" #select="onSelect" :taggable="true" #tag="addTag" :multiple="false" tag-placeholder="Add customer as new customer">
<template slot="singleLabel" slot-scope="props">{{ props.option.lastname }}</template>
<template slot="option" slot-scope="props">
<span style="font-weight: bold;">{{ props.option.lastname }}</span>, {{ props.option.firstname }} -- <small>{{props.option.email}}</small>
</template>
<template slot="noResult">no rsults brah</template>
</multiselect>
<pre class="language-json"><code>Data: {{ customer_last_name }}</code></pre>
<br>
<br>
<br>
<label for="customer_first_name_input">First Name:</label><br>
<input id="customer_first_name_input" type="text" v-model="customer_first_name" />
<br>
<label for="customer_emailt">Email:</label><br>
<input id="customer_email" type="email" v-model="customer_email" />
</div>
</div>
Vue Script:
new Vue({
components: {
Multiselect: window.VueMultiselect.default
},
data: {
customer_last_name: '',
customer_first_name: '',
customer_email: '',
options: [{"uid":"1","firstname":"John","lastname":"Doe","email":"johndoe#aol.com","phone":null,"c_organization":"ACME","c_title":null}, {"uid":"2","firstname":"Mary","lastname":"Smith","email":"msmith#aol.com","phone":null,"c_organization":"NBA","c_title":"Miss"}, {"uid":"3","firstname":"Mike","lastname":"Verlander","email":"asdafsdf#aol.com","phone":null,"c_organization":"MLB","c_title":"Mr"}]
},
methods: {
addTag (newTag) {
const parts = newTag.split(', ');
const tag = {
uid: this.options.length + 1,
firstname: parts.pop(),
lastname: parts.pop()
}
this.options.push(tag)
this.customer_last_name = tag;
},
customerSelectName (option) {
return `${option.lastname}, ${option.firstname}`
},
onSelect (option, uid) {
console.log(option, uid)
}
}
}).$mount('#app')
You pretty much have everything you need. Your method onSelect is appended to the select event of your multiselect, so you can just use it.
In your onSelect method, add these lines:
this.customer_first_name = option.firstname;
this.customer_email = option.email;
That will assign to your variables the properties of the object you get when you select an option.

How to get object relation inside <option> loop in Vue?

Let's go to the point of the question. I have a selection component, it looks like this:
<template>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="category_id">
Product Category
</label>
<select
name="category_id"
id="category_id"
:class="form.errors.has('category_id') ? 'form-control is-invalid' : 'form-control'"
v-model="form.sharedState.category_id">
<option value="" disabled hidden>Select Category</option>
<option
v-for="category in categories"
:key="category.id"
v-text="category.name"
:value="category.id"
#click="$emit('category-selected', category.sub_categories)">
</option>
</select>
<small
class="form-text text-danger"
v-if="form.errors.has('category_id')"
v-text="form.errors.get('category_id')"></small>
</div>
</div>
<div class="col-md-6">
<div
class="form-group"
v-if="revealSubCategory"
#category-selected="show">
<label for="category_id">
Sub Category
</label>
<select
name="sub_category_id"
id="sub_category_id"
:class="form.errors.has('sub_category_id') ? 'form-control is-invalid' : 'form-control'"
v-model="form.sharedState.sub_category_id">
<option value="" disabled hidden>Select Sub Category</option>
<option
v-for="subcategory in subcategories"
:key="subcategory.id"
v-text="subcategory.name"
:value="subcategory.id">
</option>
</select>
<small
class="form-text text-danger"
v-if="form.errors.has('category_id')"
v-text="form.errors.get('category_id')"></small>
</div>
</div>
</div>
</template>
<script>
import BaseCard from './BaseCard.vue';
export default {
components: {
BaseCard
},
data() {
return {
categories: [],
revealSubCategory: false,
subcategories: [],
form: new Form({
sharedState: product.data
})
}
},
mounted() {
this.getCategories();
},
methods: {
getCategories() {
axios.get('categories')
.then(({data}) => this.categories = data);
},
show(subcategories) {
this.revealSubCategory = true;
this.subcategories = subcategories
}
}
}
</script>
And a select sub category input (it is there on the second column) which is will be displayed once the user has selected one of the categories options. Each category option has relation to sub categories taken from the API.
How can I get the sub categories and display the input? I already tried #change on the select tag but I can't pass the sub category object because it is outside the loop. And #click event seems to be not working in an option tag.
You can watch the v-model of the first select and change subcategory.
watch:{
"form.sharedState.category_id": function (val) {
// update subcategories here
}

Why required not working in vue.js 2?

You can see my case below
My vue component is like this :
<template>
<select class="form-control" :name="elementName" v-model="selected" :required="module === 'addProduct'" >
<option>Choose</option>
<option v-for="option in options" v-bind:value="option.id" >{{ option.name }}</option>
</select>
</template>
<script>
...
export default {
...
props: ['elementName', 'module'],
data() {
return {
selected: 'Choose'
};
},
...
};
</script>
The result is like this :
I don't select anything. I click button submit, the required not working. It not display the required
I try like this :
<option value="">Choose</option>
It works. But, when accessed first time, option choose not show
How can I solve this problem?
See their example: https://v2.vuejs.org/v2/guide/forms.html#Select
It doesn't display anything because you have: selected: 'Choose' but you have no option with value="Choose". (the value is the empty string, "Choose" is just the inner text of the option element).
Try this:
<template>
<select class="form-control" :name="elementName" v-model="selected" :required="module === 'addProduct'" >
<option disabled value="">Choose</option>
<option v-for="option in options" v-bind:value="option.id" >{{ option.name }}</option>
</select>
</template>
<script>
...
export default {
...
props: ['elementName', 'module'],
data() {
return {
selected: ''
};
},
...
};
</script>