naive-ui icon indicating copy to clipboard operation
naive-ui copied to clipboard

Can TreeOption.label accept "string | (() => VNodeChild)" instead of just "string"?

Open ilgiznurgaliev opened this issue 2 years ago • 3 comments

This function solves the problem (这个功能解决的问题)

Hello.

I need to render a Tree component but labels should support localization. I'm trying to use a translation function (t()) from Vue-i18n library like below:

export default defineComponent({
  components: { NLayoutSider, NTree },

  setup() {

    const { t } = useI18n<{}, string>({useScope: 'global'});

    const filters: TreeOption[] = [
      { key: '1', label: () => t('tickets.filter.responsibility.group'), children: [
        { key: '1-1', label: () => t('tickets.filter.responsibility.curated') },
        { key: '1-2', label: () => t('tickets.filter.responsibility.forObservation') }
      ]}
    ]
    return { filters }
  }
  
});

</script>

<template>
  <n-layout-sider content-style="padding: 24px" width="300px" show-trigger bordered :native-scrollbar="false">
    <n-tree :data="filters" cascade checkable check-on-click default-expand-all :selectable="false" :default-checked-keys="['1']"></n-tree>
  </n-layout-sider>
</template>

The above throws type error because label accepts only string. The only way I found at the moment is to use suffix or preffix instead of label:

const filters: TreeOption[] = [
      { key: '1', suffix: () => t('tickets.filter.responsibility.group'), children: [
        { key: '1-1', suffix: () => t('tickets.filter.responsibility.curated') },
        { key: '1-2', suffix: () => t('tickets.filter.responsibility.forObservation') }
      ]}
    ]

The above works fine but looks not really correct. Similar data format has Menu component but label there accepts string | (() => VNodeChild) instead of just string, so no any issues there with translation. Can TreeOption.label be updated so that it will accept string | (() => VNodeChild) ? Probably there is another (better) way to implement localization in such cases?

Any way thank yo very mush for so good library, it's awesome.

Expected API (期望的 API)

No any changes in API, particular intefrace only.

ilgiznurgaliev avatar Aug 30 '22 19:08 ilgiznurgaliev

Why not make filters a computed:

export default defineComponent({
  components: { NLayoutSider, NTree },

  setup() {

    const { t } = useI18n<{}, string>({useScope: 'global'});

    const filters: TreeOption[] = computed(() => [
      { key: '1', label: t('tickets.filter.responsibility.group'), children: [
        { key: '1-1', label: t('tickets.filter.responsibility.curated') },
        { key: '1-2', label: t('tickets.filter.responsibility.forObservation') }
      ]}
    ])
    return { filters }
  }
});

07akioni avatar Aug 31 '22 14:08 07akioni

However I think we can add the API. For your case I think a computed is better.

07akioni avatar Aug 31 '22 14:08 07akioni

Thanks @07akioni for your response. With computed it works perfectly. But type have to be wrapped with ComputedRef, otherwise getting the following error:

Type 'ComputedRef<{ key: string; suffix: () => string; children: { key: string; suffix: () => string; }[]; }[]>' is missing the following properties from type 'TreeOption[]': length, pop, push, concat, and 26 more.

So finally it looks like below:

import type { ComputedRef } from 'vue';

export default defineComponent({
  components: { NLayoutSider, NTree },

  setup() {

    const { t } = useI18n<{}, string>({useScope: 'global'});

    const filters: ComputedRef<TreeOption[]> = computed(() => [
      { key: '1', label: t('tickets.filter.responsibility.group'), children: [
        { key: '1-1', label: t('tickets.filter.responsibility.curated') },
        { key: '1-2', label: t('tickets.filter.responsibility.forObservation') }
      ]}
    ])
    return { filters }
  }
});

ilgiznurgaliev avatar Aug 31 '22 19:08 ilgiznurgaliev

This issue does not have any recent activity. If you are still experiencing similar problems, open a new error, including a minimal copy of the problem

jahnli avatar Mar 12 '24 13:03 jahnli