I'm looking for some help, please? I have 3 select menus which have to display certain subjects depending on the previous selections.
One of the things I'm struggling with is how do I remove whatever the first selection is in menu one from both menu two and menu three?
Any help is greatly appreciated.
<template>
<select v-model="one">
<option disabled value>Select subject one</option>
<option v-for="subject in select1" :key="subject">
{{ subject }}
</option>
</select>
<select v-model="two" :disabled="!one">
<option disabled value>Select subject two</option>
<option v-for="subject in select2" :key="subject">
{{ subject }}
</option>
</select>
<select v-model="three" :disabled="!two">
<option disabled value>Select subject three</option>
<option v-for="subject in select3" :key="subject">
{{ subject }}
</option>
</select>
<div v-if="one">
<ul>
You have selected:
<li>{{ one }}</li>
<li>{{ two }}</li>
<li>{{ three }}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
subjects: [
"Subjectone",
"Subjecttwo",
"Subjectthree",
"Subjectfour",
"Subjectfive",
],
one: "",
two: "",
three: "",
selectOne: {
Subjectone: [
"Subjecttwo",
"Subjectthree",
"Subjectfour",
"Subjectfive",
],
Subjecttwo: ["Subjectone", "Subjectfive"],
Subjectthree: ["Subjectone", "Subjectfive"],
Subjectfour: ["Subjectone", "Subjectfive"],
Subjectfive: [
"Subjectone",
"Subjecttwo",
"Subjectthree",
"Subjectfour",
],
},
selectTwo: {
Subjectone: [
"Subjecttwo",
"Subjectthree",
"Subjectfour",
"Subjectfive",
],
Subjecttwo: ["Subjectone", "Subjectfive"],
Subjectthree: ["Subjectone", "Subjectfive"],
Subjectfour: ["Subjectone", "Subjectfive"],
Subjectfive: [
"Subjectone",
"Subjecttwo",
"Subjectthree",
"Subjectfour",
],
},
selectThree: {
Subjecttwo: ["Subjecttwo", "Subjectthree", "Subjectfour"],
Subjectthree: ["Subjectthree", "Subjectfour", "Subjecttwo"],
Subjectfour: ["Subjectthree", "Subjectfour", "Subjecttwo"],
},
};
},
computed: {
select1() {
return this.subjects;
},
select2() {
if (this.one) {
return this.subjects.filter((s) =>
this.selectOne[this.one].includes(s)
);
}
return this.subjects;
},
select3() {
if (
this.one == "Subjectthree" ||
this.one == "Subjectfour" ||
this.two == "Subjectthree" ||
this.two == "Subjectfour"
) {
return this.subjects.filter(
(subject) => !["Subjectthree", "Subjectfour"].includes(subject)
);
}
if (this.one == "Subjecttwo" || this.two == "Subjecttwo") {
return this.subjects.filter(
(subject) =>
!["Subjectthree", "Subjectfour", "Subjecttwo"].includes(subject)
);
}
if (this.two) {
return this.subjects.filter((s) =>
this.selectTwo[this.two].includes(s)
);
}
return this.subjects;
},
},
};
</script>
<style>
li {
display: inline-block;
}
ul li + li:not(:last-child):before {
content: ", ";
}
ul li + li:last-child:before {
content: "\00a0&\00a0";
}
ul li:last-child:after {
content: ".";
}
</style>
You can filter the select as follows:
select2() {
if (this.one) {
return this.subjects.filter(sub => sub !== this.one);
}
return this.subjects;
},
select3() {
if (this.one && this.two) {
return this.subjects.filter(sub => ![this.one, this.two].includes(sub));
} else {
if (this.one && !this.two) {
return this.select2
}
if (this.two && !this.one) {
return this.subjects.filter(sub => sub !== this.two);
}
return this.subjects;
}
}
Related
In my application I have a list of documents that I display in a table, each document has a specific type, which is specified in json file as enum values.
I can already display all the documents without any problems, but now I have tried to create an input where the user can choose from the list of enum values, and when doing so only the documents with the selected enum type will be shown in the table.
This does sorta work, but the problem is that I have somehow created an infinite update loop, which causes the application to randomly stop working.
This is the template. I am using a custom made template component, but that is not related to the issue.
<template>
<b-container>
<div #dragover.prevent.stop #drop.prevent.stop="onDropEvent">
<b-card-header header-tag="header" class="p-1" role="tab">
<b-button-toolbar justify>
<b-button
:class="showCollapse ? 'collapsed' : null"
#click="showCollapse = !showCollapse"
variant="outline-info"
class="flex-grow-1"
>
<span class="float-left">{{ folderName }}</span>
<span class="float-right">
{{
search ?
$t('documentCountFiltered', {filtered: filteredDocuments.length, count: documents.length}) :
$tc('documentCount', documents.length)
}}
</span>
</b-button>
<template v-if="!inherited && mode !== 'READ_ONLY'">
<label class="document-uploader btn btn-sm btn-outline-primary ml-2">
<span>
<i class="fas fa-fw fa-file-upload"></i>
{{ $t('uploadFiles') }}
</span>
<input type="file" multiple #change="selectFiles">
</label>
<b-dropdown
v-if="mode !== 'READ_ONLY' && mode !== 'RESTRICTED'"
size="sm" variant="outline-primary" class="ml-2 template-dropdown" no-caret right>
<template slot="button-content">
<i class="fas fa-fw fa-file-medical"></i> {{ $t('createDocument') }}
</template>
<b-dropdown-header v-if="companyTemplates.length !== 0" id="dropdown-header-templates">
{{ $t('companyTemplates') }}
</b-dropdown-header>
<b-dropdown-item v-if="companyTemplates.length !== 0" v-for="template of companyTemplates"
#click="emitWordDocumentCreateSelectEvent(template)">
{{ template.name }} <i v-if="template.freeTextEnabled" class="fa-fw fas fa-paragraph"></i>
</b-dropdown-item>
<b-dropdown-divider
v-if="companyTemplates.length !== 0 && companyFormBuilderTemplates.length > 0"></b-dropdown-divider>
<b-dropdown-header v-if="companyFormBuilderTemplates.length > 0" id="dropdown-header-inheritedDocuments">
{{ $t('formBuilderTemplates') }}
</b-dropdown-header>
<b-dropdown-item
v-for="template of companyFormBuilderTemplates"
#click="emitDocumentCreateSelectEvent(template)">
{{ template.name }}
</b-dropdown-item>
<b-dropdown-divider
v-if="globalTemplates.length !== 0"></b-dropdown-divider>
<b-dropdown-header v-if="globalTemplates.length > 0" id="dropdown-header-globalDocuments">
{{ $t('globalTemplates') }}
</b-dropdown-header>
<b-dropdown-item
v-for="template of globalTemplates"
#click="emitGlobalDocumentCreateSelectEvent(template)">
{{ template.name }}
</b-dropdown-item>
</b-dropdown>
</template>
</b-button-toolbar>
</b-card-header>
<b-form-group class="mt-4">
<w-b-form-select v-model="filteredDocumentType">
<template>
<b-form-select-option :value="null" disabled>-- {{ $t('selectDocumentByType') }} --</b-form-select-option>
</template>
<b-form-select-option :value="'all'">({{ $t('all') }})</b-form-select-option>
<option v-for="documentType in availableDocumentTypes" :key="documentType" :value="documentType">
{{ $t('model.document.types.' + documentType) }}
</option>
</w-b-form-select>
</b-form-group>
<b-collapse v-model="showCollapse">
<common-table
:fields="fields"
:items="filteredDocuments"
primary-key="id"
sort-by="creationDateTime"
sort-desc
>
<template slot="head(select)">
<check-all-checkbox :list="filteredDocuments" #change="handleTag(documents, $event)" property="selected"/>
</template>
<template slot="cell(select)" slot-scope="data">
<w-b-form-checkbox v-model="data.item.selected" v-if="data.item.selected != null"
#change="handleTag([data.item], $event)" data-test-id="check-box"/>
</template>
<template slot="cell(name)" slot-scope="data">
<div class="d-flex">
<div style="flex: 2 0 0">
<b-dropdown :text="data.item.name" variant="link" toggle-class="name-cell">
<b-dropdown-item #click="viewFile(data.item)" v-if="data.item.type != 'EMAIL'"><i
class="fas fa-eye"></i> {{ $t('showDocument') }}
</b-dropdown-item>
<b-dropdown-item #click="downloadFile(data.item)"><i class="fas fa-file-download"></i> {{
$t('download')
}}
</b-dropdown-item>
</b-dropdown>
</div>
<div style="flex: 1 0 0" v-if="data.item.uploading">
<b-progress :animated="!data.item.error" striped class="h-100">
<b-progress-bar
:value="100"
:variant="data.item.error ? 'danger' : 'primary'"
:label="data.item.error ? 'Error' : 'Uploading...'"
/>
</b-progress>
</div>
</div>
</template>
</common-table>
</b-collapse>
<p-d-f-j-s-viewer ref="pdf-viewer"/>
</div>
</b-container>
</template>
My script
<script>
import CheckAllCheckbox from '#/components/CheckAllCheckbox';
import CommonTable from '#/components/common/CommonTable';
import CommonInput from '#/components/common/CommonInput';
import {applianceService} from '#/services/appliance';
import PDFJSViewer from '#/components/PDFJSViewer';
import axios from '#/config/axios';
import {documentService} from '#/services/document';
import documentTypes from '#/models/document/type';
import {propertyFacilityService} from '#/services/property-facility';
import CommonCollapsible from '#/components/common/CommonCollapsible';
export default {
props: {
documents: Array,
documentOwnerType: String,
companyTemplates: Array,
companyFormBuilderTemplates: Array,
globalTemplates: Array,
inherited: Boolean,
startCollapsed: {
type: Boolean,
default: false
},
mode: String,
search: String,
applianceId: String,
propertyFacilityId: String,
noteId:String
},
components: {
CheckAllCheckbox,
CommonTable,
CommonCollapsible,
CommonInput,
PDFJSViewer
},
data() {
return {
documentTypes,
showCollapse: true,
filteredDocumentType: null
};
},
computed: {
filteredDocuments() {
console.log(this.filteredDocumentType)
console.log(this.documents)
if (this.filteredDocumentType === null || this.filteredDocumentType === 'all') {
return (this.documents ?? []).filter(document =>
(document.name.toUpperCase().includes(this.search.toUpperCase()) ||
this.$t(`model.document.types.${document.type}`).toUpperCase().includes(this.search.toUpperCase())))
}
else {
return (this.documents ?? []).filter(document =>
(document.name.toUpperCase().includes(this.search.toUpperCase()) ||
this.$t(`model.document.types.${document.type}`).toUpperCase().includes(this.search.toUpperCase())) &&
document.type === this.filteredDocumentType)
}
},
folderName() {
if (this.inherited) {
return this.$t('sharedDocuments');
} else if (this.documentOwnerType === 'COMPANY') {
return this.$t('companyDocuments');
} else {
return this.$t('documents');
}
},
availableDocumentTypes() {
return this.documentTypes.sort((a, b) => this.getDocumentTypeText(a).localeCompare(this.getDocumentTypeText(b)));
},
fields() {
return [
{
key: 'select',
thStyle: 'width: 1%'
},
{
key: 'name',
label: this.$t('name'),
sortable: true
},
{
key: 'inherited',
label: this.$t('inherited'),
formatter: inherited => this.$t(inherited ? 'yes' : 'no'),
sortable: true,
hide: this.inherited
},
{
key: 'sharedOnTC',
label: this.$t('sharedOnTC'),
formatter: sharedOnTC => this.$t(sharedOnTC ? 'yes' : 'no'),
sortable: true,
hide: this.sharedOnTC
},
{
key: 'type',
label: this.$t('type'),
formatter: type => this.$t('model.document.types.' + type),
sortable: true,
sortByFormatted: true
},
{
key: 'tags',
label: this.$t('tags'),
formatter: tags => tags.join(', '),
sortable: true,
sortByFormatted: true
},
{
key: 'signed',
label: this.$t('signed'),
formatter: sharedOnTC => this.$t(sharedOnTC ? 'yes' : 'no'),
sortable: true,
sortByFormatted: true
},
{
key: 'creationDateTime',
label: this.$t('created'),
sortable: true,
template: {type: 'date', format: 'L LT'}
},
{
key: 'changedDateTime',
label: this.$t('changed'),
sortable: true,
template: {type: 'date', format: 'L LT'}
},
{
key: 'actions',
hide: this.inherited || this.mode === 'READ_ONLY',
template: {
type: 'actions',
cell: [
{
icon: 'fa-edit',
tooltip: this.$t('edit'),
if: this.mode !== 'RESTRICTED',
disabled: data => data.item.uploading || !data.item.documentTemplateId || data.item.signed,
action: data => this.emitDocumentEditTemplateSelectEvent(data.item)
},
{
icon: 'fa-cog',
tooltip: this.$t('documentSettings'),
disabled: data => data.item.uploading,
action: data => this.emitDocumentEditSelectEvent(data.item)
},
{
icon: 'fa-trash',
variant: 'outline-danger',
disabled: data => data.item.uploading,
action: data => this.emitDocumentDeleteSelectEvent(data.item)
}
]
}
}
].filter(field => !field.hide);
}
},
methods: {
getDocumentTypeText(type) {
return this.$t(`model.document.types.${type}`);
},
selectFiles(event) {
this.emitFileUploadEvent(event.target.files);
event.target.value = '';
},
onDropEvent(event) {
this.emitFileUploadEvent(event.dataTransfer.files);
},
downloadFile(document) {
documentService.downloadDocument(document.id)
.catch(error => {
console.error(error);
});
},
viewFile(document) {
documentService.getPublicDownloadToken(document.id).then(result => {
let fileName = `${axios.defaults.baseURL}/file/public/${result.data}/download`;
this.$refs['pdf-viewer'].show(fileName);
}).catch(error => {
console.error(error);
});
},
emitGlobalDocumentCreateSelectEvent(template) {
this.$emit('document-global-create-select', template);
},
emitDocumentCreateSelectEvent(template) {
this.$emit('document-create-select', template);
},
emitWordDocumentCreateSelectEvent(template) {
this.$emit('document-word-create-select', template);
},
emitDocumentEditSelectEvent(document) {
documentService.getDocument(document.id).then(result => {
document = result.data;
this.$emit('document-edit-select', document);
});
},
emitDocumentEditTemplateSelectEvent(document) {
this.$emit('document-edit-template-select', document);
},
emitDocumentDeleteSelectEvent(document) {
this.$emit('document-delete-select', document);
},
emitFileUploadEvent(files) {
if (files && files.length) {
this.$emit('file-upload', [...files]);
}
},
handleTag(documents, selected) {
if (this.applianceId) {
applianceService.updateDocuments(this.applianceId, {
documentIds: documents.map(doc => doc.id), selected: selected
}).then(({data: documents}) => {
documents.forEach(doc => {
this.documents.splice(this.documents.findIndex(d => d.id === doc.id), 1,
Object.assign(doc, {selected: selected}));
});
});
}
if (this.propertyFacilityId) {
propertyFacilityService.updateDocuments(this.propertyFacilityId, {
documentIds: documents.map(doc => doc.id), selected: selected
}).then(({data: documents}) => {
documents.forEach(doc => {
this.documents.splice(this.documents.findIndex(d => d.id === doc.id), 1,
Object.assign(doc, {selected: selected}));
});
});
}
}
},
created() {
this.showCollapse = !this.startCollapsed;
}
};
</script>
I have a dropdown menu that triggers a method to get data based on what is selected in the dropdown. I would like to add a condition that changes the #change method if a checkbox is selected. The method would switch based on which checkbox is selected. I guess a v-if that runs a check somewhere--Im not sure.
new Vue({
el: "#app",
data: {
selection: 'Select a option',
todos: [{
name: 'apple'
}, {
name: 'oranges'
}, {
name: 'carrots'
}]
},
methods:{
changeP (event) {
this.getSetA();
// alert("this is set a");
},
changeP1 (event) {
this.getSetB();
alert("this is set b");
},
changeP2 (event) {
this.getSetC();
alert("this is set c");
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Fruit:</h2>
<select v-model="selection" #change="changeP($event)">
<option value="Select a option" disabled>Choose an fruit:</option>
<option v-for="(t, i) in todos" :key="i" :value="t.name">{{ t.name }}</option>
</select>
<br>
<input type="checkbox" id="vehicle1" name="vehicle1" value="apple"> Apples
<input type="checkbox" id="vehicle2" name="vehicle2" value=""> Oranges
<input type="checkbox" id="vehicle3" name="vehicle3" value="">pears
</div>
new Vue({
el: '#app',
data: {
selection: 'Select an option',
selectOptions: [ { name: 'apple' }, { name: 'oranges' }, { name: 'carrots' }],
checkboxOptions: [ 'vehicle1', 'vehicle2', 'vehicle3' ],
checkedItems: [],
message: '',
},
methods: {
onDropdownChange() {
this.message = '';
if (this.checkedItems.length) {
this.message = `You've selected: `;
for(let i = 0; i < this.checkedItems.length; i++) {
this.message += this.checkedItems[i] + ' ';
}
}
switch(this.selection) {
case 'apple':
return this.onAppleSelected();
case 'oranges':
return this.onOrangesSelected();
default:
return this.onCarrotsSelected();
}
},
onAppleSelected() {
if (this.message.length) {
this.message += 'and apple.';
return;
}
this.message = `You've selected apple`;
},
onCarrotsSelected() {
this.message += ' CARROT!'
},
onOrangesSelected() {
this.message += ' No Scurvy';
}
},
template: `
<div id="app">
<h2>Fruit:</h2>
<select v-model="selection" #change="onDropdownChange">
<option value="Select an option">Choose</option>
<option v-for="(o, i) in selectOptions" :key="o.name" :value="o.name">{{o.name}}</option>
</select>
<div style="display:block" v-for="(o, i) in checkboxOptions" :key="o">
<label :for="o">{{o}}</label>
<input type="checkbox" :id="o" :name="o" :value="o" v-model="checkedItems" />
</div>
<p>{{message}}</p>
</div>
`
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
</div>
You should probably have a single method that decides which method to call based on the state of the component.
I am trying to remove item from my list , i am using js delete operator but it can't , here is the code
HTML :
<ol v-if="status">
<li v-for="(item, key) in items" :key="item.title">
{{ item.title }} - Type - {{ item.type }}
<input v-model="item.type" type="text" value="{{ item.type }}" style="margin-left: 2%;" />
<button #click="delete items[key]">Remove Items</button>
</li>
</ol>
JS :
const sample = {
data() {
return {
newItem: [
{title: "", type: ""}
],
subject: 'Vue.js',
items: [
{ title: 'Javascript', type: 'Native'},
{ title: 'Vue', type: 'Framework'},
{ title: 'React', type: 'Framework'},
{ title: 'Angular', type: 'Framework'},
],
item: 'Javascript',
status: 1
}
},
}
Vue.createApp(sample).mount('#app')
you need to declare a proper method for your #click event:
<button #click="deleteItem(key)">Remove Items</button>
then, in your vue, methods section, declare this function:
methods:{
deleteItem(key){
this.items.splice(key, 1)
},
},
your complete vue code will be this :
const sample = {
data() {
return {
newItem: [
{title: "", type: ""}
],
subject: 'Vue.js',
items: [
{ title: 'Javascript', type: 'Native'},
{ title: 'Vue', type: 'Framework'},
{ title: 'React', type: 'Framework'},
{ title: 'Angular', type: 'Framework'},
],
item: 'Javascript',
status: 1
}
},
methods:{
deleteItem(key){
this.items.splice(key, 1)
},
},
}
Vue.createApp(sample).mount('#app')
Hi In your #onclick u dont use correctly ur function u most to do something like this :
<ol v-if="status">
<li v-for="(item, key) in items" :key="item.title">
{{ item.title }} - Type - {{ item.type }}
<input v-model="item.type" type="text" value="{{ item.type }}" style="margin-left: 2%;" />
<button #click="delete(item)">Remove Items</button>
</li>
</ol>
And here, delete is a function for delete ur item in items like this function
delete(item){
this.items.splice(item.title, 1)
},
In my component, i have multiselect that should get options selected on matched value passed:
<select class="custom-select" multiple="" v-model="items">
<option v-for="item in objects_list" :selected="itemSelected(item)" :key="item.id" :value="item.id">
{{item.name}}
</option>
</select>
...
methods() {
itemSelected(item) {
let selected;
let object_selected = this.value.filter(object => {
console.log(object)
if(item.id == object) {
return true;
}
});
}
the selected binding doesn't seems to work, how to correctly implement multiselect to bind selected options ?
The best way to do this is to use the CREATED Function from Vue.js
<template>
<div>
<select class="ur-CSS-class" multiple v-model="selected">
<option v-for="item in objects_list" :key="item.id" :value="item.id">
{{ item.name }}
</option>
</select>
<br />
<span>Selected : {{ selected }}</span>
</div>
</template>
<script>
var your_list = [
{ name: "one", id: 13 },
{ name: "two", id: 18 },
{ name: "three", id: 11 },
{ name: "four", id: 7 },
{ name: "five", id: 1 },
{ name: "six", id: 2 },
];
export default {
name: "App",
data() {
return {
objects_list: your_list,
selected: []
};
},
props:{
inputData: {
type: Object,
required: true
}
},
computed: {
selected() {
let selected = this.objects_list.filter(item => {
return this.inputData.find(i => i == item.id);
});
return selected;
}
}
};
</script>
new Vue({
el: '#application',
data: {
currencies: [
{
'name': 'Dollar',
'sign': '$'
}, {
'name': 'Euro',
'sign': '€'
}, {
'name': 'Pound',
'sign': '£'
}, {
'name': 'Cent',
'sign': '¢'
}
]
}
});
<select class="custom-select" v-model="quotationForm.currency">
<option v-for="currency in currencies" v-bind:value="currency.sign">
<span v-html="currency.sign"></span>
{{ currency.name }}
</option>
</select>
Currency sign can not been rendered on the select box.
But when i try to make statis it's works fine as per given below...
<select class="custom-select" v-model="quotationForm.currency">
<option v-for="currency in currencies" v-bind:value="currency.sign">
€
{{ currency.name }}
</option>
</select>
Whyv-html is not works in the select box? have any suggestion
Thank You.
I tested it on my own and it's working: Link
<template>
<select class="custom-select" v-model="quotationForm.currency">
<option :key="index" v-for="(currency, index) in currencies" v-bind:value="currency.sign">
<span v-html="currency.sign"></span>
{{ currency.name }}
</option>
</select>
</template>
<script>
export default {
data() {
return {
quotationForm: {
currency: null
},
currencies: [
{
'name': 'Dollar',
'sign': '$'
}, {
'name': 'Euro',
'sign': '€'
}, {
'name': 'Pound',
'sign': '£'
}, {
'name': 'Cent',
'sign': '¢'
}
]
}
}
}
</script>