Template Content

On this page, you'll learn how to display content from the Prismic API in your Vue application. This page will also teach you how to use these methods:

  • $prismic.asHtml()
  • $prismic.asText()
  • $prismic.asDate()
  • $prismic.asLink()

And these components:

  • <prismic-rich-text />
  • <prismic-embed />
  • <prismic-image />
  • <prismic-link />

By the end of this page, you will have content from Prismic displayed in your app.


Intro to templating

Content from Prismic comes in more than a dozen types. Most of these are simple primitive values, like Numbers or Booleans. Others are more complex structured values, like Titles, Rich Texts, and Links.

The examples on this page

Most of the examples on this page assume that you have queried a single document from the Prismic API and stored it in a variable called document, like so:

data() {
return {
document: null
}
},
methods: {
async getContent() {
const document = await this.$prismic.client.getByUID('page','example-page')
this.document = document
}
},
created() {
this.getContent()
}

Learn more about the structure of your response in "The structure of the API response," below.

With simple field types, you can inject them directly into your application:

Copy
<span>{{ document.data.example_number }}</span>
<!-- <span>74.5</span> -->

For structured fields types, we provide special utilities. To render Rich Text, for instance, we provide a rich text component:

Copy
<prismic-rich-text :field="document.data.example_rich_text" />

Further learning: fields

You can learn more about all of these fields in our Content Modeling documentation.

To get started, lets look at the structure of raw API response.

The structure of the API response

Multiple documents

When you make a standard query to the Prismic API, you will get a JSON object filled with results. Here is a truncated example of an API response containing some simple fields:

Copy
{
  page: 1,
  // ...
  results: [
    {
      uid: 'example_document',
      // ...
      data: {
        example_date: '2020-12-10',
        example_timestamp: '2020-12-10T04:05:09+0000',
        example_color: '#c7ab5d',
        example_number: 74.5,
        example_key_text: 'Example Key Text Value',
        example_select: 'North',
        example_boolean: true,
      }
    },
    // ...
  ]
}

So, if you store the response in a variable called "response," you might access a single data point like this:

Copy
response.results[0].data.example_key_text // 'Example Key Text Value'

In Vue, you might use that like this:

Copy
<div>
  {{ response.results[0].data.example_key_text }}
</div>

Or, more likely, you would loop over the results array and template each item, like this:

Copy
<ul>
  <li v-for="document in response.results" :key="document.id">
    {{ document.data.example_key_text }}
  </li>
</ul>

A single document

Unlike most queries, the helper functions $prismic.client.getSingle(), $prismic.client.getByUID(), and $prismic.client.getByID() will return the data for an individual document directly.

Here's a truncated example of the response for one of those queries:

Copy
{
  uid: 'about',
  // Metadata for this result
  // ...
  data: {
    example_date: '2020-12-10',
    example_color: '#c7ab5d',
    example_key_text: 'Example Key Text Value',
    // More content
    // ...
  }
}

Notice that the document is not nested in an array of results within a query response object, like in a query for multiple documents.

With a single document query, you might access your color field like this:

Copy
document.data.example_color
// '#c7ab5d'

Simple fields

The simple fields are:

  • boolean
  • color
  • date
  • timestamp
  • number
  • key text
  • select

These are represented as either a string, a number, or a boolean, and you can access them directly, like so:

Copy
document.data.example_number
// 74.5

Note: Working with dates

Dates come from the API as a string, in the formay YYYY-MM-DD. To convert a date string to a JavaScript Date object, you can use the built-in $prismic.asDate() method:

Copy
document.data.example_date
// '2020-12-10'

$prismic.asDate(document.data.example_date)
// Thu Dec 10 2020 01:00:00 GMT+0100 (Central European Standard Time)

Geopoints

The Geopoint field is served as an object with two properties: latitude and longitude. This is the structure of a geopoint:

Copy
// document.data.example_geopoint
{
  latitude: 48.85392410000001,
  longitude: 2.2913515000000073
},

You can access these properties directly:

Copy
document.data.example_geopoint.latitude
// 48.85392410000001

document.data.example_geopoint.longitude
// 2.2913515000000073

Embeds

This is the structure of an embed field:

