skip to Main Content

I´m trying to call anonymous function defined in constant variable in my composable, and i need to call it in my component parent, that this anonimous function will fill my table with any data. I´m trying this:

my composable:

export default function useNcalls(){
    let calls = ref([])
    let param_search = ref([])
    let pagination = ref([])

    const getCall = async (param_search) => {
        let response = await axios.get('/api/callApi', {param_search: {'param_search': param_search} }) 
        console.log("llego")
        calls.value = response.data.data
    } 
    const deleteCall = (id) => axios.post(`/api/callApi/${id}`, {_method: 'delete'}).then(res => {
        confirm("¿Está seguro de que desea eliminar el registro?") 
        location.reload();
    }).catch(err => {
        console.log(err);
    });  
    
    const queryForKeywords = async (event) => {
        const response = await axios.get('/api/callApi/show', { params: { 'searchParams': event } }) 
        calls.value = response.data.data
    };

    const getResults = async (page) => {
        const response = axios.get('api/callApi?page=' + page)
        calls.value = response.data
    };

    const getItems = async (page) => {
        axios.get('/api/callApi?page='+page)
            .then(response => {
                calls.value = response.data.data;
                pagination.value = response.data.meta;
            });
    };

    return{
        calls,
        getCall,
        deleteCall,
        queryForKeywords,
        getResults,
        getItems
    } 
}

i have one component that create table and any methods that use this composable:

<script>
    import nUseCalls from "../../composables/ncalls"
    import { onMounted, defineComponent } from 'vue'
    
    export default defineComponent({
        name: 'nAsignedCalls',
        data(){
            return{
                items: [],
                    pagination: {
                        current_page: 1,
                    },
            }
        },
        
        setup(props, context) {
            const { calls, getCall, deleteCalls, queryForKeywords, getResults, getItems } = nUseCalls()
            

            function remove(id) {
                deleteDates(id)
            }
            
            function searchId(action) {
                let id = document.getElementsByClassName('id_search')[0].value
                const params = [action, id];
                
                queryForKeywords(params)
            }

            function searchName(action) {
                let id = document.getElementsByClassName('name_search')[0].value
                const params = [action, id];
                
                queryForKeywords(params)
            }

            function searchPhone(action) {
                let id = document.getElementsByClassName('phone_search')[0].value
                const params = [action, id];
                
                queryForKeywords(params)
            }

            function edit(action) {
                window.location.href = '/roomboss/calls/'+action+"/edit";
            }


            function getPage(page){
                getItems(page);
            }

            context.expose({ getCall })

            return { 
                calls,
                remove,
                searchId,
                searchName,
                searchPhone,
                edit,
                getResults,
                getPage,
                getCall
            }
        }
    });
</script>

and i have my component parent, that include before component that i expose:

<script>

    import { onMounted, defineComponent } from 'vue';
    import useNassignedCall from "../composables/ncalls"
    import asignedCalls from './roomBooss/asignedCalls';
    import nAsignedCalls from './roomBooss/nasignedCalls';


    export default defineComponent({
        components: {asignedCalls, nAsignedCalls},
        data(){
            return{
                items: [],
                    pagination: {
                        current_page: 1,
                    },
            }
        },
        
        setup(props, context) {
            var param_search = "";
            const { calls, getCall, deleteCalls, queryForKeywords, getResults, getItems } = useNassignedCall()
            

            function remove(id) {
                deleteCalls(id)
            }
            
            function searchId(action) {
                let id = document.getElementsByClassName('id_search')[0].value
                const params = [action, id];
                
                queryForKeywords(params)
            }

            function searchName(action) {
                let id = document.getElementsByClassName('name_search')[0].value
                const params = [action, id];
                
                queryForKeywords(params)
            }

            function searchPhone(action) {
                let id = document.getElementsByClassName('phone_search')[0].value
                const params = [action, id];
                
                queryForKeywords(params)
            }

            function edit(action) {
                window.location.href = '/roomboss/telemarketing/call/'+action+"/edit";
            }

            function show(action) {
                window.location.href = '/roomboss/telemarketing/call/'+action;
            }

            function getPage(page){
                getItems(page);
            }

            function searchRegisters(){
                var address = "";
                var city = "";
                var cp = "";

                address = document.getElementById("address").value
                if( address != "" ) {
                    param_search = "address";
                }

                city = document.getElementById("city").value
                if( city != "" ) {
                    param_search = "city";
                }

                cp = document.getElementById("postal_code").value
                if( cp != "" ) {
                    param_search = "cp";
                }

                context.expose({ getCall })
            }

            return { 
                calls,
                remove,
                searchId,
                searchName,
                searchPhone,
                edit,
                show,
                getResults,
                getPage,
                getCall,
                searchRegisters
            }
        }
    })

</script>

In my function searchRegisters() i need call getCall sending param_search that this anonymous function call laravel API to get all my data.

always return en my console:

Uncaught TypeError: _roomBooss_nasignedCalls__WEBPACK_IMPORTED_MODULE_3__.default.getCall is not a function
    at Proxy.searchRegisters (app.js:20026:114)
    at onClick._cache.<computed>._cache.<computed> (app.js:21762:21)
    at callWithErrorHandling (app.js:7336:22)
    at callWithAsyncErrorHandling (app.js:7345:21)
    at HTMLInputElement.invoker (app.js:15616:86)

or app.js:7203 [Vue warn]: expose() should be called only once per setup().

thanks for readme and sorry for my bad english

2

Answers


  1. Chosen as BEST ANSWER

    i resolve my question with this code:

    first in my component:

    call to my function ref

    getCall(toRef(param_search,'param_search'))
    

    in my composable add onMounted and watch

    onMounted(() => {
            if (param_search) {
                getCall(param_search)
            }
        })
        watch(
            () => param_search,
                (val) => {
                    if (val) {
                    loading.value = true
                    getCall(val)
                }
            },
        )
    

    with this, i can access to my function


  2. I think what you are trying to do is to use the composable in your child component, and then use template refs to pass the result around. IMO it does not make sense to use a composable that way, and I would try to avoid using template refs in general.

    Looking at your code, the issue seems to be that the functions from the composable change the calls ref, and you have to make sure that both parent and child component use functions that alter the same calls ref. A way to do this is to use provide/inject inside the composable. Then you can setup the provide in the parent component, and inject the ref into any component that needs it.

    You code doesn’t even need to change much. This is what the composable could look like:

    import { provide, inject } from 'vue'
    
    const callsSymbol = Symbol.for('calls-api-variable') // <---- create a symbol for the injection
    
    export function createCallsApi(){
      const calls = ref([])
      const pagination = ref([])
    
      const getCall = async (param_search) => {...} 
      const deleteCall = (id) => ...
      const queryForKeywords = async (event) => {...};
      const getResults = async (page) => {...};
      const getItems = async (page) => {...};
    
      const callsApi = {
        calls,
        getCall,
        deleteCall,
        queryForKeywords,
        getResults,
        getItems
      } 
    
      provide(callsSymbol, callsApi) // <----- add a provide
      return callsApi
    }
    
    export function useCallsApi(){ // <---- composable to resolve the inject
      const callsApi = inject(callsSymbol)
      if (!callsApi) throw new Error('Failed to inject callsApi. Did you call createCallsApi() in a parent component?')
      return callsApi
    }
    

    With that, in your parent, you do

    const { calls, getCall,...} = createCallsApi()
    

    and in the child:

    const { calls, getCall,...} = useCallsApi()
    

    And that’s all, no fumbling around with template refs.

    Does that work for you, does it make sense?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search