0

I have a parent component, SearchComponent:

<template>
    
        <div>
            <div class="relative pl-8 pr-10 rounded bg-white border focus-within:bg-white focus-within:ring-1">
    
                <input v-focus @keyup.escape="clearSearch" @keyup="doSearch" v-model="searchTerm"
                       class="w-full ml-4 h-12 pl-1 text-gray-700 text-lg rounded-full border-0 bg-transparent focus:outline-none placeholder-gray-400"
                       placeholder="Search..." autocomplete="off">
    
    
            </div>
    
            <ul class="bg-white mt-4">
    
                <quick-search-item v-for="item in searchResults" :key="item.id" :item-data="item.itemData">
    
                </quick-search-item>
    
            </ul>
    
        </div>
    
    </template>

This is responsible for receiving user input and getting results from an ajax call, handling errors etc. and generating the result list.

What I'd like to do is to make this generic so that instead of having a quick-search-item child component I can pass in different types of child component (like car-search-item, person-search-item etc.) depending on the context of where the user is in the app and what they're searching for

I've read a number of tutorials and I couldn't find quite what I'm trying to do. This may mean I'm approaching this in the wrong way - but if anyone could point me in the right direction, or has a better approach, I'd be very grateful.

Thanks, Lenny.

2 Answers 2

1

I would try to make use of the <slot> element. Check out the documentation here

<parent-component>
  <slot></slot>
</parent-component>

Hope this can put you on the right path.

Sign up to request clarification or add additional context in comments.

Comments

0

Schalk Pretorius was quite right: slots are the answer to this, specifically scoped slots. I found the Vue docs a little confusing as it refers to getting data from the child component and I wanted to do it the other way around, so as an aide memoire for myself and to help anyone else here's what I did:

In my parent component I defined the slot like this:

<slot name="results" v-bind:items="searchResults">

</slot>

The v-bind binds searchResults (a data item in the parent component) to the value 'items'. 'items' then becomes available in the slot.

In my child component I have a simple property setup called items:

props: {
        items: {type: Array},
    }, 

Then to hook it all together in my Blade file I did this:

<search-component endpoint="{{ route('quick_search.index') }}">

        <template v-slot:results="props">
            <food-results :items="props.items">

            </food-results>
        </template>


 </search-component>

This creates the search-component. Inside that -as I'm using named slots - we need a template and use v-slot to tell it which slot to use (results), then the ="props" exposes all the properties we've defined on that slot (in this case just one, 'items').

Inside the template we put our child component and then we can bind items to props.items which will be the searchResults in our parent component.

I'm happy to have this working and I can now create lots of different results components while reusing the search component - and at least I learnt something today!

Cheers, Lenny.

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.