0

I have got my root component, within this component I have got a middleman which basically loads another component (search) depending on the style selected. I want to bind values to this search and then have the any updates simply change the values within the root component.

I have shown the component's below which should help make more sense of what I want. What is the best way to do this, so basically I want to update the values in the root without needing to handle multiple emit events.

// Root.vue
<template>
    <div class="app-search">
        <search class="app-search__header"
                :settings="settings"
                :search="search"
                :sort="sortResults"
                :filters-toggle="filtersToggle" />
    </div>
</template>
<script>
import search from '../Search/Search';
export default {
    components: {
        search
    },
    props: {
        settings: {
            type: Object,
            required: true
        }
    },
    data: function() {
        return {
            sortResults: {
                field: 'price',
                direction: 'asc'
            },
            filtersToggle: true,
            search: ''
        }
    }
}
</script>
// Search/Search.vue

<template>
    <component :is="component"
               :settings="settings"
               :search="search"
               :sort="sort"
               :filters-toggle="filtersToggle"/>
</template>
<script>
export default {
    props: {
        settings: {
            required: true,
            type: Object
        },
        search: {
            required: false,
            type: String
        },
        sort: {
            required: false,
            type: Object
        },
        filtersToggle: {
            required: false,
            type: Boolean
        }
    },
    computed: {
        component() {
            return () => import(`./Layouts/${this.settings.layouts.search}`)
        }
    }
}
</script>
// Selected Theme

<template>
    <div>
        <input placeholder="Search"
               class="search"
               type="text"
               :value="search"
               @input="$emit('search', $event.target.value)"
               @keyup="$emit('search', $event.target.value)">

        <select name="" id="" class="sort" @change="handleSortChange">
            <option value="">Any</option>
            <option value="created_at|desc">Recently Added</option>
            <option value="price|desc">Highest Price</option>
            <option value="price|asc">Lowest Price</option>
            <option value="year|desc">Newest Age</option>
            <option value="year|asc">Oldest Age</option>
            <option value="mileage|desc">Highest Mileage</option>
            <option value="mileage|asc">Lowest Mileage</option>
        </select>

        <button value="true" class="filters">Show Filters</button>

    </div>
</template>
<script>
export default {
    props: {
        settings: {
            required: true,
            type: Object
        },
        search: {
            required: false,
            type: String
        },
        sort: {
            required: false,
            type: Object
        },
        filtersToggle: {
            required: false,
            type: Boolean
        }
    },
    methods: {
        handleSortChange(event) {
            const value = event.target.value;
            const [ filter, direction ] = value.split('|');
            // this.$emit('sort', )
        }
    }
}
</script>
<style lang="less">
.app-search__header {
    display: flex;
    .search {
        width: auto;
        flex-grow: 2;
    }
    .sort {
        width: auto;
        flex-grow: 1;
    }
    .filters {
        width: auto;
        flex-grow: 1;
    }
}
</style>
Martyn Ball
  • 4,679
  • 8
  • 56
  • 126

1 Answers1

0

You should look into using state managers, however it is possible to only emit once to the 'grandfather' of your deepest child component.

vueJS 2 components have a $parent property that contains their parent component.

That parent component also includes its own $parent property.

Then, accessing the "grandparent" component it's a matter of accessing the "parent's parent" component:

this.$parent["$parent"].$emit("myevent", { data: 123 });

https://stackoverflow.com/a/60059853/6803592

Olaf
  • 1,038
  • 8
  • 20
  • I guess I will have to catch this emit still, I can't simply have it update the value without additional methods? I'd want it function like `v-model` – Martyn Ball Aug 03 '21 at 10:21