loading...

Vue/Nuxt Component Card

granttransition profile image Grant Smith ・1 min read

Hi,

I've been trying to learn Vue + Nuxt for static site generation. Whilst I can write the following in a way that will render out the correct HTML. I want to get my head around some of the more advanced features.

Aim:
Write a repeating card component that allows me to easily change elements within the component.

Here is where I am at…

Component:

<template>
  <div class="column is-4 has-text-centered">
    <div class="icon_block">
      <img src=":image.src" alt=":image.alt" width=":image.width" height=":image.height" />
    </div>
    <h4>{{ title }}</h4>
    <a href=":link.url" title=":link.title">{{ link.anchor }}</a>
  </div>
</template>

<script>
export default {
  name: "ContactCard",
  data: {
    contacts: [
        {
          id: '',
          image: {
            src: '',
            alt: '',
            width: ,
            height: ,
          },
          title: '',
          link: {
            url: '',
            title: '',
            anchor: ''
          }
    ]
  }
};
</script>

Template:

<template>
  <div class="footer_top">
    <div class="container">
      <div class="columns">
        <ContactCard
          v-for="contact in contacts" :key="id"
          :src="image.src"
          :alt="image.alt"
          :width="image.width"
          :height="image.height"
          :title="title"
          :url="link.url"
          :linkTitle="link.title"
          :anchor="link.anchor"
        >
        </ContactCard>
      </div>
    </div>
  </div>
</template>

<script>
import ContactCard from "~/components/ContactCard.vue";

export default {
  components: {
    ContactCard
  },
  data() function {
    return {
      contacts: [
        {
          id: '1',
          image: {
            src: '~assets/svg/address.svg',
            alt: 'Image Alt',
            width: 17,
            height: 30,
          },
          title: 'Address',
          link: {
            url: 'https://pagetolinkto',
            title: 'Title of link',
            anchor: 'Anchor Text'
          }
        },
      ]
    },
};
</script>

Needless to say, this isn't working and hence I was hoping someone might be able point me in the right direction.

Discussion

pic
Editor guide
Collapse
renesansz profile image
Rene Padillo 🇵🇭

Regarding your ContactCard component, you have to use props instead of data when you want to pass data to another component via v-bind or :

There are multiple ways to declare props:

  • you can pass an array of attributes
export default {
   props: ['src', 'alt', 'title'],
}
  • you declare it with properties and/or with default values
export default {
   props: {
      src: {
        type: String,
        required: true,
      },
      title: {
        type: String,
        default: '',
      },
   }
}

See more details about props in the official documentation.

Collapse
granttransition profile image
Grant Smith Author

Found a working solution, I hadn't declared contact in my template component, contact.image for example. Plus Rene comment about props really helped. Below is my working error-free code…

Component

<template>
  <div class="column is-4 has-text-centered" :id="id">
    <div class="icon_block">
      <img
        :src="image.src"
        :alt="image.alt"
        :width="image.width"
        :height="image.height"
      />
    </div>
    <h4>{{ heading }}</h4>
    <a :href="link.url" target="_blank" :title="link.title">
      {{ link.anchor }}
    </a>
  </div>
</template>

<script>
export default {
  name: "ContactCard",
  props: {
    id: '',
    image: {
      src: '',
      alt: '',
      width: '',
      height: '',
    },
    heading: '',
    link: {
      url: '',
      title: '',
      anchor: ''
    },
  },
};
</script>

Template

<template>
  <div class="footer_top">
    <div class="container">
      <div class="columns">
        <ContactCard
          v-for="contact in contacts"
          :key="contact.id"
          :image="contact.image"
          :src="contact.src"
          :alt="contact.alt"
          :width="contact.width"
          :height="contact.height"
          :heading="contact.title"
          :link="contact.link"
          :href="contact.url"
          :title="contact.title"
          :anchor="contact.anchor"
        ></ContactCard>
      </div>
    </div>
  </div>
</template>

<script>
import ContactCard from "~/components/ContactCard.vue";

export default {
  components: {
    ContactCard
  },
  data: function () {
    return {
      contacts: [
        {
          id: 1,
          image: {
            src: '/assets/svg/address.svg',
            alt: '######',
            width: 17,
            height: 30,
          },
          title: 'Address',
          link: {
            url: '######',
            title: '######',
            anchor: '######'
          }
        },
        {
          id: 2,
          image: {
            src: '/assets/svg/phone.svg',
            alt: '######',
            width: 34,
            height: 30,
          },
          title: 'Phone',
          link: {
            url: '######',
            title: '######',
            anchor: '######'
          }
        },
        {
          id: 3,
          image: {
            src: '/assets/svg/email.svg',
            alt: '######',
            width: 17,
            height: 30,
          },
          title: 'Email',
          link: {
            url: 'mailto:######',
            title: '######',
            anchor: '######'
          }
        },
      ]
    }
  }
};
</script>