Posts search and gallery view app in Vuejs

Posts search and gallery view app in Vuejs

Hello everyone, welcome back to justlaravel.com. Here I am going to explore some more about vuejs, in previous post, I gave some intro to vue, where we already had database connection and operations on those data and all that cool stuff. Here I will develop another simple app to see more about Vuejs.

Working Demo      Project on Github

This is a simple application something like post’s gallery where different post along with its image and its link is shown and when clicked it goes to the post.

VueJs in Laravel: Search, filter,components - justlaravel.com
VueJs in Laravel: Search, filter, components – justlaravel.com

 

So it has a simple form, where it has 3 fields, title, its link and its image when added these will store in database and the results are shown in the view.

VueJs in Laravel: Search, filter,components - justlaravel.com
VueJs in Laravel: Search, filter,components – justlaravel.com

Search and Add forms:

I used a simple input field for typing some text, with a label which says Search Title:

<label>Search Title:</label>
<input v-model="keyword" type="text" placeholder="Search anything" />

In the above snippet, the most important part is the vue directive, v-model="keyword", I later use this directive later to search through all the posts with the keyword provided in the input field.

Working Demo      Project on Github

Next to that I placed a button, which when clicked opens up a modal as shown in image above.

<button onclick="document.getElementById('inputModal').style.display='block'" class="w3-button w3-green w3-large">ADD</button>

W3CSS Modal in vue.js

Here I used a modal with a form, which has 3 fields as shown in the image before.

<div id="inputModal" class="w3-modal" v-if="showModal">
    <div class="w3-modal-content w3-card-8 w3-animate-zoom" style="max-width:600px">
      <div class="w3-center"><br>
        <span onclick="document.getElementById('inputModal').style.display='none'" class="w3-closebtn w3-hover-red w3-container w3-padding-8 w3-display-topright" title="Close Modal">&times;</span>
      </div>
      <div class="w3-container">
        <div class="w3-section">
          <label><b>Title</b></label>
          <input class="w3-input w3-border w3-margin-bottom" type="text" placeholder="Post Title" v-model="newItem.title" required>
          <label><b>Link</b></label>
          <input class="w3-input w3-border w3-margin-bottom" type="text" placeholder="Post Link" v-model="newItem.link" required>
          <label><b>Image</b></label>
          <input class="w3-input w3-border w3-margin-bottom" type="text" placeholder="Post Image" v-model="newItem.image" required>
          <button class="w3-button w3-block w3-green w3-section w3-padding" @click.prevent="addItem()">Submit</button>
        </div>
      </div>
    </div>
</div>

The above code for modal is similar as any modal you write, but here the 2 noticeable things are vue’s if directive v-if="showModal" and vue’s click method @click.prevent="addItem().

I want to show this modal only when showModal is set to true, I will change this value later in the js part, and when button is clicked I will call a vue method addItem().

Gallery View:

For showing all the posts I use a card view w3-card, and used a vue directive, v-forto loop all the posts.

<div class="w3-row center">
  <div class="w3-card-8 w3-col m3 w3-margin w3-animate-zoom card"  v-for="post in filteredList">
      <a v-bind:href="post.link" target="_blank">
      <img v-bind:src="post.image"/>
      @{{post.title}}</a>
  </div>
</div>

The VUE part

All the Vue(js) part is written in app.js file in /resources/assets/js directory.

First I will create a new vue instance, and all the vue part in handled in an element with id app i.e all the HTML content is wrapped in a div with id app.

<body>
    ....
    <div id="app">
    ...
    ...
    ...
    </div>
    ....
</body>

Create a new vue instance

const app = new Vue({
    el: "#app",
    data: { .... },
    methods: { .... },
    ....
});

First I will initialize some properties in data object.

data: {
        showModal: true,
        keyword: '',
        newItem: {
            'title': '',
            'link': '',
            'image': ''
        },
        postList: []
    },

showModal flag for showing and hiding the modal, modal is shown only when this variable is true.

keyword stores the text we enter in the search box, initially it is empty, later I use this variable to perform search operation.

newItem stores the items a new item(here a post) like its title, post link, and its image.

postList is an array which contains all the posts, initially it is empty.

Working Demo      Project on Github

Next, I will use 2 methods to get all the items from database(getItems) and another method to add an item to database(addItem).

getItems Vue method:

In order to make HTTP calls, we use axios (a promise-based HTTP client) from Vue 2 onwards. So I use the same here.

getItems: function(){
    axios.get('/vueitems').then(response => {
    this.postList = response.data;
  });
}

Here I call route /vueitems with get http verb, the laravel function for it is as follows.

Route::get('/vueitems',function(){
  $posts = Data::all();
  return $posts;
});

the above lines of code simply fetches all the data from the database and returns it. This data is handled in Vue by adding this data to postList array which I defined earlier.

this.postList = response.data;

the above line adds the response to the postList array.

addItems Vue method

Next is addItems Vue method.

addItem() {
    var input = this.newItem;
    axios.post('/vueitems', input)
        .then(response => {
            this.newItem = {
                'title': '',
                'link': '',
                'image': ''
            };
            this.postList.push(input),
            this.showModal= false
        });
    }

Here is a post request to /vueitems is called, with an extra parameter input, which contains the form data.
As I discussed earlier, for each of the field in the form there is an associated Vue model with it. v-model="newItem.title",v-model="newItem.link",v-model="newItem.image", these gets the form data and it can be passed to laravel controller which stores them in the database.

Route::post('/vueitems', function(Request $req){
   $posts = new Data();
   $posts->title  = $req->title;
   $posts->link  = $req->link;
   $posts->image  = $req->image;
   $posts->save();
});

Next, I also used mounted method, which will call when the js first loads. As I want to show all the posts, I will call getItems method in the mounted, so all the post show when the page loads.

mounted : function(){
    this.getItems();
},

Search functionality

As our app has a search feature, where a search box in shown earlier.

<input v-model="keyword" type="text" placeholder="Search anything" />

here Vue directive v-model does the binding and trick for us. I used Vue’s computed property to return the data of the post when its title is entered in the search box.

computed: {
    filteredList() {
      return this.postList.filter(post=>{
          return post.title.toLowerCase().includes(this.keyword.toLowerCase());
        });
    }
}

and in the view, I loop all the items in the filtered list to display all the posts.

<div class="w3-card-8 w3-col m3 w3-margin w3-animate-zoom card"  v-for="post in filteredList">
    <a v-bind:href="post.link" target="_blank">
    <img v-bind:src="post.image"/>
    @{{post.title}}</a>
</div>

 

Working Demo      Project on Github



3 thoughts on “Posts search and gallery view app in Vuejs”

  • 1
    Muhammad Farid Zia on July 16, 2017 Reply

    Awesome tutorial (y)

    • 2
      avinash on July 16, 2017 Reply

      Glad you liked it 🙂

  • 3
    Vadim on July 23, 2017 Reply

    When you try to add second post it’s not working

Leave a Reply