Search code examples
javascriptlaravelvue.jsvuetify.jsv-select

VueJs v-select edit selected via methods


What im trying to achieve is:

when i select the option "Alle openstaande" (result_id = 0), i want to select all these result_ids: [-1,-2,-3,-5,-7,-8,-11,-12] and deselect result_id 0.

var mergedResults returns a array of the result_ids that need to be selected

i cant figure out how i can add to the currently selected options via the methods

my blade file contains:

              <dd-results
                        naam="resultcodes-select"
                        v-model="selected.resultcodes"
                        :select-all="true"
                        :multiple="true"
                        :openstaande="true"
                        :include-ids="true"
                        :project-id="selected.project"
                        title="@lang('rapportage.resultcode')"
                        :include-negative="true"
                        return-key="result_id"
                        >
                    </dd-results>

my vue file:

<template>
    <span>
        <label v-if="title">{{title}}</label>
        <v-select
            :options="results"
            label="naam"
            :placeholder="placeholderText"
            :close-on-select="closeOnSelectValue"
            :disabled="isDisabled"
            :multiple="multiple"
            :value="value"
            @input="handleInput($event)"
            :loading="isLoading"
            :reduce="reduceKey"
        >
        <div slot="no-options">{{geenOptiesTekst}}</div>
        </v-select>
    </span>

</template>

<script>
import vSelect from "vue-select";
import Language from "../../classes/Language";

export default {
    name: 'dd-results',
    components: {
        'v-select': vSelect
    },
    props: {
        placeholder: {
            type: String,
            default: null
        },
        closeOnSelect: {
            type: Boolean,
            default: true
        },
        isDisabled: {
            type: Boolean,
            default: false,
        },
        // Meerdere waarden selecteren
        multiple: {
            type: Boolean,
            default: false
        },
        openstaande: {
            type: Boolean,
            default: false
        },
        value: {
            default: null
        },
        // Wel/geen 'Alle projecten' placeholder
        selectAll: {
            type: Boolean,
            default: false
        },
        projectId: {
            default: null,
            required: true
        },
        title: {
            type: String,
            default: null
        },
        includeIds: {
            type: Boolean,
            default: false
        },
        // Wel / niet negatieve resultcodes tonen
        includeNegative: {
            type: Boolean,
            default: false
        },
        // Als gevuld: alleen deze waarde teruggeven, anders volledig object
        returnKey: {
            type: String,
            default: null,
        },
        excludeTypes: {
            type: Array,
        }
    },
    data() {
        return {
            language: new Language,
            results: [],
            isLoading: false,
        }
    },
    created() {
        var self = this;
        this.language.set(lan);
    },
    methods: {
        reduceKey(option) {
            return this.returnKey != null ? option[this.returnKey] : option;
        },

        handleInput($event) {
            this.$emit('input', $event);
       
            if($event.includes(0)) {
                this.addOpenstaande($event);
            }
        },

        addOpenstaande(value) {
            var openstaandeResult = [-1,-2,-3,-5,-7,-8,-11,-12];

            var mergedResults = [... new Set (value.concat(openstaandeResult))];

            const removeIndex = mergedResults.indexOf(0);
            if (removeIndex > -1) {
                mergedResults.splice(removeIndex, 1); 
             }

             this.reset(mergedResults);

            console.log(mergedResults);

        },

        reset(selected=false) {
            // 1. verwijder de geselecteerde itemboxes
            console.log(this.$el,$(this.$el).find('.vs__selected'));
            $(this.$el).find('.vs__selected').remove();
            setTimeout(() => {
                // 2. herstel de placeholder
                $(this.$el).find('.vs__selected-options input').attr('placeholder', this.placeholderText);
            }, 100);

            if(selected !== false) {

            }

        }
    },
    computed: {
        // Tekst in dropdown bij geen opties
        geenOptiesTekst() {
            return this.language.trans('app', 'no_results');
        },
        // Bepaal placeholder tekst. Is afhankelijk van selectAll optie. Eigen placeholder overruled altijd.
        placeholderText() {
            if(this.placeholder != null) {
                return this.placeholder;
            }
            else if(this.selectAll) {
                return this.language.trans('rapportage', 'resultcode_alle');
            } else {
                return this.language.trans('rapportage', 'resultcode_selecteren');
            }
        },
        // Bij mogelijkheid tot selecteren van meerdere projecten, standaard niet sluiten na selectie
        closeOnSelectValue() {
            if(this.multiple) {
                return false;
            } else {
                return this.closeOnSelect;
            }
        }
    },
    watch: {
        'projectId'(newVal) {

            if(this.value != null) {
              if(this.value.length != null) {
                this.value.length = 0;
              }
            }
            
            var self = this;
            if(newVal != null) {
                self.isLoading = true;
                // Results opvragen en dropdown vullen
                axios.get('/projecten/'+newVal+'/results').then(result => {
                    self.results = Object.values(result.data);
                    console.log(self.results);

                    for (var i = 0; i < self.results.length; i++) {
                        // Als negatieven gefilterd moeten en index negatief is: verwijderen
                        if(self.results[i].result_id < 0 && !this.includeNegative) {
                            self.results.splice(i, 1);
                            i--; // Index terugzetten door verwijderen item
                            continue;
                        } 
                        // Als type in excludeTypes: verwijderen
                        if (this.excludeTypes) {
                            if (this.excludeTypes.indexOf(self.results[i].type) > -1) {
                                self.results.splice(i, 1);
                                i--;
                                continue;
                            }
                        }
                    }
                    for (var i = 0; i < self.results.length; i++) {
                        if (self.includeIds) {
                            // verander "naam" in "(result_id) naam"
                            self.results[i].naam = "(" + self.results[i].result_id + ") " + self.results[i].naam;
                        }
                    }

                    
                    if(this.multiple === true && this.openstaande) {
                        self.results.unshift({
                            result_id: 0,
                            naam: this.language.trans('app', 'alle_openstaande')
                        })
                    }
                }).catch(error => {
                    console.log(error);
                }).then(data => {
                    self.isLoading = false;
                })
            } else {
                this.results = [];
            }
        }
    }
}
</script>


<style>
    select:required:invalid {
        color: gray;
    }

    .vs--disabled .vs__dropdown-toggle, .vs--disabled .vs__clear, .vs--disabled .vs__search, .vs--disabled .vs__selected, .vs--disabled .vs__open-indicator {
        background-color: #D3D3D3;
        color: #808080;
    }
    
    option {
        color: black;
    }

    .vs__dropdown-toggle {
        background: #fff;
    }

</style>

Solution

  • i was able to make this work via the $emit in handleInput($event). (it seems so obvious now but i had no idea what this.$emit('input', $event); did at the time)

    i changed these three methods:

    handleInput($event) {
        this.$emit('input', $event);
    
        if($event.includes(0)) {
            this.addOpenstaande($event);
        }
    },
    
    addOpenstaande(value) {
        var openstaandeResult = [-1,-2,-3,-5,-7,-8,-11,-12];
    
        var mergedResults = [... new Set (value.concat(openstaandeResult))];
    
        const removeIndex = mergedResults.indexOf(0);
        if (removeIndex > -1) {
            mergedResults.splice(removeIndex, 1); 
         }
    
         this.$emit('input', mergedResults);
    },
    
    reset(selected=false) {
        // 1. verwijder de geselecteerde itemboxes
        $(this.$el).find('.vs__selected').remove();
        setTimeout(() => {
            // 2. herstel de placeholder
            $(this.$el).find('.vs__selected-options input').attr('placeholder', this.placeholderText);
        }, 100);
    }