DEV Community

Grant Smith
Grant Smith

Posted on

3

Vue/Nuxt Component Card

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.

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free

Top comments (2)

Collapse
 
renesansz profile image
Rene Padillo πŸ‡΅πŸ‡­ β€’ β€’ Edited

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 β€’ β€’ Edited

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>

Image of Docusign

πŸ› οΈ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more