Select v-model Object select - javascript

How we select item props together in v-model
I mean i select something only take one value.
I want to select value it should be binding name and dept together
Because i will push the these values on table.
<select v-model="name">
<option v-for="member in members" :key="member.id" :label="member.name" :value="member.name">
</option>
</select>
data(){
return {
members: [{id: 1, name: 'alpkaan', dept: 'quality'}]
}
}

I found one way it's running
:value="{'id':member.id, 'name':member.name}"
But;
Select button not work correctly. Because of v-model="name"
How solved this situation idk. :(

In your select you must have a variable that will contain the selected value,
an event that will listen to each value change and with a method related to this event, you will be able to browse your object array to find the object with the selected value.
NOTE : I delete the id with delete this.memberSelectedData.id but you can leave it if you need it, here is a screenshot.
And there is the code:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<select v-model="memberSelected" #change="slectMember()">
<option v-for="member in members" :key="member.id" :label="member.name" :value="member.name"></option>
</select>
<p>Member name : {{memberSelected}}</p>
<p>Member data : {{memberSelectedData}}</p>
</div>
</template>
<script>
export default {
name: "app",
data() {
return {
members: [{ id: 1, name: "alpkaan", dept: "quality" }, { id: 2, name: "alpkaan2", dept: "quality2" }],
memberSelected: "",
memberSelectedData: {}
};
},
methods: {
slectMember() {
this.members.map( member => {
if(member.name === this.memberSelected){
this.memberSelectedData = member
delete this.memberSelectedData.id
}
})
}
}
};
</script>

Related

Select Option for children it is behaving weird when parent is selected Angular

I am having an error during selecting the parent and its children on the select option.
The idea behind it is that I have for parent another select option and for the child another one.
I do have parent objects and as children nested objects which in my case are subCategory.
The problem it is that when the parent changes, the child it is empty and need to select on empty object that the list gets updated.
It is possible somehow that when parent is selected automatically show the children of the selected parent ?
Here is the code on stackblitz.
https://stackblitz.com/edit/angular-ivy-ujehrd?file=src/app/app.component.html
I have something like this.
<div class="col-md-12 pb-2">
<label>{{ "pagesInfo.categories" | translate }} </label>
<select
class="col-md-12 form-control-sm"
[ngModel]="page?.categories"
(ngModelChange)="showChildren($event)"
required
>
<option
*ngFor="let level of categoryService.categories"
[ngValue]="level"
[selected]="level"
(change)="showChildren(level)"
>
{{ level.description | translate }}
</option>
</select>
</div>
<div class="col-md-12 pb-2">
<label>{{ "categories.subCategories.name" | translate }} </label>
<select
class="col-md-12 form-control-sm"
[(ngModel)]="selectedChildren"
>
<ng-container>
<option
*ngFor="let subCat of selectedChildren"
[ngValue]="subCat"
>
{{ subCat.description | translate }}
</option>
</ng-container>
</select>
</div>
This is my TS to show the children.
selectedChildren = [];
showChildren(event) {
this.selectedChildren = [];
this.selectedChildren.push(event.subCategories);
}
And my categories looks like this.
export class Page {
_id: string;
name = "";
slogan = "";
description = "";
categories: Categories[];
}
export interface Categories {
description: string;
subCategory?: [{
name?: string,
tags?: [{
name: string
}]
}]
}
My service when I load the data.
public categories = [];
public getCategories() {
this.categories = [
{ id: Categories.Businesses, description: "categories.Businesses.name",
subCategories: [
{ id: BusinnesSubCategory.Advertising_Marketing, description: "categories.Businesses.Advertising_Marketing"},
{ id: BusinnesSubCategory.Agriculture, description: "categories.Businesses.Agriculture"}
] },
{ id: Categories.Community_Organization, description: "categories.Community_Organization.name",
subCategories: [
{ id: CommunityOrganizationSubCategory.Armed_Forces, description: "categories.Community_Organization.Armed_Forces"},
{ id: CommunityOrganizationSubCategory.Charity_Organization, description: "categories.Community_Organization.Charity_Organization"}
]},
{ id: Categories.Interest, description: "categories.Interest.name",
subCategories: [
{ id: InterestSubCategory.Literary_Arts, description: "categories.Interest.Literary_Arts"},
{ id: InterestSubCategory.Performance_Art, description: "categories.Interest.Performance_Art"},
As already pointed out by Faizal, you're using [(ngModel)]="selectedChildren" for the child select.
ngModel directive is used for the value of the <select> - you don't need to provide the list as a "model" for the selection.
The best solution is to use a different property as the model:
public selectedChild = null
`[(ngModel)]="selectedChild"`
Also there's a problem where you're pushing the whole subcategories into the selection so it is then an array of arrays of subcategories. Just assign the subcatecories as the children array.
this.selectedChildren = event.subCategories
See stackblitz: https://stackblitz.com/edit/angular-ivy-ysodem?file=src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fcategory.service.ts

Vue 3 custom checkbox component with v-model and array of items

Desperately in need of your help guys.
So basically I have a custom checkbox component whit a v-model. I use a v-for loop on the component to display checkboxes with the names from the array. In the parent component I have two columns Available and Selected. The idea is that if I check one of the boxes in the Available column it should appear on the Selected column. The problem is that it displays letter by letter and not the full name.
I am able to achieve the desired result without having a checkbox component, but since I will be needing checkboxes a lot throught my project I want to have a component for it.
Please follow the link for the code:
CodeSandBox
Dont mind the difference in styling.
The problem:
The desired outcome:
There are two problems. The first problem is, that you have your v-model set to v-model="filter.filterCollection", so a checkbox you select will be stored into the array as a string and if you select another checkbox the string gets overwritten. The second problem is, that you call that stored string as an array. That causes, that your string, which is an array of letters, will be rendered for each letter. So 'Number' is like ["N", "u", "m", "b", "e", "r"].
To solve your problem, you need to store every selection with its own reference in your v-model. To cover your needs of correct listing and correct deleting you need to apply the following changes:
Your checkbox loop
<Checkbox
v-for="(item, index) in items"
:key="item.id"
:label="item.name"
:id="index"
:isChecked="isChecked(index)" // this is new
#remove-selected-filter="removeSelectedFilter" // This is new
:modelValue="item.name"
v-model="filter.filterCollection[index]" // Change this
/>
Your v-model
filter: {
filterCollection: {} // Object instead of array
}
Methods in FilterPopUp.vue
methods: {
removeSelectedFilter(index) {
delete this.filter.filterCollection[index];
},
isChecked(index) {
return !!this.filter.filterCollection[index];
}
}
Your Checkbox.vue:
<template>
<label>
<p>{{ label }}</p>
<input
type="checkbox"
:id="id"
:value="modelValue"
:checked="isChecked"
#change="emitUncheck($event.target.checked)"
#input="$emit('update:modelValue', $event.target.value)"
/>
<span class="checkmark"></span>
</label>
</template>
<script>
export default {
name: "Checkbox",
props: {
modelValue: { type: String, default: "" },
isChecked: Boolean,
label: { type: String },
value: { type: Array },
id: { type: Number },
},
methods: {
emitUncheck(event) {
if(!event){
this.$emit('remove-selected-filter', this.id);
}
}
}
};
</script>
This should now display your items properly, delete the items properly and unselect the checkboxes after deleting the items.
StevenSiebert has correctly pointed to your errors.
But his solution is not complete, since the filters will not be removed from the collection when you uncheck one of them.
Here is my complete solution of your checkbox working as expected:
Checkbox.vue
<template>
<label>
<p>{{ label }}</p>
<input
type="checkbox"
:id="id"
v-model="checked"
#change="$emit('change', { id: this.id, checked: this.checked})"
/>
<span class="checkmark"></span>
</label>
</template>
<script>
export default {
name: "Checkbox",
props: {
modelValue: { type: Boolean, default: false },
label: { type: String },
id: { type: Number },
},
emits: ["change"],
data() {
return {
checked: this.modelValue
};
}
};
</script>
FilterPopUp.vue
<template>
...
<Checkbox
v-for="(item, index) in items"
:key="index"
:label="item.name"
:id="index"
#change="onChange"
/>
...
</template>
<script>
...
methods: {
removeSelectedFilter(index) {
this.filter.filterCollection.splice(index, 1);
},
onChange(args) {
const {id, checked} = args;
const item = this.items[id].name;
if (checked) {
if (this.filter.filterCollection.indexOf(item) < 0) {
this.filter.filterCollection.push(item);
}
} else {
this.filter.filterCollection = this.filter.filterCollection.filter( i=> i != item);
}
},
},
...
Here is the working CodeSandbox:
https://codesandbox.io/s/pensive-shadow-ygvzb?file=/src/components/Checkbox.vue
Sure, there are many ways to do it. If somebody has a nicer and shorter way to do it, please post your solution. It will be interesting to look at it.

How to enable second dropdown list only after the first dropdown is selected?

I've dynamically created three dropdown lists using v-for. Now, I have trouble performing the following task. For example,
1) I want the first dropdown list to be enabled so that users can select an option.
2) The second and third dropdowns cannot be selected yet and must be disabled.
3) After the user selected an option from the first dropdown, the second dropdown will be enabled but the third dropdown will remain disabled
4) After the user selected an option from the second dropdown, the third dropdown will be enabled for the user to select an option from it
Edit1 Still trying to solve this issue, help is greatly appreciated!
Edit2 Still trying to solve this, is there anyone that can help me?
Edit3 Here is a Codepen to work with https://codepen.io/Issaki/pen/RzzxvL
Below is my current code:
<template>
<div>
<!-- Dynamically create the select dropdowns using v-for -->
<div v-for="(attribute, index) in attributes" :key="index">
<label>{{attribute.type}}</label>
<!-- Dynamically render the id to keep track of which dropdown was selected -->
<select
#change="selectedValue($event)"
:id="'option' + index"
v-model="selectedValues[index]"
>
<option value>Select option</option>
<option v-for="(value, index) in attribute.values" :key="index">{{value}}</option>
</select>
</div>
</div>
</template>
<script>
export default {
data() {
return {
// Do note that, the size of this array is not fixed.
// At the moment, there is only three objects in the array
attributes: [
{
type: "Color",
values: ["Black", "White", "Yellow"]
},
{
type: "Size",
values: ["Small", "Medium", "Large"]
},
{
type: "Finish",
values: ["Shiny", "Glossy"]
}
],
selectedValues: []
};
},
methods: {
selectedValue(e) {
console.log(e);
console.log(this.selectedValues);
if (e.target.id === "option0") {
if (this.selectedValues[0] === "") {
document.getElementById("option1").disabled = true;
document.getElementById("option2").disabled = true;
} else {
document.getElementById("option1").disabled = true;
document.getElementById("option2").disabled = true;
}
}
}
}
};
</script>
I don't think there's any need to resort to element ids or direct manipulation of the DOM. You can keep it all in the template just by setting the disabled attribute depending on how many values have been selected.
Figuring out which select has been changed can be done just by passing the index to the #change handler.
new Vue({
el: "#app",
data: {
attributes: [
{
type: "Color",
values: ["Black", "White", "Yellow"]
},
{
type: "Size",
values: ["Small", "Medium", "Large"]
},
{
type: "Finish",
values: ["Shiny", "Glossy"]
}
],
selectedValues: []
},
methods: {
selectValue (index, value) {
const newValues = this.selectedValues.slice(0, index)
if (value) {
newValues.push(value)
}
this.selectedValues = newValues
}
}
})
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<div id="app">
<div v-for="(attribute, index) in attributes" :key="index">
<label>{{ attribute.type }}</label>
<select
#change="selectValue(index, $event.target.value)"
:value="selectedValues[index]"
:disabled="selectedValues.length < index"
>
<option :value="undefined">Select option</option>
<option v-for="(value, index) in attribute.values" :key="index">{{ value }}</option>
</select>
</div>
<div>{{ selectedValues }}</div>
</div>

Iterating over keys in data script

I am trying to figure out how to compare user input value from a dropdown menu with an objects of IDs with the keys matching the dropdown's options in Vue.
Example:
<template>
<select v-model="selectMenu">
<option v-for"select in selections">{{ selection }}</option>
</select>
</template>
<script>
export default {
data() {
return {
selectMenu: '',
selections: [ 'one', 'two', 'three' ],
ids: {
one: 'dfs745jfdb',
two: 'adfjdsh3gf5',
three: 'ag23dsgnsj'
}
}
}
}
</script>
I figured out how to do this a much easier way. i'm very new to vue and coding in general. What I did was combine selections and id's into a single array like this:
Solution:
<template>
<select v-model="selectMenu">
<option v-for"selectId in selectIds" v-bing:value="selectId.id">
{{ selectId.text }}
</option>
</select>
</template>
<script>
export default {
data() {
return {
selectMenu: '',
selectIds: [
{ text: 'one', id: 'dfs745jfdb' },
{ text: 'two' id: 'adfjdsh3gf5' },
{ text" 'three' id: 'ag23dsgnsj' }
]
}
}
}
</script>
this.ids[this.selectMenu] should give you the object in ids object.
You could try
Object.keys(this.ids).forEach(x => ... /* do stuff with this.ids[x] */)

Vue.js how to delete component v-for values

I am learning Vue, so I created radio button component, but I am struggling with how can one delete these values. My current solution deletes actual values, but selection is still displayed.
This is the component
<template id="fradio">
<div>
<div class="field is-horizontal">
<div class="field-label" v-bind:class = "{ 'required' : required }">
<label
class = "label"
>{{label}}
</label>
</div>
<div class="field-body">
<div>
<div class="field is-narrow">
<p class="control" v-for="val in values">
<label class = "radio">
<input
type="radio"
v-bind:name = "name"
v-bind:id = "name"
#click = "updateValue(val)"
>
<span>{{val[valueLabel]}}</span>
<span v-if="!valueLabel">{{val}}</span>
</label>
<label class="radio">
<button class="delete is-small" #click="removeValue"></button>
</label>
<slot></slot>
</p>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
label: {
type: String,
required: true,
},
inputclass: {
type: String,
},
required: {
type: Boolean,
default: false,
},
valueLabel:{
type: String,
},
returnValue:{
type: String,
},
values:{},
name:'',
},
data() {
return {
};
},
methods: {
updateValue: function (value) {
var selectedValue;
(!this.returnValue) ? selectedValue = value : selectedValue = value[this.returnValue];
this.$emit('input', selectedValue)
},
removeValue: function() {
this.$emit('input',null);
},
},
}
</script>
It should be easy, but I need someone to point out the obvious...
Update:
I just realized that you may be more focused on the data not dynamically updating, which means that your issue might be that the data in the parent component is not being updated. Most of your data is being passed down as props, so I'd need to see how the event is being fired in the parent component in order to help diagnose what's wrong. Based on the code you provided, it looks like your removeValue() function is emitting an event but I don't see any code that actually removes the value.
I would check the parent component to make sure that it is removing the child component and that should fix your problem!
Initial Answer:
Generally, when removing an item from a v-for list, you need to know the index of the item and use the Array.splice in order to modify the list to remove it.
Here's a generic example off the top of my head.
<template>
<ul>
<li v-for="(fruit, index) in fruits"
#click="removeItem(index)">
{{ fruit }}
</li>
</ul>
</template>
<script>
export default {
data() {
return {
fruits: ['Apple', 'Banana', 'Clementines']
}
},
methods: {
removeItem(index) {
this.fruits.splice(index, 1)
}
}
}
</script>
Let me know if you have any questions!

Categories

Resources