Simple Photo App with Vue.js, Axios and Flickr API — Part 1

Next, empty out Home.

vue:We need a way to enter and submit a search term.

Add a form to the template that contains one text input and a submit button.

The text input should usev-model to connect to a tag data property.

The submit button should fire a search method when clicked, BUT it should not reload the page (hence the prevent modifier on the click event).

Make sure to actually add the data() function for the tag property and the methods section with the search function.

For now the search function can just log this.

tag to the console:After a user submits their search term, the page should populate with photos that have been tagged with that term.

The template should display a loading.

message while the data is being fetched and then include an unordered list of photos (using v-for) once it’s ready.

Based on the above, our template is now using two new data properties, loading and images, so be sure to add them to the data() function.

Next, our search method needs to do a couple of things.

When it’s first called, it should change loading to true, since the data fetching process is underway.

Then it should make a request to the Flickr API using axios, and when the response (image data) is available, populate images with an array of images and set loading to false.

Let’s break the axios/API call part down a bit more.

For clarity I separated out the actual API call into its own method, fetchImages().

To use axios, I imported it at the top of the script section, along with config, where our api_key is stored (because we’ll need that momentarily as well).

axios then needs an object that specifies what kind of request we’re making (the method), where we’re making a request to (the url), and a bunch of parameters that further specify what kind of information we want from the url.

The params object has the following contents:method — we use the flickr.

photos.

search method to perform a searchapi_key — we pass in our api_key so Flickr trusts ustags — the terms we want to search for, provided by our tag data propertyextras — any additional info we want about the photos that get returned.

We want to see the photo so we need the url_n string.

owner_name tell us who took the photo.

datetaken tells us when the photo was taken.

And views tell us how many people have viewed the photo.

You can find a full list of what’s available for a given photo here, and you can play around with the flickr.

photos.

search method here.

The rest of the params specify how many photos we get back and what kind of format the data is presented to us in.

json will allow us to easily navigate the data structure in Javascript.

fetchImages() handles that actual retrieval of the photos, but it doesn’t populate images.

That happens in a subsequent callback once the data is ready.

We know the data is ready when a Promise is returned.

Promises are what allow us to retrieve data asynchronously.

In other words, we can ask axios to work on getting the photo data for us while also letting Vue do other things.

In short, Promises help our app run faster and perform multiple tasks at once.

When the Promise is returned with our data, we tell Vue what to do with it.

The then() method is called when a Promise is returned successfully.

It accepts the response, which contains a data object.

Inside data, we’ll find a photos object, which contains an array of photos named photo.

That’s what we want images to store.

Once we do that, we can mark loading as false and reset our tag property.

then((response) => { this.

images = response.

data.

photos.

photo; this.

loading = false; this.

tag = "";})After all this, you should get similar output to the following:Step 5: Make an ImageCard ComponentYay!.We’ve got access to data.

Now let’s make it human readable by updating our template.

Inside the unordered list of Home.

vue, add:.

<li v-for="image in images" :key="image.

id"> <img :src="image.

url_n" :alt="image.

title"> <div> <p v-if="image.

title">{{image.

title}}</p> <p v-else>No Title Found</p> <p>By {{image.

ownername}}</p> <section> <p>{{image.

datetaken}}</p> <p>Views: {{image.

views}}</p> </section> </div></li>.

That’s better, but the page still needs some styling.

To simplify Home.

vue, pull the above markup into its own component.

Inside the components directory, delete HelloWorld.

vue and make a file called ImageCard.

vue.

Place the following inside:The above component has the same markup from Home.

vue, and receives an image prop so it knows what data to render.

To use the ImageCard component, import it in Home.

vue and register it:.

import ImageCard from '@/components/ImageCard';export default { name: 'home', components: { ImageCard }, .

}Then add it to the template in place of the previous <li> markup:.

<ul v-else> <image-card v-for="image in images" :key="image.

id" :image="image" /></ul>.

The result should be the same as before in your browser.

Now add styles to Home.

vue and ImageCard.

vue to make it pretty.

During the project setup I didn’t install a pre-processor, so run the following in order to use SCSS:npm install -D sass-loader node-sassUpdate ImageCard.

vue with class names in the template and a styles section:Home.

vue also needs some love.

Style the navbar to be full-width but leave the list of photos is still centered with some margins.

I also made a few other structural template modifications and of course added new class styles:One last part here, I made a few CSS changes to App.

vue as well:The output should then look like this:Step 6: Formatting dates with Moment.

jsOur cards are looking great, but the dates are a little ugly.

Moment.

js is a popular date formatting library we can use.

Install it with:npm install moment –saveInside ImageCard.

vue, import moment and create a filter to format the date.

Think of filters as functions that receive an input in need of formatting.

The filter returns output in a way that we want.

Visit the string formatting page for more ways to control how the dates show up:<script>import moment from 'moment';export default { name: 'ImageCard', props: [ 'image' ], filters: { moment(date) { return moment(date).

format("MMMM Do, YYYY"); } }}</script>Use the filter in the template by adding the pipe character after the date we want to format, and referencing our filter by its name:<p class="image-date">{{image.

datetaken | moment}}</p>Step 7: Basic data cleaningYou might’ve noticed that sometimes images don’t show up, producing the following in your browser:This is probably due to data inconsistency from Flickr (ie a missing url_n string).

A simple solution is to create a computed property called cleanImages that filters out any image that doesn’t have a url_n, and use cleanImages to loop through in our template instead of images.

In Home.

vue, add the computed property:.

computed: { cleanImages() { return this.

images.

filter(image => image.

url_n) }},Then in the template, change images to cleanImages:<template>.

<image-card v-for="image in cleanImages" :key="image.

id" :image="image" />.

</template>And there you have it!.We’ve used axios and Vue.

js to make a simple get request to the Flickr API, and made it look nice with basic CSS styles and some help from Moment.

js!.Next, we’ll add image detail pages, and refactor our app a bit from a routing/page standpoint.

See you then!.????.

. More details

Leave a Reply