Search code examples
vue.jsvuejs3vue-component

shorter names for vue3 deep objects when accessing them in template and in code


How to get around long names of objects, for example, buttons.btnCancel.inactive? I've tried plain desctructuring using const {btnCancelInactive: inactive, btnCancelInactiveClass: inactiveClass, btnCancelActiveClass: activeClass} = buttons.btnCancel but I lose reactivity. I tried destructuring to toRefs but then even the value btnCancelInactive is empty.

Here is the complete code:

//vueAddItemPanel.js

const template = `
    <div class="input-group input-group-sm">
      <input 
       type="text"
       class="form-control" 
       placeholder="Select a role to add..."
       ref="searchInputRef"
       v-model="searchText"
       >
      <button 
       class="btn disabled text-muted" 
       type="button">
       <i class="fas fa-check"></i></button>
      <button 
       :class="[btnCancelInactive ? btnCancelInactiveClass : btnCancelActiveClass]"
       type="button"
       @click.stop="clearSearch">
       <i class="fas fa-x"></i></button>
    </div>
    sss {{btnCancelInactive}}
`

const {ref, reactive, watch, toRefs, } = Vue;

const vueAddItemPanel = {
    setup(props, ctx) {
        const searchText = ref('')
        const searchInputRef = ref(null)
        const buttons = reactive({
            btnCancel : {
                inactive : true,
                inactiveClass : "btn btn-outline-secondary disabled text-muted",
                activeClass : "btn btn-outline-secondary"
            }
        })

        const {btnCancelInactive, btnCancelInactiveClass, btnCancelActiveClass 
            } = toRefs( buttons.btnCancel )

        // note: debounce is from lodash
        const debouncedSearch = _.debounce(() => {
            ctx.emit('searchChanged', searchText.value)
        }, 500)
        
        watch( searchText, () => {
            buttons.btnCancel.inactive = searchText.value.trim() === ''
            debouncedSearch()        
        })

        const clearSearch = () => {
            searchText.value = ''
            searchInputRef.value.focus()
            buttons.btnCancel.inactive = true
        }

        return {
            searchText, clearSearch, debouncedSearch, searchInputRef,
            btnCancelInactive, btnCancelInactiveClass, btnCancelActiveClass,
        }
    },
    template: template,
}

export default vueAddItemPanel

Solution

  • To avoid losing reactivity and to make access easier in the template, use computed properties

        // Computed properties for easier access in templates
        const isBtnCancelInactive = computed(() => buttons.btnCancel.inactive);
        const inactiveClass = computed(() => buttons.btnCancel.inactiveClass);
        const activeClass = computed(() => buttons.btnCancel.activeClass);