<div class="container" id="app">
  <h3 class="text-center">VueNews</h3>

  <section class="callout secondary">
    <h5 class="text-center">Filter by Category</h5>
    <form>
      <div class="row">
        <div class="large-6 columns">
          <select v-model="section">
							<option v-for="section in sections" :value="section">{{ section }}</option>
						</select>
        </div>
        <div class="large-6 columns">
          <a @click="getPosts(section)" class="button expanded">Retrieve</a>
        </div>
      </div>
    </form>
  </section>

  <h5 class="text-center uppercase" v-if="!loading">{{ title }}</b></h5>
  <div v-if="loading" class="loader"><img src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/0.16.1/images/loader-large.gif" alt="loader"></div>

  <news-list v-if="!loading" :results="results"></news-list>
</div>
.container {
  padding: 20px 0
}

.column:last-child:not(:first-child),
.columns:last-child:not(:first-child) {
  float: left;
}

.main_heading {
  margin: 10px 0 30px;
}

.callout {
  margin-bottom: 40px;
}

select {
  text-transform: capitalize;
}

.loader {
  text-align: center;
  padding: 40px;
}

.uppercase {
  text-transform: uppercase;
}
const NYTBaseUrl = "https://api.nytimes.com/svc/topstories/v2/";
const ApiKey = "your_api_key_here"; // replace with NYT API key 
const SECTIONS = "home, arts, automobiles, books, business, fashion, food, health, insider, magazine, movies, national, nyregion, obituaries, opinion, politics, realestate, science, sports, sundayreview, technology, theater, tmagazine, travel, upshot, world";

function buildUrl(url) {
  return 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nytimes-api.json';
}

Vue.component('news-list', {
  props: ['results'],
  template: `
    <section>
      <div class="row" v-for="posts in processedPosts">
        <div class="columns large-3 medium-6" v-for="post in posts">
          <div class="card">
          <div class="card-divider">
          {{ post.title }}
          </div>
          <a :href="post.url" target="_blank"><img :src="post.image_url"></a>
          <div class="card-section">
            <p>{{ post.abstract }}</p>
          </div>
        </div>
        </div>
      </div>
  </section>
  `,
  computed: {
    processedPosts() {
      let posts = this.results;

      // Add image_url attribute
      posts.map(post => {
        let imgObj = post.multimedia.find(media => media.format === "superJumbo");
        post.image_url = imgObj ? imgObj.url : "http://placehold.it/300x200?text=N/A";
      });

      // Put Array into Chunks
      let i, j, chunkedArray = [],
        chunk = 4;
      for (i = 0, j = 0; i < posts.length; i += chunk, j++) {
        chunkedArray[j] = posts.slice(i, i + chunk);
      }
      return chunkedArray;
    }
  }
});

const vm = new Vue({
  el: '#app',
  data: {
    results: [],
    sections: SECTIONS.split(', '), // create an array of the sections
    section: 'home', // set default section to 'home'
    loading: true,
    title: ''
  },
  mounted() {
    this.getPosts('home');
  },
  methods: {
    getPosts(section) {
      let url = buildUrl(section);
      axios.get(url).then((response) => {
        this.loading = false;
        this.results = response.data.results;
        let title = this.section !== 'home' ? "Top stories in '" + this.section + "' today" : "Top stories today";
        this.title = title + "(" + response.data.num_results + ")";
      }).catch((error) => {
        console.log(error);
      });
    }
  }
});
Run Pen

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css

External JavaScript

  1. https://unpkg.com/axios/dist/axios.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js