Vue.js - Converting Airtable URL field data into clickable links

I’m working on a Vue.js project where I need to display data from Airtable and convert URL fields into proper clickable links.

I’ve successfully connected to the Airtable API and can display basic field data, but I’m struggling with formatting URL fields properly. The URLs are coming through as objects rather than simple strings, and I need to extract the actual URL value to create working href attributes.

Here’s my current template setup:

<div id="main-app">
    <div class="content-grid">
        <div v-for="record in records" class="item-card">
            <h2>{{ record['fields']['CompanyName'] }}</h2>
            <a :href="record['fields']['Website']['url']" v-if="record['fields']['Website']">
                <span>Visit: {{ record['fields']['Description'] }}</span>
            </a>
            <div>
                <em>URL Data: </em>
                {{ record['fields']['Website'] }}
            </div>                
        </div>
    </div>            
</div>

And here’s my Vue component logic:

var mainApp = new Vue({
  el: "#main-app",
  data: {
    records: []
  },
  mounted: function() {
    this.fetchRecords();
  },
  methods: {
    fetchRecords: function() {
      var component = this;
      var base_id = "your-base-id";
      var api_token = "your-api-token";
      this.records = [];
      axios
        .get(
          "https://api.airtable.com/v0/" +
            base_id +
            "/Companies?view=Main%20View",
          {
            headers: { Authorization: "Bearer " + api_token }
          }
        )
        .then(function(result) {
          component.records = result.data.records;
        })
        .catch(function(err) {
          console.log(err);
        });
    }
  }
});

The problem is that the URL field returns an object with nested properties instead of just the URL string. How do I properly access and format these URL fields to create working links in my Vue template?

Your code looks mostly correct, but you’re hitting the common issue where Airtable URL fields can be either strings or objects depending on how they’re entered.

I’ve dealt with this exact problem in multiple projects. The trick is handling both formats in your template. Here’s what I do:

<a :href="getUrl(record['fields']['Website'])" v-if="record['fields']['Website']">
    <span>Visit: {{ record['fields']['Description'] }}</span>
</a>

Then add this method to your Vue component:

methods: {
    fetchRecords: function() {
        // your existing code
    },
    getUrl: function(urlField) {
        if (typeof urlField === 'string') {
            return urlField;
        }
        if (urlField && urlField.url) {
            return urlField.url;
        }
        return '#';
    }
}

This handles three scenarios I’ve seen:

  1. URL entered as plain text (returns string)
  2. URL entered as proper link (returns object with url property)
  3. Empty or malformed data (returns fallback)

You’re seeing objects because someone probably entered the URLs using Airtable’s link formatting feature instead of just pasting plain text. This method covers both cases without breaking your app.

Had this exact same headache about a year ago when building a client directory. The problem is that Airtable’s URL field stores data in different formats depending on how users enter it. I fixed it by creating a computed property that normalizes the URL data before rendering. Instead of dealing with this mess in the template, handle it in your component logic: javascript computed: { normalizedRecords() { return this.records.map(record => { const website = record.fields.Website; let websiteUrl = null; if (website) { websiteUrl = typeof website === 'string' ? website : website.url; } return { ...record, websiteUrl: websiteUrl }; }); } } Then in your template: html <a :href="record.websiteUrl" v-if="record.websiteUrl"> <span>Visit: {{ record['fields']['Description'] }}</span> </a> This keeps your template clean and handles all the data transformation in one spot. The computed property auto-updates when your records change, so it plays nice with your API calls.