Search code examples
apiurlaxiosvue-clidynamic-url

Vue CLI clickable dynamic url from a news API


I'm fetching data from newsapi.org and I want there to be a clickable link after the headlines so that you can read more about the article. But I can't make it work.

Maybe this is too advanced for me since I'm no good at coding. I thought maybe there was a simple way of making the dynamic urls work.

<template>
  <div class="api">
    <h1>Latest gossip</h1>
    <br />
    <div v-for="item of items" v-bind:key="item.id">
      <h3>{{ item.title }}</h3>
      <p>{{ item.description }}</p>
      <a v-bind:href="adress">
        {{ item.url }}
      </a>
    </div>
  </div>
</template>

I use axios.

<script>
import axios from "axios";
export default {
  name: "Api",
  props: ["articles"],

  data() {
    return {
      items: [],
      adress: "item.url"
    };
  },

  mounted() {
    this.getInfo();
  },

  methods: {
    getInfo() {
      axios({
        method: "GET",

        url:
          "https://cors-anywhere.herokuapp.com/https://newsapi.org/v2/top-headlines?country=se&category=entertainment&apiKey=XXX",

        dataType: "json",

        headers: {
          "X-Requested-With": "XMLHttpRequest",
          "Access-Control-Allow-Origin": "*"
        }
      }).then(res => {
        /* eslint-disable no-console */
        console.log(res.data);
        this.items = res.data.articles;
      });
    }
  }
};
</script>

Solution

  • So from what I understand, you're going to have a separate url for each different news article. It seems like there is a slight misunderstanding about how that information will be passed into the anchor tag, where it should be coming from, and how you're using data.

    First, let's address your data method. If you look at the structure of your data you can see that you have an items property, which is an array and an adress property, which is set to a string.

    data() {
      return {
        items: [],
        adress: "item.url"
      };
    },
    

    The problem here is that adress is not dynamic. It will always be the literal string "item.url", which is to say that it will always represent those characters ("item.url") in that order, but it doesn't actually represent any specific item's url property.

    The good news is that you should already be seeing the correct url displayed on your page here:

    <a v-bind:href="adress">
      {{ item.url }}
    </a>
    

    Remember that an anchor tag in this case has two parts: 1. What we're displaying to the user. 2. Where we're telling the browser to redirect to.

    The proper syntax here (without Vue) would be something like:

    <a href="https://somelinktogoto.com">
      Some text to display
    </a>
    

    What you're currently saying is: "I want an anchor tag to display the item's url to the user and redirect to whatever is stored in the data property called adress". Since adress is only storing the string "item.url", if you inspect your html that's been generated in your browser, I would suspect that all of your anchor tags look something like this:

    <a href="item.url">
       https://somenewsarticle.com
    </a>
    

    Luckily, the fix here is simple. Since you're already using v-bind, the href can use dynamic information, or information that's stored in your data somewhere, which can be referenced by its name. Then you can choose to display anything you'd like to your user. You can also delete your adress property from data, because it's not serving any purpose if all the urls are contained within items.

    Try:

    <a v-bind:href="item.url" target="_blank">
      Read more...
    </a>
    
    data() {
      return {
        items: [],
      }
    }
    

    Also, no one is good at coding at first, just keep trying to understand how data is flowing and you'll get there!