3

I have a vue component which should dispaly and handle filter-options for the results shown on the site.

The code below shows a part of my component. In this example a min and a max price can be set by the user. Because my filter is handled by the backend, I want to get all available filter-option (or the default-filters) before the component is rendered.

Unfortunatelly I get the following error-message: TypeError: Cannot read property 'min' of undefined.

COMPONENT

<template>
    <div id="filter">
        <fieldset>
            <div class="input-group">
                <div class="input-group-prepend">
                    <span class="input-group-text">Preis von - bis</span>
                </div>

                <select class="form-control" id="min_price" v-model="filter.price.min"
                        v-on:change="countResults">
                    <option value="0" selected="selected">beliebig</option>
                    <option value="250">250 €</option>
                    <option value="500">500 €</option>
                    <option value="750">750 €</option>
                    <option value="1000">1000 €</option>
                    <option value="1500">1500 €</option>
                </select>
                <select class="form-control" id="max_price" v-model="filter.price.max"
                        v-on:change="countResults">
                    <option value="250">250 €</option>
                    <option value="500">500 €</option>
                    <option value="750">750 €</option>
                    <option value="1000">1000 €</option>
                    <option value="1500">1500 €</option>
                    <option value="0" selected="selected">beliebig</option>
                </select>

            </div>
        </fieldset>
    </div>
</template>

JS

<script>
    export default {
        name: "VehicleFilterComponent",
        data: function () {
            return {
                categories: [],
                filter: {}
            }
        },
        methods: {
            getDefaultFilter() {
                axios.get(this.$apiUrl + '/vehicles/default-filters')
                    .then(result => {
                        this.filter = result.data.filter;
                    }).catch(function (error) {
                    console.warn(error)
                });
            }
        },
        beforeMount() {
            this.getDefaultFilter();
        }
    }
</script>

Is there a way to wait until all filters are loaded?

Right now I make use of v-if and set the filter-data per default to false. So the template is only rendered when all filters where loaded. Is there a better way, maybe via Promises?

5
  • 1
    The solution you propose in your question (setting filter to false) should work, why didn't you try it? Commented Aug 3, 2018 at 11:54
  • Just edited the question^^ but thanks for your reply! Commented Aug 3, 2018 at 11:55
  • 1
    The way you have implemented it is fairly okay but you might run into a few situations, one is, handling when the result from the API is empty. I'll suggest, begin with using a different value to monitor the fetching. Eg: data.fetched = false. From there you can render a message telling the user the data has not been fetched and another telling them it has been fetched but had no entries, etc. Commented Aug 3, 2018 at 12:05
  • Checkout this example on jsFiddle, it is a similar implementation to my comment: jsfiddle.net/adamwathan/xov6ksvd Commented Aug 3, 2018 at 12:06
  • Try to use beforeRouteEnter: function(to, from, next) for this. Commented Aug 3, 2018 at 12:48

1 Answer 1

3

Your existing solution is not bad. In general, your template rendering should not be linked to data retrieval – consider the case when the server is taking a long time to respond or worse, is completely unavailable for some reason. You should show at least a spinner in this case.

So this means that whatever display logic there is, it should be done "manually" and should not be linked with the Vue lifecycle, i.e. with v-if and such.

As for the code itself, you can perhaps make it more clear with async / await syntax:

export default {
    name: "VehicleFilterComponent",
    data: function () {
        return {
            categories: [],
            filter: {}
        }
    },
    methods: {
        async getDefaultFilter() {
            this.filter = (await axios.get(this.$apiUrl + '/vehicles/default-filters')).data.filter;
        }
    },
    beforeMount() {
        this.getDefaultFilter();
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.