{"id":3907,"date":"2018-03-26T09:11:39","date_gmt":"2018-03-26T09:11:39","guid":{"rendered":"http:\/\/www.nikola-breznjak.com\/blog\/?p=3907"},"modified":"2025-06-12T17:26:42","modified_gmt":"2025-06-12T17:26:42","slug":"getting-started-vue-js-2-building-giphy-search-application","status":"publish","type":"post","link":"https:\/\/nikola-breznjak.com\/blog\/javascript\/vue-js\/getting-started-vue-js-2-building-giphy-search-application\/","title":{"rendered":"Getting started with Vue.js 2 by building a Giphy search application"},"content":{"rendered":"<h2>TL;DR<\/h2>\n<p>This tutorial follows the same pattern as <a href=\"https:\/\/www.pluralsight.com\/guides\/front-end-javascript\/getting-started-with-angular-2-by-building-a-giphy-search-application\">this Angular 2<\/a> post. You&#8217;ll learn how to use <a href=\"https:\/\/github.com\/vuejs\/vue-cli\">Vue CLI<\/a>  to build a Vue.js 2 application for searching <a href=\"http:\/\/giphy.com\/\">Giphy&#8217;s gifs<\/a> by using <a href=\"https:\/\/github.com\/Giphy\/GiphyAPI\">their API<\/a>.<\/p>\n<p>The main reason for making this post was to evaluate a bit more lightweight solution than Angular or React.<\/p>\n<blockquote><p>\n  I&#8217;m using Vue.js 2, and I&#8217;ll be referring to it as just Vue.js in the rest of this post.\n<\/p><\/blockquote>\n<h2>Introduction<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/CseGOCb.png\" alt=\"\" \/><\/p>\n<p>Let&#8217;s be honest, even those of us that don&#8217;t actually hate the JavaScript ecosystem can understand the frustration with the fact that new JS frameworks are popping up all the time.<\/p>\n<p>I stuck to the Angular bandwagon ever since version 1.0. Even though I would recommend starting a new SPA project with it, I must say that my recent research led me to believe that due to Vue&#8217;s progressive and flexible nature, it&#8217;s a perfect fit for the teams that have to rewrite old codebases <strong>one step at a time<\/strong>.<\/p>\n<p>If you want to check out some detailed comparisons between popular frontend frameworks, here are two great posts:<\/p>\n<ul>\n<li><a href=\"https:\/\/medium.com\/unicorn-supplies\/angular-vs-react-vs-vue-a-2017-comparison-c5c52d620176\">Angular vs. React vs. Vue: A 2017 comparison<\/a><\/li>\n<li><a href=\"https:\/\/vuejs.org\/v2\/guide\/comparison.html\">Vue.js vs. React, Angular, AngularJS, Ember, Knockout, Polymer, Riot<\/a><\/li>\n<\/ul>\n<p>General &#8216;framework war&#8217; kind of questions I tend to answer in the following way:<\/p>\n<blockquote><p>\n  Please just stop with the analysis paralysis already.<\/p>\n<p>  Do your research, pick a framework (any framework for that matter) that the community is using, use it, and see how far it gets you.<\/p>\n<p>  All these talks about X being slow or Y being better just make no sense until you try it yourself for your use case and preference. Besides, nowadays the speed will not be a deciding factor among the top JS frameworks.\n<\/p><\/blockquote>\n<p>With all this said, fasten your seatbelts, take a venti (or trenta) sized cup of coffee, and let&#8217;s go!<\/p>\n<h2>Demo app<\/h2>\n<p>As said, we&#8217;ll build an application for searching (and showing) gifs from the <a href=\"http:\/\/giphy.com\/\">Giphy<\/a> website by using their <a href=\"https:\/\/github.com\/Giphy\/GiphyAPI\">API<\/a>.<\/p>\n<p>You can fork the complete source code on <a href=\"https:\/\/github.com\/Hitman666\/GiphySearch_Vue2\">Github<\/a>.<\/p>\n<h2>Prerequisites<\/h2>\n<p>Make sure that you have the following tools installed:<\/p>\n<ul>\n<li>Node.js  &#8211; <a href=\"https:\/\/hackhands.com\/how-to-get-started-on-the-mean-stack\/#installing-node-js\">step by step guide<\/a>  for both Windows and Mac<\/li>\n<li>Git  &#8211; a fun <a href=\"https:\/\/dev.to\/hitman666\/learn-git-fast-as-if-your-job-depends-on-it-dgj\">getting started<\/a> tutorial <\/li>\n<\/ul>\n<h2>Vue CLI<\/h2>\n<p>As their README says:<\/p>\n<blockquote><p>\n  Vue CLI aims to be the standard tooling baseline for the Vue ecosystem. It ensures the various build tools work smoothly together with sensible defaults so you can focus on writing your app instead of spending days wrangling with configurations. At the same time, it still offers the flexibility to tweak the config of each tool without the need for ejecting.\n<\/p><\/blockquote>\n<p>To installing <code>vue-cli<\/code>, run:<\/p>\n<p><code>npm install -g @vue\/cli<\/code><\/p>\n<p>You can confirm that the installation went well if you run:<\/p>\n<p><code>vue --help<\/code><\/p>\n<blockquote><p>\n  \u26a0\ufe0f Just for reference (in case you follow this tutorial at a later stage and something is not the same as I output it here), my version (<code>vue --version<\/code>) as of this writing is <code>2.9.3<\/code>.\n<\/p><\/blockquote>\n<h2>Starting a new app with Vue CLI<\/h2>\n<p>We&#8217;ll call our app, originally, <code>giphy-search<\/code>. So, let&#8217;s start a new app using <code>vue-cli<\/code>:<\/p>\n<p><code>vue init webpack giphy-search<\/code><\/p>\n<p>You should get an output similar to this:<\/p>\n<pre><code># nikola in ~\/DEV\/Vue [13:37:99]\n? Project name giphy-search\n? Project description Giphy search app with Vue.js\n? Author Nikola Bre\u017enjak &lt;nikola.breznjak@gmail.com&gt; \/\/ I welcome spam ;)\n? Vue build standalone\n? Install vue-router? No\n? Use ESLint to lint your code? Yes\n? Pick an ESLint preset Standard\n? Set up unit tests No\n? Setup e2e tests with Nightwatch? No\n? Should we run `npm install` for you after the project has been created? (recommended) npm\n\n   vue-cli \u00b7 Generated \"giphy-search\".\n\n# Installing project dependencies ...\n\nnpm notice created a lockfile as package-lock.json. You should commit this file.\nadded 1349 packages in 28.159s\n\nRunning eslint --fix to comply with chosen preset rules...\n# ========================\n\n&gt; giphy-search@1.0.0 lint \/Users\/nikola\/DEV\/TeltechRepos\/FrontendEvaluation\/Vue\/giphy-search\n&gt; eslint --ext .js,.vue src \"--fix\"\n\n# Project initialization finished!\n# ========================\n\nTo get started:\n\n  cd giphy-search\n  npm run dev\n\nDocumentation can be found at https:\/\/vuejs-templates.github.io\/webpack\n<\/code><\/pre>\n<p>After this command finishes, let&#8217;s <code>cd<\/code> into the project and run it:<\/p>\n<pre><code>cd giphy-search\nnpm run dev\n<\/code><\/pre>\n<p>You should get:<\/p>\n<pre><code>DONE  Compiled successfully in 3745ms\n\nYour application is running here: http:\/\/localhost:8080\n<\/code><\/pre>\n<p>You should see the following page in your browser if you visit this link: http:\/\/localhost:8080.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/CdB6Kz3.png\" alt=\"\" \/><\/p>\n<h3>Folder structure<\/h3>\n<p>Now, let&#8217;s open this project in the editor of your choice (I&#8217;m using <a href=\"https:\/\/code.visualstudio.com\/\">Visual Studio Code<\/a>), and you should see something like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/GtxQkvQ.png\" alt=\"\" \/><\/p>\n<p>As I said, this is an introduction tutorial to get you running fast so I won&#8217;t be going into any specific details this time (this is up for some other posts), so here we&#8217;ll only focus on the <code>src<\/code> folder. The contents of that folder should be something like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/7PsGI6Y.png\" alt=\"\" \/><\/p>\n<h3>Adding content<\/h3>\n<p>Ok, so, let&#8217;s add something to our app.<\/p>\n<p>But, where to start?<\/p>\n<p>Well, one of the first things I do when I come to a project for the first time is look at the generated output. Then I try to find the strings corresponding to that output within the source code.<\/p>\n<p>So, if you search for the string <code>Welcome to Your Vue.js App<\/code>, you&#8217;ll see the string is within the <code>HelloWorld.vue<\/code> file. This file contains the following (<code>...<\/code> is used for brevity in the listing below):<\/p>\n<pre><code>&lt;template&gt;\n  &lt;div class=\"hello\"&gt;\n    &lt;h1&gt;{{ msg }}&lt;\/h1&gt;\n    &lt;h2&gt;Essential Links&lt;\/h2&gt;\n    &lt;ul&gt;\n      ...\n    &lt;\/ul&gt;\n    &lt;h2&gt;Ecosystem&lt;\/h2&gt;\n    &lt;ul&gt;\n      ...\n    &lt;\/ul&gt;\n  &lt;\/div&gt;\n&lt;\/template&gt;\n\n&lt;script&gt;\nexport default {\n  name: 'HelloWorld',\n  data () {\n    return {\n      msg: 'Welcome to Your Vue.js App'\n    }\n  }\n}\n&lt;\/script&gt;\n\n&lt;!-- Add \"scoped\" attribute to limit CSS to this component only --&gt;\n&lt;style scoped&gt;\nh1, h2 {\n  font-weight: normal;\n}\nul {\n  list-style-type: none;\n  padding: 0;\n}\nli {\n  display: inline-block;\n  margin: 0 10px;\n}\na {\n  color: #42b983;\n}\n&lt;\/style&gt;\n<\/code><\/pre>\n<p>Without knowing anything about Vue.js, we can see where we would change the <code>Welcome to Your Vue.js App<\/code> text. So, let&#8217;s change that to <code>Welcome to GiphySearch<\/code>. While you do that, also remove the contents of the <code>style<\/code> tag.<\/p>\n<h3>Adding input and a button<\/h3>\n<p>Our basic application should have one input field and one button.<\/p>\n<p>To do this, add the following code to the <code>HelloWorld.vue<\/code> file:<\/p>\n<pre><code>&lt;input name=\"search\"&gt;\n\n&lt;button&gt;Search&lt;\/button&gt;\n<\/code><\/pre>\n<h3>Actions<\/h3>\n<p>Having a simple search input field and a button doesn&#8217;t help much. We want to click the button, and we want to output something to the console just to verify it&#8217;s working correctly.<\/p>\n<p>So, this is how we define a function that will handle button click in Vue:<\/p>\n<p><code>&lt;button @click=\"performSearch\"&gt;Search&lt;\/button&gt;<\/code><\/p>\n<p>But, now if open up your DevTools, you&#8217;ll see an error like:<\/p>\n<pre><code>webpack-internal:\/\/\/.\/node_modules\/vue\/dist\/vue.esm.js:592 [Vue warn]: Property or method \"performSearch\" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option or for class-based components, by initializing the property. See https:\/\/vuejs.org\/v2\/guide\/reactivity.html#Declaring-Reactive-Properties.\n\nfound in\n\n---&gt; &lt;HelloWorld&gt; at src\/components\/HelloWorld.vue\n       &lt;App&gt; at src\/App.vue\n         &lt;Root&gt;\n<\/code><\/pre>\n<p>That&#8217;s because we haven&#8217;t defined the <code>performSearch<\/code> function anywhere.<\/p>\n<p>Let&#8217;s do that now. In the <code>HelloWorld.vue<\/code> file, add the following function definition inside the <code>script<\/code> tag, <code>methods<\/code> object property:<\/p>\n<pre><code>&lt;script&gt;\nexport default {\n  name: \"HelloWorld\",\n  data() {\n    return {\n      msg: \"Welcome to GiphySearch\"\n    };\n  },\n  methods: {\n    performSearch: function() {\n      console.log(\"clicked\");\n    }\n  }\n};\n&lt;\/script&gt;\n<\/code><\/pre>\n<p>With this, we defined the <code>performSearch<\/code> function, which doesn&#8217;t accept any parameters and it does not return anything.<\/p>\n<h3>Taking input<\/h3>\n<p>What if we would like to print to the console the string that someone typed in the input field?<\/p>\n<p>Well, first we need to add a new attribute to the input field:<\/p>\n<p><code>&lt;input name=\"title\" v-model=\"searchTerm\"&gt;<\/code><\/p>\n<p>The <code>v-model<\/code> is a directive that instructs Vue to bind the input to the new <code>searchTerm<\/code> variable.<\/p>\n<p>Finally, change the <code>performSearch<\/code> function to this:<\/p>\n<pre><code>performSearch: function() {\n    console.log(this.searchTerm);\n}\n<\/code><\/pre>\n<h3>Giphy search API<\/h3>\n<p>Finally, we come to the cool part, and that is to fetch some data from the service and to show it in our app (in our case, we&#8217;ll show images).<\/p>\n<p>So, how do we get this API? Well, if you do a simple Google search for giphy api and open the <a href=\"https:\/\/github.com\/Giphy\/GiphyAPI\">first link<\/a> you&#8217;ll get the documentation for their API.<\/p>\n<p>We need the search API. If you scroll a bit, you&#8217;ll find the following link:<\/p>\n<p>http:\/\/api.giphy.com\/v1\/gifs\/search?q=funny+cat&#038;api_key=dc6zaTOxFJmzC<\/p>\n<p>Great, now we see what kind of a request we need to create to search Giphy&#8217;s gif database for a certain term.<\/p>\n<p>If you open this link in the browser, you&#8217;ll see what the service returns. Something like:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/skihplVl.png\" alt=\"\" \/><\/p>\n<p>In the next section, we&#8217;ll cover retrieving this data from within our app.<\/p>\n<h3>Vue.js HTTP requests<\/h3>\n<p>We have several options for doing HTTP requests in Vue.js, and some may see this flexibility as a pro and some may see it as a con. Either way, for more options, check out <a href=\"https:\/\/www.techiediaries.com\/vuejs-ajax-http\/\">this post<\/a>.<\/p>\n<p>I chose to go with Axios, as it&#8217;s a very popular JavaScript library for making HTTP requests. It&#8217;s an HTTP client that makes use of the modern Promises API by default (instead of the ~~ugly~~ not so nice JavaScript callbacks) and runs on both the client and the server (i.e. Node.js).<\/p>\n<p>In your Terminal\/Command prompt enter the following command to install axios via npm:<\/p>\n<p><code>npm install axios --save<\/code><\/p>\n<p>Import axios in the <code>HelloWorld.vue<\/code> file just after the <code>script<\/code> tag:<\/p>\n<p><code>import axios from \"axios\";<\/code><\/p>\n<p>The <code>performSearch<\/code> function should now look like this:<\/p>\n<pre><code>var link = \"http:\/\/api.giphy.com\/v1\/gifs\/search?api_key=dc6zaTOxFJmzC&amp;q=\";\nvar apiLink = link + this.searchTerm;\n\naxios\n.get(apiLink)\n.then(response =&gt; {\n    console.log(response);\n})\n.catch(error =&gt; {\n    console.log(error);\n});\n<\/code><\/pre>\n<p>Just for reference, to put it all in one listing, the contents of the <code>HelloWorld.vue<\/code> file should be:<\/p>\n<pre><code>&lt;template&gt;\n  &lt;div class=\"hello\"&gt;\n    &lt;h1&gt;{{ msg }}&lt;\/h1&gt;\n    &lt;input name=\"title\" v-model=\"searchTerm\"&gt;\n\n    &lt;button @click=\"performSearch()\"&gt;Search&lt;\/button&gt;\n  &lt;\/div&gt;\n&lt;\/template&gt;\n\n&lt;script&gt;\nimport axios from \"axios\";\nexport default {\n  name: \"HelloWorld\",\n  data() {\n    return {\n      msg: \"Welcome to GiphySearch\"\n    };\n  },\n  methods: {\n    performSearch: function() {\n      console.log(this.searchTerm);\n\n      var link = \"http:\/\/api.giphy.com\/v1\/gifs\/search?api_key=dc6zaTOxFJmzC&amp;q=\";\n      var apiLink = link + this.searchTerm;\n\n      axios\n        .get(apiLink)\n        .then(response =&gt; {\n          console.log(response.data);\n        })\n        .catch(error =&gt; {\n          console.log(error);\n        });\n    }\n  }\n};\n&lt;\/script&gt;\n<\/code><\/pre>\n<p>Now, if you run the app, enter something in the search box, and click the search button, you&#8217;ll see something like this in your console log:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/N2Zs7Ch.png\" alt=\"\" \/><\/p>\n<p>You can see that we&#8217;re getting back the <code>response<\/code> object and that in its <code>data<\/code> property there are 25 objects, which hold information about the images that we want to show in our app.<\/p>\n<p>And, well, this is all great now, but we don&#8217;t want to be logging out our objects to the console, we want to show them in our app.<\/p>\n<p>To show the image, we need to position ourselves on the object <code>images<\/code>, then <code>original<\/code>, and finally on the <code>url<\/code> property.<\/p>\n<p>Also, we don&#8217;t want to just show one image but all of the images. We&#8217;ll use the <code>v-for<\/code> directive for that:<\/p>\n<p><code>&lt;img v-for=\"g in giphies\" :key=\"g.id\" src=\"{{g.images.original.url}}\"&gt;<\/code><\/p>\n<p>For reference, here&#8217;s the full listing of <code>HelloWorld.vue<\/code> file:<\/p>\n<pre><code>&lt;template&gt;\n  &lt;div class=\"hello\"&gt;\n    &lt;h1&gt;{{ msg }}&lt;\/h1&gt;\n    &lt;input name=\"title\" v-model=\"searchTerm\"&gt;\n\n    &lt;button @click=\"performSearch()\"&gt;Search&lt;\/button&gt;\n\n    &lt;div&gt;\n        &lt;img v-for=\"g in giphies\" :key=\"g.id\" :src=\"g.images.original.url\"&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/template&gt;\n\n&lt;script&gt;\nimport axios from \"axios\";\nexport default {\n  name: \"HelloWorld\",\n  data() {\n    return {\n      msg: \"Welcome to GiphySearch\",\n      searchTerm: \"cat\",\n      giphies: []\n    };\n  },\n  methods: {\n    performSearch: function() {\n      console.log(this.searchTerm);\n\n      var link = \"http:\/\/api.giphy.com\/v1\/gifs\/search?api_key=dc6zaTOxFJmzC&amp;q=\";\n      var apiLink = link + this.searchTerm;\n\n      axios\n        .get(apiLink)\n        .then(response =&gt; {\n          this.giphies = response.data.data;\n        })\n        .catch(error =&gt; {\n          console.log(error);\n        });\n    }\n  }\n};\n&lt;\/script&gt;\n<\/code><\/pre>\n<p>At this point, if we take a look at the app and search for example for &#8216;cat coding&#8217; we&#8217;ll get this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/N3o2RAN.png\" alt=\"\" \/><\/p>\n<p>Although the result doesn&#8217;t look sleek, our code does exactly what it&#8217;s supposed to do. If you want it to look nicer, feel free to add more CSS.<\/p>\n<p><a href=\"https:\/\/bulma.io\/\">Bulma<\/a> is a cool framework that I used recently in the <a href=\"https:\/\/dev.to\/hitman666\/jwt-authentication-in-an-angular-application-with-a-go-backend--13cg\">JWT authentication in an Angular application with a Go backend<\/a> post.<\/p>\n<h2>Conclusion<\/h2>\n<p>In this tutorial, you learned how to get started with using Vue.js by building an application for searching Giphy&#8217;s gifs by using their API.<\/p>\n<p>Please leave any comments and feedback in the discussion section below!<\/p>\n<p>Thank you for reading!<\/p>\n<blockquote class=\"twitter-tweet\" data-width=\"550\">\n<p lang=\"en\" dir=\"ltr\">Getting started with <a href=\"https:\/\/twitter.com\/hashtag\/Vue?src=hash&amp;ref_src=twsrc%5Etfw\">#Vue<\/a>.js 2 by building a <a href=\"https:\/\/twitter.com\/hashtag\/Giphy?src=hash&amp;ref_src=twsrc%5Etfw\">#Giphy<\/a> search application <a href=\"https:\/\/t.co\/AV1kjK6C1m\">https:\/\/t.co\/AV1kjK6C1m<\/a><\/p>\n<p>&mdash; Nikola Bre\u017enjak (@HitmanHR) <a href=\"https:\/\/twitter.com\/HitmanHR\/status\/978198584670769152?ref_src=twsrc%5Etfw\">March 26, 2018<\/a><\/p><\/blockquote>\n<p><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>TL;DR This tutorial follows the same pattern as this Angular 2 post. You&#8217;ll learn how to use Vue CLI to build a Vue.js 2 application for searching Giphy&#8217;s&hellip;<\/p>\n","protected":false},"author":1,"featured_media":3908,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[58],"tags":[],"class_list":["post-3907","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-vue-js"],"_links":{"self":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/3907","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/comments?post=3907"}],"version-history":[{"count":2,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/3907\/revisions"}],"predecessor-version":[{"id":3910,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/3907\/revisions\/3910"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/media\/3908"}],"wp:attachment":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/media?parent=3907"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/categories?post=3907"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/tags?post=3907"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}