typesense / typesense-instantsearch-adapter

A JS adapter library to build rich search interfaces with Typesense and InstantSearch.js
MIT License
402 stars 63 forks source link

Can't update component value in the adapater #166

Open guillaumetch opened 1 year ago

guillaumetch commented 1 year ago

Description

Hi, I currently facing an issue using the adapter with VueJs. I have a vue slider component (https://www.npmjs.com/package/vue-slider-component) and others in my Vue. I need to update to value of vue slider component after mounted to trigger a search but I can't the component in the mounted() method

Steps to reproduce

Here is my code

export default {
    data() {
        return {
            searchClient: null,
            routing,
            filterIcon: '/sgdm-theme/images/filter.png',
            moneyFormatter: v => "${( v + '€')}",
            favorites: [],
            limit: 10,
            showMoreLimit: 1000,
            paddingPagination: this.isMobile ? 1 : 2,
            isMobile: isMobileOnly ? 1 : 0,
            isTablet: isTablet ? 1 : 0
        };
    },
    components: {
        VueSlider,
        Collapsible,
        MoneyFormat,
        isMobileOnly,
        isTablet
    },
    props: [
        'dataPath',
        'typesenseUrl',
        'typesenseKey',
        'typesenseVehicles',
        'urlAideEtConseils',
        'urlGaranties',
        'urlWishListAdd',
        'urlWishListRemove',
        'urlWishList',
        'dataUser',
        'urlLogin',
        'urlRegister',
        'infoPrice',
        'rangeMin',
        'rangeMax'
    ],
    methods: {
        pageChange() {
            document.body.scrollIntoView();
        },
        showAlert() {
            this.$swal('Vous devez être <a href="'+this.urlLogin+'">connecté</a> ou <a href="'+this.urlRegister+'">créer un compte</a> pour utiliser les favoris !');
        },

        generateThumbnail(item)
        {
            var path = item.image;
            if(this.isMobile)
            {
                var path = item.image_mobile;
            }

            return path;
        },

        generatePlacehold()
        {
            var path = 'https://via.placeholder.com/248x164/CCCCCC/CCCCCC';
            if(this.isMobile)
            {
                var path = 'https://via.placeholder.com/320x190/CCCCCC/CCCCCC';
            }

            return path;
        },

        toValue(value, range) {
            return [
                typeof value.min === "number" ? value.min : range.min,
                typeof value.max === "number" ? value.max : range.max,
            ];
        },

        removeEmpty(items) {
            return items.filter(item => item.label.length > 0)
        },

        isFavorit(itemId)
        {
            return this.favorites.includes(itemId);
        },

        getFavorites()
        {
            axios.get(Routing.generate('ajax_whishlist'))
                .then(response => {
                    this.favorites = JSON.parse(response.data);

                    return this.favorites;
                });
        },

        isLimitPrice(price)
        {
            return parseInt(price) >= limitPrice ? 1 : 0;
        }

    },
    mounted: function () {

        const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
            server: {
                apiKey: this.typesenseKey,
                nodes: [
                    {
                        url: this.typesenseUrl
                    },
                ],
            },
            cacheSearchResultsForSeconds: 0,

            additionalSearchParameters: {
                query_by: "label,brand,short_description,motor,version,category",
                sort_by: "random_sort_field:desc",
                filter_by: "monthly_rent:>0",
                use_cache: false
            },
        });

        this.$data.searchClient = typesenseInstantsearchAdapter.searchClient;

        this.getFavorites();

        new Tooltip(document.body, {
            selector: "[data-bs-toggle='tooltip']",
        })

        // Access the VueSlider component using the $refs object
        const slider = this.$refs.slider;
        console.log(this.$refs);

        // Set the value of the slider programmatically
        slider.setValue([this.rangeMin, this.rangeMax]);
    }
};

Expected Behavior

Update the vue slider component value to trigger the search

Actual Behavior

In the mounted() method, I try to access my component but I got 2023-05-03_10-25

My Vue slider component code

<h4>Prix</h4>
<h5>par mois TTC</h5>
<ais-range-input attribute="monthly_rent">
    <template v-slot="{ currentRefinement, range, refine }">
        <vue-slider
            :min="range.min"
            :max="range.max"
            :lazy="true"
            :value=[rangeMin,rangeMax]
            @change="refine({ min: $event[0], max: $event[1] })"
            :tooltip-formatter="moneyFormatter"
            ref="slider"
        />
    </template>
</ais-range-input>

Metadata

Typesense Version:

0.23.1

OS: Ubuntu 22.04.1 LTS 64 bit

ibasaw commented 1 year ago

hi, i need the same thing, i want to initialise on dom ready the slider with 2 variables come from a form homepage. so client use slider, click on submit form, i need to use min and max on the search page with these variables already set. how to do that with the adapter and vue-slider-component ?

ibasaw commented 1 year ago

@jasonbosco hello, can we have a hint for this issue please ?

jasonbosco commented 1 year ago

@guillaumetch Your question is technically unrelated to how typesense-instantsearch-adapter functions and more of a Vue question. While I'm familiar with Vue (definitely not an expert), I'm not sure why the standard Vue ref mechanism is not working to access that nested slider component... Could you try posting on Stackoverflow - there should be more Vue experts there.

jasonbosco commented 1 year ago

@ibasaw I just stumbled on this thread, may be this helps: https://github.com/algolia/vue-instantsearch/issues/717#issuecomment-530373088