Copy
// document.data.example_embed
{
  version: "1.0",
  url: "https://prismic.io",
  type: "link",
  title: "Make your website editable for the whole team - Prismic",
  provider_name: null,
  thumbnail_url: "https://images.prismic.io/prismic-website/6e49007fec52f99861047cdd55b3ab190ea04295_dev-landing-page-image.png?auto=compress,format",
  html: "<div data-type=\"unknown\"><a href=\"https://prismic.io\"><h1>Make your website editable for the whole team - Prismic</h1><img src=\"https://images.prismic.io/prismic-website/6e49007fec52f99861047cdd55b3ab190ea04295_dev-landing-page-image.png?auto=compress,format\"><p>Choose your technology. Use the API to fetch content. Empower your content team.</p></a></div>",
  embed_url: "https://prismic.io/"
},

You can template an embed with the embed component:

Copy
<prismic-embed :field="document.data.example_embed" />

Images

In Prismic, you can define an image's alt text, copyright, and alternate crops — all of which can also have their own alt text. All of this information is served in the API response. A simple image field might look like this:

Copy
// document.data.example_image
{
  dimensions: {
    width: 1920,
    height: 1302
  },
  alt: null,
  copyright: null,
  url: "https://images.prismic.io/sm-20201204-2/7d1fba99-5bec-4d59-b8eb-402706e2d36c_a-pril-62u95KgB49w-unsplash.jpg?auto=compress,format"
},

You can template an image with the image component:

Copy
<prismic-image :field="document.data.example_image" />

Rich Text and Titles

Rich Text and Titles are delivered in an array that contains information about the text structure. Here's an example of a Rich Text field (Title fields follow the same format):

Copy
// document.data.example_rich_text
[
  {
    type: "paragraph",
    text: "Example Rich Text Value",
    spans: [
      {
        start: 8,
        end: 17,
        type: "strong"
      }
    ]
  }
],

@prismicio/vue provides three ways to work with text.

Rich text component

Here's how to render Rich Text or a Title with the rich text component (HTML Serializer is optional):

Copy
<prismic-rich-text :field="document.data.example_rich_text" :htmlSerializer="optionalHtmlSerializer" />

What is an HTML Serializer?

The HTML Serializer defines the markup of your Rich Text. (For example: italic text should have <em> tags.) @prismicio/vue contains a default HTML Serializer for standard markup, but you can create your own HTML Serializer if you want to customize your markup. To learn how, see the section on Advanced Templating.

Rich text helper function

Here's how to render Rich Text or a Title with the rich text helper function:

Copy
<div v-html="$prismic.asHtml(document.data.example_rich_text, optionalHtmlSerializer)" />

Plaintext helper function

Here is how to get plain text from a Rich Text or title field with the plaintext helper function:

Copy
<div>{{ $prismic.asText(document.data.example_rich_text) }}</div>

Links in Rich Text

Links in Rich Text are rendered with the default Link Resolver function defined in your Vue app setup. See more info on link resolving below.

Links and Content Relationships

The Link field allows you to link to an external webpage, an internal Prismic document, or an item in your media library (like a PDF). The Content Relationship field allows you to link specifically to an internal Prismic document.

Here's an example Content Relationship (a Link takes a similar format):

Copy
// document.data.example_content_relationship
{
  id: "X9C65hEAAEFIAuLo",
  type: "page",
  tags: [],
  slug: "another-document",
  lang: "en-us",
  uid: "another-document",
  link_type: "Document",
  isBroken: false
},

There are two things that you might want to do with a link:

  • Link to another page or media item, internally or externally
  • Pull in content from another document

Here's how to do those two things:

Link to another page

Internal linking always requires a Link Resolver.

What is a Link Resolver?

You may remember that you created a Link Resolver in the setup step. If you need a refresher, return to the setup page.

In simple terms, Prismic does not know the structure of your Vue app. A Link Resolver is a function that tells Vue how to construct URLs for Prismic documents.

By default, @prismicio/vue will use the Link Resolver that you added in your setup to resolve links. However, when templating Links and Content Relationships, you can also pass a custom Link Resolver.

Here is how to create a link with the link component:

Copy
<prismic-link :field="document.data.example_link">Example Link</prismic-link>

Here is how to create a link with the link helper function:

Copy
<router-link :to="$prismic.asLink(document.data.example_link)" />Example Link</router-link>

