Vue components called through column render don't have a current instance

Vue components called through column render don't have a current instance

Paulie1Paulie1 Posts: 2Questions: 1Answers: 0

I have a table that looks like this:

<DataTable :columns="columnOptions" :data="rows" :options="options">
  <thead>
    <tr>
      <th>One</th>
    </tr>
  </thead>
  <template #custom="props">
    <MyComponent :label="props.cellData" />
  </template>
</DataTable>

const columnOptions = [{
  render: '#custom',
  data: 'one',
  defaultContent: ''
}]

If MyComponent is pretty simple that works. But if it has any call that requires getCurrentInstance it fails. I looked at the value of that when I call MyComponent normally and when I call it from inside the DataTable and I see that the app is set to null and that throws an error. (An easy way to get this error is by including the i18n object)

Here is MyComponent.vue:

<template>
  <span>
    {{label}}
  </span>
</template>

<script setup lang="ts">
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { getCurrentInstance } from 'vue'
import { useI18n } from 'vue-i18n'

const instance = getCurrentInstance()
console.log("instance:", instance.appContext.app)

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { t } = useI18n({ useScope: 'global' })

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const props = defineProps<{
    label: string;
}>()
</script>

That is, when I run this I get null in the console.

Is there some context I'm supposed to pass in?

Answers

  • Paulie1Paulie1 Posts: 2Questions: 1Answers: 0

    I created a simple project that demonstrates the error.

    Do the following:

    git clone git@github.com:paulrosen/datatable-vue-crash.git
    cd datatable-vue-crash
    npm install
    npm run dev
    

    You will see error messages in the console.

  • cauesantosre4cauesantosre4 Posts: 3Questions: 0Answers: 0

    I had the same problem.

    I could fix it modifying node_modules/datatables.net-vue3/src/DataTable.vue -> createRenderer function to:

    /**
     * Create a DataTables rendering function for a slot
     *
     * @param slot Slot to render
     * @param {ComponentPublicInstance|ComponentInternalInstance} instance Vue Instance
     */
    function createRenderer(slot: any, instance: any) {
        return function (
            data: any,
            type: string,
            row: any,
            meta: any
        ) {
            let key = meta.row + ',' + meta.col;
    
            if (!elements[key]) {
    
                const slotRender = slot({
                    cellData: data,
                    colIndex: meta.col,
                    rowData: row,
                    rowIndex: meta.row,
                    type
                });
    
                slotRender[0].appContext = instance.appContext;
    
                let content = h('div', slotRender);
    
                elements[key] = document.createElement('div');
                render(content, elements[key]);
            }
    
            return elements[key];
        }
    }
    

    You'll have to copy DataTable.vue into your project and use it in place default one.

  • cauesantosre4cauesantosre4 Posts: 3Questions: 0Answers: 0

    Vue instance is available into applyRenderers function

Sign In or Register to comment.