I got 60k items in my autocomplete form, so I wanted to load it after user types 3 characters with only items that contains the given characters. Is there an option in autocomplete to implement this?
You should rather filter this amount of data on server side.
But it is doable in Vuetify. You can use search-input.sync and computed property for filtering items. Then you should clear your search value by input method
<v-autocomplete
:value="value"
:items="filterdItems"
#input="clearSearch"
:search-input.sync="search"
/>
export default {
data() {
return {
value: null,
search: "",
items: [], // Your items
};
},
computed: {
filterdItems() {
if (this.search.length < 2) return;
return this.items.filter(item => item.startsWith(this.search))
}
}
methods: {
clearSearch() {
this.search = '';
},
},
};
Related
I have combobox in Vue JS to select multiple items, I want to validate if user select any items or keep it empty, but the problem when I print the length and value of combox in console always gives length == 2 and values gives undefined in both cases if user select items or not
HTML
<v-col cols="6">
<v-combobox class="xrfelements" :items="xrfElementsRatios" v-model="mainElementsRatios" :rules="notEmptyRule" label="Main Elements and Ratios" multiple required small-chips outlined dense></v-combobox>
</v-col>
java script
validateForm: function (e) {
if (document.getElementsByClassName("xrfelements").length) {
console.log(document.getElementsByClassName("xrfelements".values
return true;}
this.errors = [];
if (!document.getElementsByClassName("xrfelements").length){
console.log(document.getElementsByClassName("xrfelements").index)
console.log(document.getElementsByClassName("xrfelements".values)
this.errors.push('there is no element selected.')
}
if (this.errors.length)
{
this.$alert ("The following items should not be empty: " +this.errors.join(", "))
}
e.preventDefault(e);
},
That's not how frameworks like vue work: You often times don't interact with the DOM directly. Instead, you use Vue intermediary. Please learn the basics of Vue.
new Vue({
el: '#app',
template: ` <v-col cols="6">
<v-combobox class="xrfelements" :items="xrfElementsRatios" v-model="mainElementsRatios" :rules="notEmptyRule" label="Main Elements and Ratios" multiple required small-chips outlined dense></v-combobox>
</v-col>`,
data() {
return {
notEmptyRule: [],
mainElementsRatios: [],
xrfElementsRatios: [],
}
},
methods: {
validateForm: function (e) {
if (mainElementsRatios.length) {
console.log(mainElementsRatios);
return true;
}
this.errors = [];
if (!mainElementsRatios.length) {
console.log(document.getElementsByClassName("xrfelements").index)
console.log(mainElementsRatios)
this.errors.push('there is no element selected.')
}
if (this.errors.length) {
this.$alert("The following items should not be empty: " + this.errors.join(", "))
}
e.preventDefault(e);
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
i have code below in Vue js that shows Categories from API and whenever i click on any of them it add it to the array AddCategory and post it to API, also i've implemented button Removeall that whenever i click on it, it remove all the selected categories in array (it will empty the array) and it works fine. my problem is when i want to click again on the selected single category (in function remove below) it's not poping it up from array however it pushed it twice, any help?
<template>
<b-row class="categories-row">
<div
class="categories"
v-for="(category, index) in categories"
:key="index"
#click="Add(category._id, index)"
:class="[selectedIndex.includes(index) ? 'green' : 'gray']"
required
>
{{ category.category_name }}
</div>
</b-row>
</template>
export default {
data() {
return {
categories: [],
selectedIndex: [],
AddCategory: [],
posts: {
description: null,
questionTitle: null,
categories: null,
},
};
},
methods: {
Add(AddCategory, index) {
if (this.selectedIndex.includes(index))
this.Remove(index);
else
this.selectedIndex.push(index);
this.AddCategory.push(AddCategory);
},
Remove(index) { //not working
this.selectedIndex.splice(this.selectedIndex.indexOf(index),1);
},
RemoveAll() {
this.AddCategory = [];
this.selectedIndex.splice(this.AddCategory);
},}}
try this:
Remove(index) {
this.selectedIndex = this.selectedIndex.filter((item)=> item !== index) ;
}
Edited:
#sara97 maybe you need remove it from this.AddCategory too.
Edited:
#sara97 and because it runs "this.AddCategory.push(AddCategory);" everytime. use {} in if and else.
Add(AddCategory, index) {
if (this.selectedIndex.includes(index)) {
this.Remove(AddCategory,index);
}else{
this.selectedIndex.push(index);
this.AddCategory.push(AddCategory);}
},
Remove(AddCategory,index) {
this.selectedIndex = this.selectedIndex.filter((item)=> item !== index);
this.AddCategory = this.AddCategory.filter((item)=> item !== AddCategory)
},
I'm designing a form in React that has a main form builder (Create Job.js) and some form pages (AdditionalInfo.js) and (Confirmation.js). this form had a tag input that allows you to choose tags from a drop-down list provided by an API. the selected items need to be shown later in the confirmation page.
This is my main form builder that has props and functions:(CreateJob.js)
state = {
step:1,
Title:'',
requirements:'',
Location:'',
Benefits:'',
Company:'',
InternalCode:'',
Details:'',
Tags:[],
Address:'',
Department:'',
Salary:''
}
handleDropDown = input => value => {
this.setState({ [input]: value });
}
render () {
const { step } = this.state
const {Title,Benefits,Company,InternalCode,Detailss,Tags,Address,Department,Salary,requirements,Location } = this.state;
const values ={Title,Benefits,Company,InternalCode,Detailss,Tags,Address,Department,Salary,requirements,Location}
return (
<div>
....
<AdditionalInfo
nextStep={this.nextStep}
prevStep={this.prevStep}
handleChange={this.handleChange}
handleChangeRaw={this.handleChangeRaw}
handleDropDown={this.handleDropDown}
values={values}
/>
<Confirmation
nextStep={this.nextStep}
prevStep={this.prevStep}
values={values}
/>
....
and this is my form page which includes the list from API and the drop down using react-select(AdditionalInfo.js):
export class AdditionalInfo extends Component {
state = {
locations:[],
departments: [],
tagsList:[],
}
componentDidMount() {
axios.get('/api/jobs/list-tags',{headers:headers}).then(respo =>{
console.log(respo.data)
this.setState({
tagsList:respo.data.map(Tags=>({label: Tags.name, value: Tags.id}))
})
console.log(this.state.tagsList)
})
}
render() {
const {values, handleDropDown} = this.props
<Select placeholder='Select from pre-created Tags 'onChange={handleDropDown('Tags')} defaultValue={values.Tags} required isMulti options={this.state.tagsList}/>
...
this is the list of tags received from the API:
Object { label: "MongoDB", value: 1 }
Object { label: "JavaScript", value: 2 }
Object { label: "HTML", value: 3 }
Object { label: "CSS", value: 4 }
...
And this is my Confirmation page which needs to show the info received from previous pages (Confirmation.js)
.....
render () {
const {
values: {
Title, Benefits,
Company, InternalCode, Detailss, Department,Tags, Salary,requirements,Location
}} = this.props
<Row> Tags: {Tags.join(", ")}</Row>
....
the problem is that, instead of showing tags on the page like putting the labels next to each other
:JavaScript,
MongoDB,
... it shows this
: [object Object], [object Object], [object Object], [object Object]. sorry for the long code but Im a beginner in JavaScript and I dont know how to handle it so it shows the labels. How can I achieve this?
You are doing great, and you have done right, just simple tweak you need.
If React show anything like [Object Object] it means you are trying to render Javascript Object not a single value because you have got Tags from props which is an Array of objects.
Use it like this, it will work like butter -
import React from 'react';
const Confirmation = () => {
const tags = [ // which you got from props
{ label: "MongoDB", value: 1 },
{ label: "JavaScript", value: 2 },
{ label: "HTML", value: 3 },
{ label: "CSS", value: 4 }
];
return (
<div>
{tags.map(tag => tag.label).join(', ')} {/* map over tags to get the array of tag labels */}
</div>
);
}
export default Confirmation;
When you click on the "add" button, you should check whether some text is entered into the input and, if so, then some object should be added with the text entered into the input and then save in the localstorage. When you restart the program, this object should return to the page. It is also possible to delete an object by clicking on the delete button For the component, this code is working.
Here is how it works.
Now I need to transfer everything to vuex. But I can't do this right. When I enter the text in the input in the console, I get the error "Error in v-on handler:" TypeError: e.target is undefined ". And as soon as I remove the focus from the input, the text entered there will disappear. Also, I cannot use v-model as it is not supported by framework 7
How it works now
My code in component
<f7-block strong>
<f7-block-title>Some items</f7-block-title>
<f7-block v-for="(cat, n) in compCats">
<span>{{ cat }}</span>
<f7-button fill color="red" #click="removeCat(n)">Delete Cat</f7-button>
</f7-block>
<f7-list form>
<f7-list-input
:value="compNewCats"
#input="newCatOnInput"
type="text"
placeholder="Заметка"
></f7-list-input>
<f7-button fill color="blue" #click="addCat">Add some item</f7-button>
</f7-list>
</f7-block>
<script>
export default {
computed:{
compCats(){
return this.$store.state.cats;
},
compNewCats(){
return this.$store.state.newCat;
}
},
mounted() {
if (localStorage.getItem('cats')) {
try {
this.cats = JSON.parse(localStorage.getItem('cats'));
} catch(e) {
localStorage.removeItem('cats');
}
}
},
methods: {
addCat(e) {
this.$store.commit('addNewCat');
},
newCatOnInput(e){
this.$store.commit('newCatInput', e.target.value);
},
removeCat(n){
this.$store.comit('removeSomeCat');
}
}
}
</script>
My code in VUEX
export default new Vuex.Store({
state: {
cats:[],
newCat: null
},
mutations: {
addNewCat(state) {
if (!this.newCat) {
return;
}
this.state.cats.push(this.state.newCat);
this.state.newCat = '';
this.saveCats();
},
removeSomeCat(x) {
this.state.cats.splice(x, 1);
this.saveCats();
},
saveCats(state) {
const parsed = JSON.stringify(this.state.cats);
localStorage.setItem('cats', parsed);
},
newCatInput(payload) {
this.newCat = payload;
},
}
}
});
I am using Vue-multiselect with Laravel.
I am using the multiselect component in my form to let the user select multiple countries. The component works fine but when I submit the form and I dd() it, it shows [object Object].
I can't get the value of the multiselect component. I have found similar questions but none of them worked for me.
Here is my code:
The ExampleComponent.vue file:
<template slot-scope="{ option }">
<div>
<label class="typo__label">Restricted country</label>
<multiselect
v-model="internalValue"
tag-placeholder="Add restricted country"
placeholder="Search or add a country"
label="name"
name="selectedcountries[]"
:options="options"
:multiple="true"
track-by="name"
:taggable="true"
#tag="addTag"
>
</multiselect>
<pre class="language-json"><code>{{ internalValue }}</code></pre>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
// register globally
Vue.component('multiselect', Multiselect)
export default {
components: {
Multiselect
},
props: ['value'],
data () {
return {
internalValue: this.value,
options: [
{ name: 'Hungary' },
{ name: 'USA' },
{ name: 'China' }
]
}
},
watch: {
internalValue(v){
this.$emit('input', v);
}
},
methods: {
addTag (newTag) {
const tag = {
name: newTag,
code: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.options.push(tag)
this.value.push(tag)
}
},
}
</script>
Here is my register form:
<div id="select">
<example-component v-model="selectedValue"></example-component>
<input type="hidden" name="countriespost" :value="selectedValue">
</div>
<script>
const select = new Vue({
el: '#select',
data: {
selectedValue: null
},
});
</script>
When I submit the form, the countriespost shows me me this: [object Object] instead of the actual value.
It's because you are providing an array of objects as options property:
options: [
{ name: 'Hungary' },
{ name: 'USA' },
{ name: 'China' }
]
so the value emited on input is an object.
Try to change the options to following:
options: [ 'Hungary', 'USA', 'China' ]
If you pass an array of objects to the :options prop of the multiselect component, you should submit the form with javascript so you can extract the object ids or whatever you need on the backend and then send them through.
Add a method like this:
submit: function() {
let data = {
objectIds: _.map(this.selectedOptions, option => option.id), //lodash library used here
// whatever other data you need
}
axios.post('/form-submit-url', data).then(r => {
console.log(r);
});
}
Then trigger it with a #click.stop event on your submit button.