Pull in content from another document

To pull in content from another content, you must fetch that content in your API Query, using the graphQuery or fetchLinks option. To do so, add an options object to your query, with fetchLinks as a key, and the field that you want to fetch as the value. The field is formatted as [custom-type].[field]:

Copy
$prismic.client.getByUID('post', 'hello-world', { fetchLinks: 'page.example_key_text' })

You can learn more about how to use these options in the section on Advanced Querying.

Once you have adjusted your API query, the linked content will appear in a "data" object nested in the Link or Content Relationship field:

Copy
// document.data.example_content_relationship
{
  id: "X9C65hEAAEFIAuLo",
  type: "page",
  tags: [],
  slug: "another-page-title",
  lang: "en-us",
  uid: "page-2",
  data: {
    example_key_text: "Another Page Key Text"
  },
  link_type: "Document",
  isBroken: false
},

You can then template that content as usual:

Copy
<span>{{ document.data.example_content_relationship.data.example_key_text }}</span>
<!-- <span>Another Page Key Text</span> -->

Slices and Groups

Slices and Groups both allow you to create repeatable content templates. Groups are available in the main section of your document, and Slices are available in the Slice Zone.

The difference between Groups and Slices is that Groups can only be repeated, while Slices can be repeated and rearranged.

Groups

A Group field renders an array of content groups:

Copy
// document.data.example_group
[
  {
    example_boolean_in_group: true,
    example_number_in_group: 3,
    example_key_text_in_group: "dog"
  },
  {
    example_boolean_in_group: false,
    example_number_in_group: 7,
    example_key_text_in_group: "cat"
  },
],

To template a Group, you can use a v-for:

Copy
<ul>
  <li v-for="item in document.data.example_group" key="item.example_key_text_in_group">
    {{ example_key_text_in_group }} - {{ example_number_in_group }}
  </li>
</ul>

Slices

Slices are repeatable, rearrangeable content sections. Slices are found in the body section of your document:

Copy
// document.data.body
[
  {
    slice_type: 'title_slice',
    slice_label: null,
    items: [{}],
    primary: {
      title: 'Some colorful numbers and birthdays'
    }
  },
  {
    slice_type: 'birthday_slice',
    slice_label: null,
    items: [{}],
    primary: {
      person: 'Alan Turing',
      birthday: '1912-06-23'
    }
  },
  {
    slice_type: 'birthday_slice',
    slice_label: null,
    items: [{}],
    primary: {
      person: 'Grace Hopper',
      birthday: '1906-12-09'
    }
  }
]

Slices cannot have "Group" fields, but every Slice has a "non-repeatable" and "repeatable" section. The repeatable section functions just like a group field.

In principle, Slices are rendered by looping over the body array and then executing a switch statement on each Slices to determine how to template it. However, we recommend using the SliceZone component to render your Slices. To learn how to use the SliceZone, see the SliceZone section.

Metadata

An API response also contains metadata for the API response and for the individual result. Here's a truncated example for a standard query of multiple documents, as discussed above:

Copy
{
  // Response metadata
  page: 1,
  results_per_page: 20,
  results_size: 3,
  total_results_size: 3,
  total_pages: 1,
  next_page: null,
  prev_page: null,
  results: [
    {
      // Document metadata
      id: 'YBQvbxUAACUAa5jh',
      uid: 'example-uid',
      type: 'page',
      href: 'https://your-repo-name.cdn.prismic.io/api/v2/documents/sear...',
      tags: [],
      first_publication_date: '2021-01-29T15:53:23+0000',
      last_publication_date: '2021-01-29T15:53:23+0000',
      slugs: ['hello-world'],
      linked_documents: [],
      lang: 'en-us',
      alternate_languages: [],
      data: {
        // Document data
        example_date: '2020-12-10',
        example_timestamp: '2020-12-10T04:05:09+0000',
        // ... More document data
      }
    },
    // ... More documents
  ]
}

The response metadata is often used for more advanced query functions, such as pagination.

The metadata for a single document includes some useful information, such as the document's UID.


Next steps

You should now have some content from Prismic displayed in your Vue app. On the next page, we'll deploy your app.


Was this article helpful?
Not really
Yes, Thanks

Can't find what you're looking for? Get in touch with us on our Community Forum.