Modify static component to dynamic

Viewed 81

I'm new in Vuejs and I'm currently working with composition API, I have a nav component where I have an Array called tabs as you can see that array is static.

So I want to do this dynamic and send that props from another component. I read about that but I do not understand at all.

Supossely I can change the array of my component with a model like:

const tabs<MyModel>

And then I can send it from the other component, but I'm lost

Nav component

<template>
  <div>
    <div class="sm:hidden">
      <label for="tabs" class="sr-only">Select a tab</label>
      <select
        id="tabs"
        name="tabs"
        class="block w-full focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md"
      >
        <option v-for="tab in tabs" :key="tab.name" :selected="tab.current">
          {{ tab.name }}
        </option>
      </select>
    </div>

    <div class="hidden sm:block">
      <nav class="flex items-center space-x-4">
        <a
          v-for="tab in tabs"
          :key="tab.name"
          :href="tab.href"
          :class="[
            tab.current
              ? 'bg-purple-70 q0 text-white'
              : 'text-purple-700 hover:text-gray-700',
            'px-12 py-2 rounded-full font-bold text-xl',
          ]"
          @click="changeTab(tab)"
        >
          {{ tab.name }}
        </a>
      </nav>
    </div>
    <div class="hidden sm:block">
      <div
        v-for="tab in tabs"
        :key="tab.name"
        :href="tab.href"
        class="px-12 flex justify-center"
        :class="[tab.current || 'hidden']"
        @click="changeTab(tab)"
      >
        {{ tab.id }} - {{ tab.name }} - {{ tab.href }} - {{ tab.title }}
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, computed } from '@vue/composition-api'
import i18n from '@/setup/i18n'

export default defineComponent({
  name: 'ProgramModal',

  setup() {
    const ariaLabel = computed(() => i18n.t('share') as string)

    const tabs = ref([
      {
        id: 1,
        title: 'test title one',
        imageSrc: '/programs/test1.png',
        content: '',
        name: 'LOREM',
        href: '#test1',
        current: true,
      },
      {
        id: 2,
        title: 'test title two',
        imageSrc: '/programs/test2.png',
        content: '',
        name: 'IPSUM',
        href: '#test2',
        current: false,
      },
      {
        id: 3,
        title: 'test title three',
        imageSrc: '/programs/test3.png',
        content: '',
        name: 'PDF',
        href: '#test3',
        current: false,
      },
    ])

    const changeTab = (selectedTab: { id: number }) => {
      tabs.value.map((t) => {
        t.id === selectedTab.id ? (t.current = true) : (t.current = false)
      })
    }

    return {
      tabs,
      changeTab,
      ariaLabel,
    }
  },
})
</script>

The component where I want to send parameters:

<template>
  <ProgramModal />
</template>


<script lang="ts">
import ProgramModal from '@/components/ProgramModal.vue'
import { defineComponent, ref } from '@vue/composition-api'

export default defineComponent({
  name: 'Home',

  components: {
    ProgramModal,
  },

  setup() {
    const isModalOpen = ref(true)

    const showModal = () => {
      isModalOpen.value = true
    }

    return {
      isModalOpen,
      showModal,
    }
  },
})
</script>

How can I change this logic to receive different values? Regards

1 Answers

Two schemes, props or composables:

1. Use props:

You can create tabs in Home component and pass to ProgramModel:

<template>
  <ProgramModal :tabs="tabs" />
</template>


<script lang="ts">
import ProgramModal from '@/components/ProgramModal.vue'
import { defineComponent, ref } from '@vue/composition-api'

export default defineComponent({
  name: 'Home',

  components: {
    ProgramModal,
  },

  setup() {
    // ...

    const tabs = ref([
      {
        id: 1,
        title: 'test title one',
        imageSrc: '/programs/test1.png',
        content: '',
        name: 'LOREM',
        href: '#test1',
        current: true,
      },
      {
        id: 2,
        title: 'test title two',
        imageSrc: '/programs/test2.png',
        content: '',
        name: 'IPSUM',
        href: '#test2',
        current: false,
      },
      {
        id: 3,
        title: 'test title three',
        imageSrc: '/programs/test3.png',
        content: '',
        name: 'PDF',
        href: '#test3',
        current: false,
      },
    ])

    return { tabs }
  },
})
</script>

Then, define a prop in ProgramModal component:

export default defineComponent({
  name: 'ProgramModal',

  props: {
    tabs: Array as PropType<Array<Tab>>
  },

  setup() {
    const ariaLabel = computed(() => i18n.t('share') as string)

    const changeTab = (selectedTab: { id: number }) => {
      tabs.value.map((t) => {
        t.id === selectedTab.id ? (t.current = true) : (t.current = false)
      })
    }

    return {
      tabs,
      changeTab,
      ariaLabel,
    }
  },
})

2. Use composables (Vue3 recommend)

You can define a file named useTab:

// useTab.js

const tabs = ref([
  {
    id: 1,
    title: 'test title one',
    imageSrc: '/programs/test1.png',
    content: '',
    name: 'LOREM',
    href: '#test1',
    current: true,
  },
  {
    id: 2,
    title: 'test title two',
    imageSrc: '/programs/test2.png',
    content: '',
    name: 'IPSUM',
    href: '#test2',
    current: false,
  },
  {
    id: 3,
    title: 'test title three',
    imageSrc: '/programs/test3.png',
    content: '',
    name: 'PDF',
    href: '#test3',
    current: false,
  },
]);
export default function (
  const changeTab = (selectedTab: { id: number }) => {
    tabs.value.map((t) => {
      t.id === selectedTab.id ? (t.current = true) : (t.current = false)
    })
  }

  return { tabs, changeTab }
)

Then, you can use it anywhere.

// Home.vue

export default defineComponent({
  name: 'Home',

  components: {
    ProgramModal,
  },

  setup() {
    // ...

    // By this way, you can change tab in Home or anywhere you want.
    const { changeTab } = useTab();

    return { }
  },
})
// ProgramModal.vue

export default defineComponent({
  name: 'ProgramModal',

  setup() {
    const ariaLabel = computed(() => i18n.t('share') as string)

    const { tabs, changeTab } = useTab();

    return {
      tabs,
      changeTab,
      ariaLabel,
    }
  },
})

By the way, method 2 is the real composition api. :)

Related