Hands-on Vue.js for Beginners

Hands-on Vue.js for Beginners

Learning a new framework can be a very daunting process for any developer, specially for one that is still learning the base language (in this case JavaScript). This is why I have decided to create this series in which I will attempt to make the learning of Vue.js as easy and digestible as possible 🙂

Im not a fan of making long drawn out introductions, so I will assume that if you’re still reading:

  1. You have some basic HTML/CSS/JS knowledge. You don’t need to be an experienced front-end developer to take on on Vue as a development framework, but at the very least you need to be able to write your own HTML markup, understand the basic of how CSS works and, yes, how to write javascript. In the end, this is what this is all about.
  2. That’s it. No, really.

Hands-on Vue.js for Beginners (Part 1)

Vue as a library

There are several ways in which you can incorporate Vue into your web project. Let’s start with the simplest one (which you will probably not end up using a lot).

Most tutorials/articles will assume that you have understanding of how to set up a development environment in which you will use things like npm, webpack to set up your project - and while this is ideal because of what you get out of the box - we can start with a much simpler beginner-friendly approach. The reliable old <script> tag.

Go ahead and fire up your favorite code editor, and create a new file called index.html. (If you don’t have one yet, VS Code is a popular free choice.

<pre class="ql-syntax" spellcheck="false"><html> <head> <title>Vue 101</title> </head>

<body>
<h1>Hello!</h1>
<div id="app"></div>
</body>
</html>

</pre>

Nothing fancy, we’re just setting the bones for a simple website. Now let’s get the Vue library in there. Paste this script tag before your closing </body>.

<pre class="ql-syntax" spellcheck="false">[...]
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</body>

</pre>

Now that Vue is being loaded into our page, we can start using it.

Let’s go ahead and create a new Vue instance, by newing it up inside a <script> tag. We will give it a selector by passing #app to the el property of the options object, and that way Vue will know where our app should be rendered. (Remember that empty <div> with an ID of app?)

Place this code after our last script tag.

<pre class="ql-syntax" spellcheck="false"><script>
const app = new Vue({
el: '#app', // 1
data: { // 2
myLocalProperty: 'Im a local property value' // 3
}
});
</script>

</pre>

So whats happening here?

We created our new Vue instance, and pass it a configuration object. See the {} as a parameter?

  1. el: As I mentioned before, here we tell Vue where inside our HTML we want our app to be displayed. In this case, the div with the app id.
  2. data object. Every Vue instance has a local storage, like a box of variables and properties that it will hold for us and that we can use when coding our app. Data holds a JavaScript object, so we assign it one with the { } syntax. Inside, we place a property.
  3. myLocalProperty. This property is defined inside the data object for our instance, it’s name is myLocalProperty and the value on the right hand side is the value - in this case, a string.

Displaying properties on our app

Right now if you open up index.html in your browser, not much is happening.

Let’s add some code to display our property inside the HTML. Your file should look like this:

<pre class="ql-syntax" spellcheck="false"><html>
<head>
<title>Vue 101</title>
</head>

&lt;body&gt;
    &lt;h1&gt;Hello!&lt;/h1&gt;
    &lt;div id="app"&gt;
      &lt;p&gt;My local property: {{ myLocalProperty }}&lt;/p&gt;
    &lt;/div&gt;

    &lt;script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&gt;&lt;/script&gt;

    &lt;script&gt;
      const app = new Vue({
        el: '#app',
        data: {
          myLocalProperty: 'Im a local property value'
        }
      });
    &lt;/script&gt;
&lt;/body&gt;

</html>

</pre>

Pay close attention to this line:

<pre class="ql-syntax" spellcheck="false"><p>My local property: {{ myLocalProperty }}</p>

</pre>

What’s happening here is called variable interpolation, which is a fancy term for "i’m going to display the content of my myLocalProperty variable in this placeholder where my {{ }} are now.

Reload the page, and you will now see the string updates to reflect our variable.

Go ahead and try to change the string inside myLocalProperty to some other text and reload the page, you should see the text update accordingly.


Reactivity

Finally for this lesson, let’s talk about reactivity. You may have heard that Vue is a reactive framework. But what exactly does this mean? Open up your console in the chrome developer tools, and with your index.html loaded type:

<pre class="ql-syntax" spellcheck="false">app.myLocalProperty = 'Vue is reactive';

</pre>

You will see the page react to this variable change!


Hands-on Vue.js for Beginners (Part 2)

In part 1 we figured out how to add Vue to our index.html with a regular <script> tag, and we managed to add our very first reactive property to the page. Today, let’s learn how we can change this property with user input.

Our code so far looks like this:

<pre class="ql-syntax" spellcheck="false"><html>
<head>
<title>Vue 101</title>
</head>

&lt;body&gt;
    &lt;h1&gt;Hello!&lt;/h1&gt;
    &lt;div id="app"&gt;
      &lt;p&gt;My local property: {{ myLocalProperty }}&lt;/p&gt;
    &lt;/div&gt;

    &lt;script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&gt;&lt;/script&gt;

    &lt;script&gt;
      const app = new Vue({
        el: '#app',
        data: {
          myLocalProperty: 'Im a local property value'
        }
      });
    &lt;/script&gt;
&lt;/body&gt;

</html>

</pre>

Listening to user events

In order to better showcase the reactivity of Vue, and to learn how to react to user events we are going to add a button to our app that will change the value of our myLocalProperty prop.

Go ahead and first add a new button to our <div id="app">.

<pre class="ql-syntax" spellcheck="false"><div id="app">
<p>My local property: {{ myLocalProperty }}</p>
<hr>
<button>Click me</button>
</div>

</pre>

Now, how do we react to this button getting clicked?

If you come from a jQuery background your instinct may be to try to do something like this: $('button').click();, however there’s a golden rule in Vue. NEVER manipulate the DOM (elements in the page’s HTML) directly.

Without going into super intricate details, Vue keeps a virtual “copy” of your HTML (in this case our div with the “app” ID) and automagically 🧙‍♀️ 🧙‍♂️ figures out where and how to update it when properties change.

If you make changes to the DOM directly with JavaScript, you risk losing these changes and unexpected behavior whenever Vue re-renders the content, because it will not be aware of these changes.

Enough theory though, let’s move on with the clicking. Add this event handler to our button:

<pre class="ql-syntax" spellcheck="false"><button v-on:click="myLocalProperty = 'The button has been clicked'">
Click me
</button>

</pre>

A couple things are happening here.

v-on:click="" In Vue we have these “directives” that we can add to our HTML content.

A directive simply put is an HTML parameter that Vue can understand.

In this particular case, we are telling Vue: Vue (v-), on the user’s click do this: "myLocalProperty = 'The button has been clicked'", which is simply an inline declaration to change the value of our property.

If you go ahead and open your index.html file now in the browser and click the button, you will see the string that we interpolated earlier inside the {{ }} in our code will react to our button modifying the property.


Alternate syntax

In most places you will most likely not find events being set on the HTML with v-on:[eventname] as we have in this example, because in Vue we have a very handy shorthand for this type of thing. @[eventname].

Let’s change our <button> click even to to use this shorthand:

<pre class="ql-syntax" spellcheck="false"><button @click="myLocalProperty = 'The button has been clicked'">Click me</button>

</pre>

Methods

In most cases, when a user event like the click of a button is fired, you will need to do a lot more than changing the value of a variable. So let’s learn about methods (aka, functions).

To continue with our example, let’s make the button call a function that will do something really simple, it’ll change the value of myLocalProperty by appending a random number to a string.

Delete our previous implementation of @click and replace it with this:

<pre class="ql-syntax" spellcheck="false"><button @click="buttonClicked">Click me</button>

</pre>

Notice that we’re not adding a () after "buttonClicked". We can omit these when we are not passing any arguments to our function. For example, @click="changeName('Marina')". (More on this later when we look at conditional rendering 🙂)

Now that we have our button ready to execute buttonClicked on clicks, we need to actually write this function.

Vue has a special place to write functions that our Vue instance can use. This place is inside the { } we passed to our new Vue({}) line before.

We will create a methods: {} property that will hold an object filled with our functions.

<pre class="ql-syntax" spellcheck="false"><script>
const app = new Vue({
el: '#app',
data: {
myLocalProperty: 'Im a local property value'
},
methods: { // 1
buttonClicked() { // 2
const newText = 'The new value is: ' + Math.floor( Math.random() * 100); // 3

    this.myLocalProperty = newText; // 4
  }
}

});
</script>

</pre>

Let’s dissect this:

  1. We declare the methods property inside our Vue instance. As I mentioned, in here you will put all your instance methods/functions.
  2. Inside the methods object { } we declare buttonClicked(), which is the function we are trying to call on our @click listener. We’re not going to use any parameters at this point so empty ().
  3. We join the value of the rounded down value Math.floor of the result of multiplying the random value of 0-1 by 100 to a string and store it in a constant.
  4. We assign the value of our new string to myLocalProperty. Now be very careful about this tiny detail 🙃 (lame pun intended). When we assign new values to the properties inside the instance’s data property (the one inside data: {}) you MUST access it through this.[prop-name].

In the context of a method the keyword this refers to the Vue instance. Vue will perform some magic behind the scenes so that you can read/write to your properties inside data by doing this.property = value.

Now that we have everything set up, reload your index.html file and click on your button. The value of our interpolated {{ }} string on the containing <p> will be updated every time you click the button, for every single time the buttonClicked function is executed. Once again, the magic of Vue’s reactivity is coming into play.


Wrapping up

If at this point you’re thinking, well, this is really easy then you’re on the right track. One of the things I love the most about this framework is its clear syntax and simplicity. It just works. But this should not be confused with thinking that Vue is not powerful.

We’re merely scratching the surface of what we can do with Vue so far, but you’ll see as we progress through these articles that these tiny building blocks put together will soon make the core of your amazing next app.


Hands-on Vue.js for Beginners (Part 3)

A simple if-else

One of the most important tools under the belt of any programmer regardless of framework is conditional rendering. The ability to show or hide parts of your app depending on a condition or value is a great place to start learning about this, and also about Vue directives.

We will continue building upon our previous example. In case you lost it or are just catching up, here’s what we have so far:

<pre class="ql-syntax" spellcheck="false"><html>
<head>
<title>Vue 101</title>
</head>

&lt;body&gt;
    &lt;h1&gt;Hello!&lt;/h1&gt;
    &lt;div id="app"&gt;
      &lt;p&gt;My local property: {{ myLocalProperty }}&lt;/p&gt;
      &lt;hr&gt;
      &lt;button @click="buttonClicked"&gt;Click me&lt;/button&gt;
    &lt;/div&gt;

    &lt;script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&gt;&lt;/script&gt;

    &lt;script&gt;
      const app = new Vue({
        el: '#app',
        data: {
          myLocalProperty: 'Im a local property value'
        },
        methods: {
          buttonClicked() {
            const newText = 'The new value is: ' + Math.floor( Math.random() * 100 );

            this.myLocalProperty = newText;
          }
        }
      });
    &lt;/script&gt;
&lt;/body&gt;

</html>

</pre>

So far we’ve managed to output our local properties into our app, and also listen to the clicks of a user on a simple button.

Let’s take it a step further and learn about our conditional rendering.

Let’s change our button clicks so that they generate a random number just as we have been doing, but instead of outputting a concatenated string, we will toggle the display of a couple of <p> elements with the results.

This will require some refactoring, so first let’s change our buttonClicked method to only calculate this new number, and we will store it on a new property called randomNumber.

<pre class="ql-syntax" spellcheck="false"><script>
const app = new Vue({
el: '#app',
data: {
myLocalProperty: 'Im a local property value',
randomNumber: 0 // 1
},
methods: {
buttonClicked() {
this.randomNumber = Math.floor(Math.random() * 100); // 2
}
}
});
</script>

</pre>

Let’s take a quick look.

  1. We’ve added a new local property randomNumber, and the default value will be 0.
  2. We deleted the old code, and instead of using the random value on the previous string we will just store it provisionally in our randomNumber prop.

We want to show/hide content depending on the result of our randomNumber calculation, so let’s have two new <p> elements. One will show only when randomNumber is greater or equal to 50. The other will show if it is less than 50.

<pre class="ql-syntax" spellcheck="false"><div id="app">
<p>My local property: {{ myLocalProperty }}</p>
<hr>
<button @click="buttonClicked">Click me</button>
<hr>
<!-- 1 -->
<p v-if="randomNumber >= 50">randomNumber is >= 50!</p>

<!-- 2 -->
<p v-else>Sorry, randomNumber is only <b>{{ randomNumber }}</b></p>
</div>

</pre>

We’ve added a <hr> for clary and separation, and then our two <p> elements.

Let’s look at each in detail.

First, v-if="randomNumber >= 50". So, v-if is a Vue directive. Don’t get too caught on the definition of the term, it only means that it is a “special” value that we can place inside HTML elements that Vue will know how read and interpret. In fact, you’ve already used directives before. Remember v-on:click and @click? Those are directives too!

Theory aside, v-if tells Vue to only show this element if the condition we declare inside of it is true. In this case, “Vue: only show this <p> element IF and only IF randomNumber is greater than or equal that 50”.

Second, whenever you have a v-if directive, you can have an else case. But heads up, v-else ONLY works on an element that directly follows the one that holds the v-if (or a third option v-else-if). As you’d expect from any if - else statement, the element with v-else will get rendered on any other case that is not true for the first. Either/or.

Go ahead and reload your index.html and click the button a few times. You’ll see that the <p> tags get rendered reactively depending on the value of randomNumber.


v-if and v-show

If you’re curious to open your dev tools while you’re click around, you will notice a VERY important thing. v-if is not a display: block/hidden css switch toggle, it actually renders or destroys elements whenever the value of our conditional changes. If you want to have a visibility toggle directive, go ahead and try switching that first v-if for v-show and see what happens!

You may notice is that the block that has the v-else declarative is not showing anymore. This is because v-show is a lone-ranger and will only work by itself. So what is the benefit of using v-show?

There is a performance cost that you may want to consider when using v-if because Vue has to go and re-render the DOM (don’t worry it’s very smart about which parts it needs to add/remove) but this is a more extensive task than applying/removing css display properties.

Bottom line: If you’re going to toggle a small/medium part of the app a few times only, like a menu bar for example, v-if will usually do the trick. But if you’re going to be switching around tabbed screens for example, or huge chunks of your page then v-show may be cheaper in terms of performance because your markup is not getting re-written every time.

(P.S. before we continue, set back the directive to v-if or else you’ll get console errors because of the v-else below it is unpaired.)


Development tools

If you’re wishing you knew a way to figure out which value is getting randomized into randomNumber for our >= 50 condition without having to render it inside the <p> tag with our trusty {{ }} then Vue has a fantastic tool for the job.

Go ahead and install the Chrome Vue Devtools or Firefox Vue Devtools.

Since some of us may be opening the file directly on our browser using the file:// protocol, if you don’t see the extension working for you in chrome. Please first follow these instructions:

<pre class="ql-syntax" spellcheck="false">"To make it work for pages opened via file:// protocol, you need to check "Allow access to file URLs" for this extension in Chrome's extension management panel."

Right click the Vue icon on the extensions toolbar, click on manage extensions and then toggle the allow access switch.

</pre>

Once you’ve added them to your favorite flavor of browser, go ahead and open them (Open your dev tools by “inspecting” or through the browser menus, then navigate to the “Vue” tab on the development pane) while you’re on your index.js page and you’ll notice quite a few goodies to play around with.

The screen you should see looks like this:

You’ll notice a toolbar with some icons on the top right, those we’re going to look at when we look at Vuex and you can safely ignore them for now.

The important thing in this screen however is the components tree. The dev tools will allow you to inspect every component that you create for a page, its properties (data) and later on when we look at state management how they interact with it. (Don’t worry if this makes no sense right now).

Click on the <Root> component and you will see this:

Notice our two local properties, myLocalProperty and randomNumber.

Click on your <button> a few times and see how the developer tools responds by showing you the changes in the randomNumber value.

Now this may not seem super impressive right now, but this tool will be your #1 source of information when we start building a real world application, or even in your actual work projects, so definitely spend some time playing with it!

A neat thing for example with local storage, is that you can modify the values manually to test different states of your application. Hover of the property you want to modify and you’ll get an edit button and (in case of numeric properties) a + and - button to increase or decrease the value.


Conclusion

With the fundamentals that we’ve already covered: setup, events, properties and conditional rendering you now have the building blocks to start creating some really fun and reactive applications. However this is just barely scratching the surface of the power of Vue and it only gets more fun and interesting from here.


Hands-on Vue.js for Beginners (Part 4)

Last time we took at conditional rendering with v-if and v-show. This time we will learn how to loop through arrays and objects and create an element for each one of the items in them. We will also apply some of the concepts we have learned before.


v-for

v-for is one of the fundamental directives of Vue.js, and once you understand how it works the extension of what you can build inside your apps will grow exponentially.

v-for is, simply put, a for loop. If you don’t yet know what this means, a for loop is a piece of code that gets executed one time per each element in a group - which in turn is usually an Array or an Object.

We’re going to start with an empty slate today, so that everything we do has a clear purpose. Here’s a copy of our base index.html file for you to copy and paste into your editor.

<pre class="ql-syntax" spellcheck="false"><html>

<head>
<title>Vue 101</title>
</head>

<body>
<div id="app">

</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
const app = new Vue({
el: '#app',
data: {

  },
  methods: {

  }
});

</script>
</body>

</html>

</pre>

Let’s start by creating a simple list, an array, that we can loop to output its content. We will create a property inside our data object, called games. Feel free to change the titles to your own personal favorites 🙃🎮

<pre class="ql-syntax" spellcheck="false">data: {
games: [
'Super Mario 64',
'The Legend of Zelda Ocarina of Time',
'Secret of Mana',
'Super Metroid'
]
},

</pre>

Awesome! Now that we have our array set up, let’s create a sad and simple <ul> element where will display it. For the sake of example, let’s keep it simple for now.

<pre class="ql-syntax" spellcheck="false"><div id="app">
<ul>
<li>Game title here</li>
</ul>
</div>

</pre>

Ok, looking good! Now we have to tell Vue that we want to output as many <li> elements inside the <ul> as needed to loop through our whole array.

In other languages, and even in vanilla JavaScript, you may be used to doing something that looks similar to this:

<pre class="ql-syntax" spellcheck="false"><?php foreach ($game in $games): ?>
<li><?php echo $game; ?></li>
<?php endforeach; ?>

</pre>

Where the loop encloses the element(s) it’s going to output or print out.

In Vue we declare our v-for directive on TOP of the element we want to loop. Make these changes to your <li> and we’ll dissect them after.

<pre class="ql-syntax" spellcheck="false"><ul>
<li v-for="game in games">{{ game }}</li>
</ul>

</pre>

Let’s take a look.

  1. v-for was added directly to the <li>, not the <ul> as we saw earlier. This reads: "For each game in my games array, please make a new <li> inside these <ul> tags.
  2. Note that games is the property that we added earlier with the array inside our data, so we have to use this variable name.
  3. The variable game (singular) is defined by us, we could use item, game, title or whatever we feel like. But be sure to understand that this game in games is what you will be using as a variable inside your loop.
  4. Finally, inside our <li> tag we’re outputting the contents of our game variable, so while the loop is running for each of our games, this will output the string into the <li>.

Run your app inside the browser, and you should see your list of items being outputted to the screen.


Taking it up a notch

So far, so good? v-for is actually a very simple concept, and this example is super boring. So how about we make things a bit more complicated, by making our array include some objects, and also applying some v-ifs inside our list?

First things first, let’s update our games property with some more interesting data.

<pre class="ql-syntax" spellcheck="false">data: {
games: [
{ name: 'Super Mario 64', console: 'Nintendo 64', rating: 4 },
{ name: 'The Legend of Zelda Ocarina of Time', console: 'Nintendo 64', rating: 5 },
{ name: 'Secret of Mana', console: 'Super Nintendo', rating: 4 },
{ name: 'Fallout 76', console: 'Multiple', rating: 1 },
{ name: 'Super Metroid', console: 'Super Nintendo', rating: 6 }
]
},

</pre>

As always feel free to use your own favorite titles. PS. Super Metroid’s rating of 6 is not a typo, it’s just THAT good - and i’m biased. 😬 Also, Bethesda, you should be ashamed. cough Anyways.

If you run your app this point it will not particularly break, but it will just output the objects in a string format, which is not pretty. In fact, we’re going to scratch our <ul> approach completely, and use a <div> to output our information. (Don’t worry, it’ll still be ugly).

Update your whole <div id="app">:

<pre class="ql-syntax" spellcheck="false"><div id="app">
<div v-for="game in games">
<h1>{{ game.name }} - <small>{{ game.console }}</small></h1>

&lt;span v-for="star in game.rating"&gt;❤️&lt;/span&gt;

&lt;div v-if="game.rating &gt; 5"&gt;Wow, this game must be &lt;b&gt;REALLY&lt;/b&gt; good&lt;/div&gt;

</div>
</div>

</pre>

WOAH. Ok, maybe not, but don’t worry, you already know everything you need to understand what’s happening here.

  1. div v-for="game in games" Same old, we’re going to loop our games array prop and store each game in the game variable.
  2. h1. Ok, so game is an object, which in turn holds its own properties, name, console and rating. Inside the <h1> we’re going to output the game’s *name: game.name. And the console: game.console. As you can see now, v-for is not limited to outputting just a single element like we saw before with the li, but you can actually output as much HTML as you need.
  3. The nested v-for. So inside the span element we actually have a nested v-for loop (which is TOTALLY ok to do), except it’s a little different, we’re not looping an array or an object. I didn’t LIE to you, maybe just withheld some information - like for example, you can actually loop a numeric value (in this case game.rating and the loop will count up from 1 till it reaches the value of the rating. Simple?
  4. Finally, v-if. We are going to output a <div> tag inside our loop IF the condition is met, so if and only if the current game’s rating is greater than 5. Take a guess which?

Go ahead and run this again in your browser and behold the awesomeness of not bothering with CSS.


What if I don’t need a wrapping DIV?

If at any point you find yourself making a bunch of <div> elements simply to wrap up your v-for loops, theres a special HTML tag you can use to help your case. <template></template>

If you, for example, remove the wrapping <div> and change it for <template> take a look at your developer console and you’ll see that the <h1> and <span> elements are not wrapped by anything.

<template> is special, because Vue will treat it as a wrapper element but it won’t be rendered into the HTML when we execute it, so you can safely use it to wrap a bunch of other elements logically for the loop without affecting your markup.


The :key attribute

One final thing that I purposely left for the end. The :key attribute.

When you are looping through elements with v-for Vue.js has NO clue how to track your elements for reactivity, because it can’t “tell apart” one object from the other. What this means for you is that since Vue can’t do this, it will re-render the WHOLE section of the page that is being created by this loop. In our case it’s a very small section and the performance hit would probably be minimal, but it’s something that you should keep in mind - and just do it for best practice.

Now, how do we use it?

:key expects some string it’ll use to “name” or “track” the element, so we need to give it a unique identifier. In the case of our games it’s simple, we can do:

<pre class="ql-syntax" spellcheck="false"><div v-for="game in games" :key="game.name">

</pre>

I’m pretty certain that we’re not going to have the same game twice in this list, so this is pretty safe. An id if you have data coming from a database is also ideal to use here.

If you are curious about the intricacies of :key you can always take a look at the documentation. Key’s docs

In fact, now that you have gotten this far I can’t stress enough the importance of getting acquainted with the documentation. Vue.js 's docs are impressively good, and very very clear with code examples, the documentation team does a fantastic job to keep them updated and clear - big shout out to all of them.


Final code

Here’s the final code, just in case.

<pre class="ql-syntax" spellcheck="false"><html>

<head>
<title>Vue 101</title>
</head>

<body>
<div id="app">
<div v-for="game in games" :key="game.name">
<h1>{{ game.name }} - <small>{{ game.console }}</small></h1>

&lt;span v-for="star in game.rating"&gt;❤️&lt;/span&gt;

&lt;div v-if="game.rating &gt; 5"&gt;Wow, this game must be &lt;b&gt;REALLY&lt;/b&gt; good&lt;/div&gt;

</div>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
const app = new Vue({
el: '#app',
data: {
games: [
{ name: 'Super Mario 64', console: 'Nintendo 64', rating: 4 },
{ name: 'The Legend of Zelda Ocarina of Time', console: 'Nintendo 64', rating: 5 },
{ name: 'Secret of Mana', console: 'Super Nintendo', rating: 4 },
{ name: 'Fallout 76', console: 'Multiple', rating: 1 },
{ name: 'Super Metroid', console: 'Super Nintendo', rating: 6 }
]
}
});
</script>
</body>

</html>

</pre>

Challenge

This time you get a challenge, if you wish to accept it. Add a @click listener to the <span> which outputs the game’s rating, and increase the ranking by 1 with each click for that UNIQUE game. You already know everything you need to achieve this 😉.


Hands-on Vue.js for Beginners (Part 5)

This time around we’re going to look (finally) at components! So get some ☕️ and let’s get started.

Here’s the clean slate for today’s article 😁

<pre class="ql-syntax" spellcheck="false"><html>

<head>
<title>Vue 101</title>
</head>

<body>
<div id="app">

</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
const app = new Vue({
el: '#app',
data: {

  }
});

</script>
</body>

</html>

</pre>

Component Basics

We’re going to nose dive right into component creation, because this is where really fun stuff starts. But rest assured that this is only barely brushing the power of components. Also, we still have yet to learn computed properties and watchers, which will also be a huge aid. But we’ll cover that next time on top of what we learn today.

Components are a core part of the Vue.js framework, they are your Lego blocks for building reactive, rich applications - and luckily for us they are super simple to learn and use!

Think of a component as any element in your webpage/app that you want to use one or several times. It can be as smol as a button, or input, or as a big as your whole menu bar or even the whole page’s view.

The advantage of creating a component, is that you write the logic for how its displayed (HTML/CSS), and how it interacts with the user (JS) once - and then you just use it all over your app.

As usual, we’re going to start with the simplest possible example, a button.

Let’s define first the blueprint or template for this component, we’ll call it awesome-button and it shall be so!

Let’s define a new awesome-button component. Copy this code above your new Vue declaration.

<pre class="ql-syntax" spellcheck="false">Vue.component('awesome-button', {
template: &lt;button @click="clickHandler"&gt;Click me for some awesomeness&lt;/button&gt;,
methods: {
clickHandler() {
alert('YAAAS 😎');
}
}
});

</pre>

The Vue object that is made available to us through the Vue.js script tag that we added on day 1 has this component method that we are calling here. It allows us to create a new component, as expected. The first parameter we are setting is a String, which will be the name of our component.

The second parameter is a JavaScript object, which - surprise - is actually the same type of configuration object that we have been using for our main Vue instance! What does this mean for you? That you already know how to assign properties and methods for this new component.

In the example above, you will notice just one difference - the template property. In here we’re declaring a String (note that we’re also using the back-tick character to wrap it so that we can declare multiple lines later on if we need without having to concatenate multiple strings), this String will hold our actual HTML code for this component. In the case of this particular example, just a simple <button> tag will suffice.

If you reload your page right now, nothing will happen. Remember earlier I told you this was only the blueprint/template? It’s time to actually render it on our page.

Head over to the <div id="app"> where we have been placing all our markup, and create a new <awesome-button> element.

Your HTML should now look something like this:

<pre class="ql-syntax" spellcheck="false"><div id="app">
<awesome-button></awesome-button>
</div>

</pre>

Load the page, and now you will actually see the button being rendered on the page. Place a couple, or ten more (reader’s choice) awesome-button tag on the page. Now you start to see the power of components, although at this point I think we can take it up a nudge.

Bonus: If you’re the curious type, take a look at your page source and compare it to the inspect feature with your browser’s developer tools. When the page load, Vue.js is using the <awesome-button> tag as a placeholder to where it should put the parsed content of our template.


Level 2 - Something a little more useful

Let’s revisit our example from last week, and play some more with our games data.

First, let’s re-add this array of games into our data() in the main Vue instance.

<pre class="ql-syntax" spellcheck="false">const app = new Vue({
el: '#app',
data: {
games: [
{ name: 'Super Mario 64', console: 'Nintendo 64', rating: 4 },
{ name: 'The Legend of Zelda Ocarina of Time', console: 'Nintendo 64', rating: 5 },
{ name: 'Secret of Mana', console: 'Super Nintendo', rating: 4 },
{ name: 'Fallout 76', console: 'Multiple', rating: 1 },
{ name: 'Super Metroid', console: 'Super Nintendo', rating: 6 }
]
}
});

</pre>

Just as before, feel free to update these with your favorite titles.

This time, however, we are going to create a game-card component, that will make a bit more sense to display our data in.

Ready for this?

<pre class="ql-syntax" spellcheck="false">Vue.component('game-card', {
props: ['gameData'],
template: `
<div style="border-radius: .25rem; border: 1px solid #ECECEC; width: 400px; margin: 1rem; padding: 1rem;">
<h2>{{ gameData.name }} - <small>{{ gameData.console }}</small></h2>

  &lt;span v-for="heart in gameData.rating"&gt;❤️&lt;/span&gt;

  &lt;button @click="increaseRating"&gt;Increase Rating&lt;/button&gt;
&lt;/div&gt;

`,
methods: {
increaseRating() {
// this.game.rating++ ?
}
}
});

</pre>

Don’t get overwhelmed, you already know all/most-all of this 😃!

We’re creating a new Vue.component and naming it game-card. Let’s skip props for a second, and look at the template.

Nothing new here, except you may have noticed we’re accessing the properties of a gameData property that is not defined inside data, but inside the props property.

Afterwards, we declare our methods object, with the increaseRating method inside it. I’ve purposely commented out this.game.rating++ which would be how you may want to address this particular function, but it won’t work! Now it’s time to talk about props.


Component Props

One of the reserved properties we can have on our custom components is called props. In its simplest form, it will take an array of Strings that will define variables. In our previous example, we are telling the component blueprint/template that we want it to be aware of a property called game.

Props will allow us to pass information into our components from outside! Let’s view this in action, it’ll be easier to grasp.

First, let’s add a bunch of <game-card> items to our app. We will be using a v-for loop just like we did before, but we’re going to loop on top of our custom components this time!

<pre class="ql-syntax" spellcheck="false"><div id="app">
<awesome-button></awesome-button>
<hr>
<game-card v-for="game in games" :game-data="game" :key="game.name"></game-card>
</div>

</pre>

That is quite a bit of game being tossed around, so let’s look at it in detail.

First step, we are creating our <game-card> component, like we discussed earlier.

After, we add the v-for="game in games" loop like we saw last week. This creates a game variable that will hold the current game in the loop, and we can use it right away!

Finally, we assign to the template’s prop, gameData, a value, in this case our game variable from the loop. Notice that instead of camel case, we’re using a hyphen game-data because HTML is case insensitive. If you are having a hard time grasping this, try thinking it in object terms. We are doing something similar to game-card.props.gameData = game

Don’t forget about the :key!

There is a huge gotcha to mention here, we are passing game to our game-data prop, but there is a : behind it. Did you notice?

When we assign a property to a component instance, theres two ways to go about it. Following our example, we could either do it with the : before it (this is a shorthand for v-bind:!). This will make sure the data that we are passing after the ="<here>" is used by JavaScript as a variable, or an actual piece of code.

If you were to type instead gameData="game", then Vue will take this as assigning the gameData prop the String "game". So something like: game-card.props.gameData = "game"!

Go ahead and take a break from theory and actually go and run this in your browser. You will see as expected, that our whole <game-card> component’s template is being rendered for each one of our game's.

The greatest part about this is that if we were to make a change to our HTML, it will be updated everywhere in our app.

Also, and most importantly, components allow you to contain the logic for that particular component. Let’s revisit that game-card's increaseRating() method.


Component Data vs. Props

Props for components actually can be a very lengthy subject, but there is a very important rule of thumb that you must always keep in mind. A property should NEVER be modified from inside a component.

In fact, if you try to do this, Vue will throw all sorts of warnings and yell at you in the console - because this WILL lead to unexpected behavior. Here’s the documentation, in case you want to read about it: Mutating props in Vue2 is an anti-pattern.

How then, will we modify the value of rating inside of our component’s storage? The key is in the question itself! We need to make a copy of this prop into our data so that we can actually modify it.

Let’s first add our data to our game-card component, and assign it a new non-conflicting name (props and data props will conflict if named the same), and then pre-fill it with the prop’s value.

<pre class="ql-syntax" spellcheck="false">data() {
return {
game: {...this.gameData}
}
},

</pre>

Couple of things to note here, but before that, if you don’t know yet what {...gameData} is doing, it’s a spread operator. I won’t go into full detail here and will try to post a brief article about it soon, but basically were making a copy of the gameData prop, because we don’t ever want to modify that from the child.

The data property’s return:

When we learned about the data property, I told you that it needed to hold an object with all the properties we needed, and this is how we’ve been doing it for our main Vue instance. However for components we actually need to make it a function, by adding (), and second return the actual object.

But WHY?! 😫

Simply put, there can be one or many instances of your component, right?

Each instance will need a unique data object! You don’t want to share a single data object between all of those, or they would all share the same title for example - and the point of this whole app would be lost.

So the whole reason behind making it a function and returning an object, is that Vue can ☎️ call this function every time it creates one of our game-cards. That way each one will get a unique object of data to play with!

Accessing our props:

When we create the game's data property, we are assigning it this.gameData, so a couple of things to learn here. props can also be accessed within your component scripts via this just as your local state props from data. So here, we are setting game to be equal to the gameData property.

This means now we have to update our HTML, so inside the component switch the gameData reference for game like so:

<pre class="ql-syntax" spellcheck="false"><div style="border-radius: .25rem; border: 1px solid #ECECEC;">
<h2>{{ game.name }} - <small>{{ game.console }}</small></h2>

<span v-for="heart in game.rating">❤️</span>

<button @click="increaseRating">Increase Rating</button>
</div>

</pre>

Run this once again in your browser, and you should get the same results.

Finally, we are at the point where we can make our increaseRating method work! Head to the method and replace the comment with the following:

<pre class="ql-syntax" spellcheck="false">methods: {
increaseRating() {
this.game.rating++
}
}

</pre>

With every click, we’re going to increment the component’s internal data property which holds the game's rating, -not- the prop.


There is a lot of theory to be learned about components, i’ve just began to scratch the surface, but hopefully you are starting to have a clearer picture of why frameworks like Vue are so popular, and so much fun to use.

From this point forward we’re going to start looking at what I consider intermediate topics, like computed properties, watchers, events, etc. So hopefully you are excited to get to know the meaty part of Vue soon enough.

In case you need it, here’s the complete code for today, and thanks for reading! 🤗😋

<pre class="ql-syntax" spellcheck="false"><html>

<head>
<title>Vue 101</title>
</head>

<body>
<div id="app">
<awesome-button></awesome-button>
<game-card v-for="game in games" :game-data="game" :key="game.name"></game-card>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
Vue.component('awesome-button', {
template: &lt;button @click="clickHandler"&gt;Click me for some awesomeness&lt;/button&gt;,
methods: {
clickHandler() {
alert('YAS. 😎');
}
}
});

Vue.component('game-card', {
    props: ['gameData'],
    data() {
      return {
        game: {...this.gameData}
      }
    },
    template: `&lt;div style="border-radius: .25rem; border: 1px solid #ECECEC; width: 400px; margin: 1rem; padding: 1rem;"&gt;
      &lt;h2&gt;{{ game.name }} - &lt;small&gt;{{ game.console }}&lt;/small&gt;&lt;/h2&gt;

      &lt;span v-for="heart in game.rating"&gt;❤️&lt;/span&gt;

      &lt;button @click="increaseRating"&gt;Increase Rating&lt;/button&gt;
    &lt;/div&gt;`,
    methods: {
      increaseRating() {
        this.game.rating++
      }
    }
  });

const app = new Vue({
  el: '#app',
  data: {
    games: [
      { name: 'Super Mario 64', console: 'Nintendo 64', rating: 4 },
      { name: 'The Legend of Zelda Ocarina of Time', console: 'Nintendo 64', rating: 5 },
      { name: 'Secret of Mana', console: 'Super Nintendo', rating: 4 },
      { name: 'Fallout 76', console: 'Multiple', rating: 1 },
      { name: 'Super Metroid', console: 'Super Nintendo', rating: 6 }
    ]
  }
});

</script>
</body>

</html>

</pre>

Hands-on Vue.js for Beginners (Part 6)

Let’s talk about computed properties.

So far you’ve learned how Vue handles its own local state, the one we put inside data, and how a component can handle its prop properties - the ones that get handed down by the parent.

However, there is a type of properties in Vue which are called Computed Properties. Let’s take a look at these today.

We’re going to use a clean slate today, so that we can build a clear example. Here’s the code.

<pre class="ql-syntax" spellcheck="false"><html>

<head>
<title>Vue 101</title>
</head>

<body>
<div id="app">
<age-calculator></age-calculator>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
Vue.component('age-calculator', {
template: &lt;p&gt; NAME has been kicking butt for X days! &lt;/p&gt;
});

const app = new Vue({
  el: '#app'
});

</script>
</body>

</html>

</pre>

I’ve gone ahead and added the scaffolding for an age-calculator component, right now it only outputs a <p> tag with an X where we’re going to perform some sort of calculation. I’ve also added the corresponding tags <age-calculator> to the div#app.

If you need a refresher on basic components, take a look at Part V of this series, or better yet, nosedive the official docs!


When a simple prop isn’t enough

Before we write any code, let’s talk about what we’re trying to accomplish.

I want to have a component where I pass it someone’s age, and it will tell us how many days they’ve been around to enjoy avocados. If you don’t like avocados then this is where our relationship ends, have a nice life.

Let’s tackle the easy tasks that we already know how to accomplish, first we need an array of people with ages so that we can loop through it and output a bunch of components. Let’s add the corresponding data.

<pre class="ql-syntax" spellcheck="false">const app = new Vue({
el: '#app',
data: {
people: [
{ name: 'Mario', age: 38 },
{ name: 'Luigi', age: 38 },
{ name: 'Samus', age: 31 },
{ name: 'Link', age: 20 },
{ name: 'Marina', age: 32 },
//Add yourself here :)
]
}
});

</pre>

Now, let’s set up our v-loop to output an age-calculator per each one.

<pre class="ql-syntax" spellcheck="false"><div id="app">
<age-calculator v-for="person in people" :key="person.name"></age-calculator>
</div>

</pre>

Awesome, now let’s allow the age-calculator component to receive a person, remember we do this with a prop. So first, let’s add this new prop to the component.

<pre class="ql-syntax" spellcheck="false">Vue.component('age-calculator', {
props: {
person: {
type: Object,
required: true
}
},
template: &lt;p&gt; {{ person.name }} has been kicking butt for X days! &lt;/p&gt;
});

</pre>

Bonus! Before you learned that to declare the props that a component can receive, you set up an array of strings props: ['person'] and this is fine in most cases. But what happens if we want a bit more control?

You can also, like in this case, set props to be equal to an object. Inside this object, we can create a property per each property we want to declare.

Inside the property declaration, in this case person, we can set some configuration values.

type to declare which (duh) type of data we’re passing, so Object, Array, String, Number for example.

required is a boolean that allows us to mark this property as required for the component to work.

You can also set a default value, but we’re not going to use that here.

Next, look at the template. We are now outputting the person’s name {{ person.name }} onto the <p> tag.

One more thing before we can actually run this in our browser though. Can you tell what we’re missing?

We still need to pass the actual person to the age-calculator component!

Go into the render loop and pass in our variable.

<pre class="ql-syntax" spellcheck="false"><age-calculator
v-for="person in people"
:person="person"
:key="person.name"></age-calculator>

</pre>

Go ahead and run this in your browser to check that everything is working. Baby-steps!

Note Before we move on, if you’re curious what setting a prop to required will do for you, try removing this last bit we did when we pass the person to the component and look at your dev tools in the console section.

Handy, ain’t it? 👌


The actual Computed Property

Alright, enough setting up and review.

We still have one more feature to tackle inside our component, we want to calculate the number of days each person has been alive.

Granted, it’s not a very hard calculation, we just have to multiply 365 times the number of years (we’re not going to go hardcore with JS Dates here). And in fact, we could go ugly and direct and put this straight into our template.

<pre class="ql-syntax" spellcheck="false">template: &lt;p&gt; {{ person.name }} has been kicking butt for {{ person.age * 365 }} days! &lt;/p&gt;

</pre>

This works, sort of. But what happens when you require more logic? A harder computation, some ifs/ands/ors/whens/beers? Then you’re in a real problem because you can’t really put that much logic inside the template, or it’s going to get unmanageable real quick.

Here’s where computed properties shine. Computed properties are in the end functions, that will execute a bit of code, and return a value. This value is now treated like a property, which means we can straight up use it in our template.

Let’s take a look at how to set it up. First, let’s add the computed wrapper to our component.

<pre class="ql-syntax" spellcheck="false">Vue.component('age-calculator', {
props: {
person: {
type: Object,
required: true
}
},
template: &lt;p&gt; {{ person.name }} has been kicking butt for {{ person.age * 365 }} days! &lt;/p&gt; ,
computed: {
// Computed props go here
}
});

</pre>

So far so good, in fact this structure is the exact same one we have been using for methods, remember? (If you’re thinking a method could also solve our problem, you’re on the right track - we’ll talk about this in a minute.)

Let’s create a new computed property called daysAlive, it needs to be a function, and it needs to return something.

<pre class="ql-syntax" spellcheck="false">computed: {
daysAlive() { //Remember, computed props are functions in the end
return this.person.age * 365
}
}

</pre>

Take note that just like in methods we need to access the person prop though this, only inside the template we can use it directly! Other than that, nothing too fancy going on.

Now let’s use this new daysAlive prop in our template.

<pre class="ql-syntax" spellcheck="false">template: &lt;p&gt; {{ person.name }} has been kicking butt for {{ daysAlive }} days! &lt;/p&gt;,

</pre>

Note that we’re outputting the value of the daysAliveproperty–, (aha moment here). Vue treats computed props as, well, props - so we can use this here as you would a props prop, or a data prop.

In fact, Vue makes it so that if you would need to use this prop inside a method for example, you would have to access it through this.daysAlive. Neat right? It ACTUALLY becomes a prop. 🤯

YAY, run it in the browser and bask in your awesomeness.


Methods vs Computed Properties

You may have noticed a lot of similarities between methods and computed props, I mean, they’re basically identical at code level. However there is a CORE difference that you need to understand in order to harness them fully.

Computed properties get cached.

What this means is, in the simplest possible way to explain it, that behind the scenes Vue will “read” your code and look for reactive dependencies - so data props and props props. It will watch these properties, and whenever they change, Vue will recalculate the value of your computed property. If they don’t change, it’ll just use a cached/stored value.

Methods, on the other hand, are ran EVERY time - there is no caching, no code reading, no magic. They’re just plain old functions.

Why does this matter? When are these functions called?

Every time your component/app re-renders (so every time a component’s data change, or every time it’s parent’s data changes), Vue will figure out if that data is tied to a computed property, if it’s not - it won’t call this function again. For regular methods however, they will be re-run every time!

For this example, where we’re doing a very simple calculation for these few objects it doesn’t really matter, frankly. But when you start doing some serious code weightlifting on top of a thousand components, then you’re going to want to leverage this caching or your app is going to take a hit on each render cycle.

If you want to read more, here’s a link to the official docs regarding computed properties.

Here’s the complete code for today.

<pre class="ql-syntax" spellcheck="false"><html>

<head>
<title>Vue 101</title>
</head>

<body>
<div id="app">
<age-calculator
v-for="person in people"
:person="person"
:key="person.name"></age-calculator>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
Vue.component('age-calculator', {
props: {
person: {
type: Object,
required: true
}
},
template: &lt;p&gt; {{ person.name }} has been kicking butt for {{ daysAlive }} days! &lt;/p&gt; ,
computed: {
daysAlive() {
return this.person.age * 365
}
}
});

const app = new Vue({
  el: '#app',
  data: {
    people: [
      { name: 'Mario', age: 38 },
      { name: 'Luigi', age: 38 },
      { name: 'Samus', age: 31 },
      { name: 'Link', age: 20 }
    ]
  }
});

</script>
</body>

</html>

</pre>

Hands-on Vue.js for Beginners (Part 7)

We are nearing the end of journey, and you are almost ready to graduate from Vue Padawan level. But first watchers, you must learn.

We’re going to tackle two very important concepts today, watchers, as mentioned, and form input bindings.

Let’s get started and we’ll build a super simple form to showcase both these fantastic features.

<pre class="ql-syntax" spellcheck="false"><html>

<head>
<title>Vue 101</title>
</head>

<body>
<div id="app">
<label>What's your favorite game ever?</label>
<input type="text" >

&lt;hr&gt;

&lt;p&gt;{{ response }}&lt;/p&gt;

</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
const app = new Vue({
el: '#app',
data() {
return {
favoriteGame: null,
response: ''
}
}
});
</script>
</body>

</html>

</pre>

Let’s take a look at what we’re doing here.

Inside our <div id="app"> we’ve created a label and the most basic form of an <input> tag. After, we’re outputting the result of a response property.

Inside our Vue instance, we’re declaring a local state that includes two properties, favoriteGame and response. Also note, that we’re using the data() as a function with the return syntax this time, if we don’t v-model won’t work.

The idea here, is that we want to first be able to store whatever the user inputs on the <input> field into a variable, that way we can use it later on as we see fit.

In vanilla JS or even jQuery you may be tempted to try to capture the input element with a $('input') or document.querySelector, but in Vue we have a much simpler way to achieve this mundane task.

Introducing v-model.


v-model

As you’ve learned before, everything that starts with a v- is a Vue directive. What v-model in particular translates to, in very simple terms, is:


Vue, I want you to grab this input that i’m putting this v-model directive on, and make a two way relation with it. I’m going to give you a property, and whenever I change this property anywhere in my code - I want you to change it on the input, and likewise, whenever this input changes - I want you to reflect those changes in my prop.

Let’s try to put this in action, go to the <input> declaration, and add the v-model directive to it.

<pre class="ql-syntax" spellcheck="false"><input type="text" v-model="favoriteGame">

</pre>

Now go and run this in your browser and type something into your magical input box of goodness. Taaaaa…da?

Ok, even though nothing seems to be happening. Go ahead and open your Vue devtools and inspect the <Root> element’s data. YEAH. Progress!

Now go into the dev tools and change the value of favoriteGame into something else (don’t forget the quotes wrapping it, we need a string here). EZ-BINDS-R-US 💪

Vue is VERY smart about how to bind with every type of native HTML form inputs, so really you only need to drop in the v-model bomb and profit, but the power of v-model really shows when you start building your own wrapper components and using it a-la-carte.

Behind the scenes v-model is actually setting up a v-bind:value and a v-on:input even binding, but going in depth on this is a bit out of scope so i’m just going to drop you a link if you’re interested in looking further and look the other way. v-model on Components


Watchers

Now that we have our sweet sweet two-way binding v-model awesomeness in place, let’s actually do something with it.

You’ve already learned that with a state data prop you can put it in your template with {{ favoriteGame }}, so no need to go over that again. You’ve learned how to use it inside a method and computed prop with this.favoriteGame - so no need to redo that. But what happens when you want to “listen” or “react” to this property actually getting modified?

Computed properties are fantastic at recalculating stuff and returning a value, but what if we want to modify another piece of state on our app when this value changes, or maybe even fire an async request of some sort? In these niche cases watchers come and save the day.

Let’s go an add the boilerplate for creating a watched prop.

<pre class="ql-syntax" spellcheck="false"><script>
const app = new Vue({
el: '#app',
data() {
return {
favoriteGame: null,
response: ''
}
},

// Watchers here
watch: {
  favoriteGame(newValue, oldValue) {
    console.log('Favorite game was ' + oldValue + ' and now is ' + newValue)
  }
}

});
</script>

</pre>

Watchers are defined inside a watch property in our instance or component, and we pass it an object that will include a property for each one of the props we want to watch.

In simple terms, every data prop or props prop you want to watch/react to needs to go inside this watch: {} with its name. So if your prop is named favoriteGame that’s the name of your function.

Each one of these functions gets two params passed to it, the first one will be the newValue that this prop is getting, and the second one is the oldValue that it used to have before the change.

Check out the console.log statement and refresh your browser window. Try typing something into the <input> and check out your console output. Every time our favoriteGame prop changes in ANY way, this watcher will be fired.

Now let’s actually do something cool with it. Remember our response prop? Let’s put something into it depending on what the user answers, and have some fun with it.

<pre class="ql-syntax" spellcheck="false">watch: {
favoriteGame(newValue, oldValue) {
if (!newValue) return // If its an empty string, pass

// If the new value contains the keyword metroid
if (newValue.toLowerCase().indexOf('metroid') !== -1) {
  this.response = 'Ceres station is under attack!'
  return
}

// If the new value contains the word zelda
if (newValue.toLowerCase().indexOf('zelda') !== -1) {
  this.response = 'Its dangerous to go alone, take this 🗡️'
  return
}

// If the OLD value was metroid, and user changed it something else
if (
  oldValue.toLowerCase().indexOf('metroid') !== -1 &amp;&amp;
  newValue.toLowerCase().indexOf('metroid') === -1
) {
  this.response = 'GET TO DA CHOPPA NAO'
  return
}

// Default response
this.response = 'Sure, why not?'

}
}

</pre>

In case you don’t know, indexOf checks the string and returns -1 in case there was no match, and else it returns the position of the string we’re searching for in the string being searched.

Go ahead and have some fun with this, make some new examples and play with it in your browser.

I hope you can see now the power of watched properties, the way I have found it useful is to think, if my property changes and I need to REACT programmatically to it (with an ajax call, an external function, updating a secondary value, etc), then watchers are usually a good call. For anything else, go with computed properties.

<pre class="ql-syntax" spellcheck="false"><html>

<head>
<title>Vue 101</title>
</head>

<body>
<div id="app">
<label>What's your favorite game ever?</label>
<input type="text" v-model="favoriteGame">

&lt;hr&gt;

&lt;p&gt;{{ response }}&lt;/p&gt;

</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
const app = new Vue({
el: '#app',
data() {
return {
favoriteGame: null,
response: ''
}
},
watch: {
favoriteGame(newValue, oldValue) {
if (!newValue) return

      if (newValue.toLowerCase().indexOf('metroid') !== -1) {
        this.response = 'Ceres station is under attack!'
        return
      }

      if (newValue.toLowerCase().indexOf('zelda') !== -1) {
        this.response = 'Its dangerous to go alone, take this 🗡️'
        return
      }

      if (
        oldValue.toLowerCase().indexOf('metroid') !== -1 &amp;&amp;
        newValue.toLowerCase().indexOf('metroid') === -1
      ) {
        this.response = 'Nothing is true , everything is permitted'
        return
      }

      this.response = 'Sure, why not?'
    }
  }
});

</script>
</body>

</html>

</pre>

Conclusion

Congratulations on making it this far!

You now have the basic tools to actually build a really cool and functional application in Vue, I guarantee it. However, there is still a lot to learn and a lot to explore in order for you to squeeze every inch of juice out of this framework.

But don’t worry, i’ve said it before and I stand by it today, one of the key aspects I enjoy most about Vue.js is the documentation.

I remember back when I was starting out with programming I was really afraid of having to dive docs because they were usually really poor explained, and assumed a high level of understanding of the language and the framework/lib that I was trying to use.

Thankfully, the Vue docs team has done a wonderful job of making a complete guide full with examples for every thing that we have covered in this guide plus everything else you need to excel at this framework.

This concludes the Beginner series for Vue (although I will keep making more topic-oriented articles that will follow up on this). It’s been a pleasure, and thanks for reading!

Thanks for reading ❤

If you liked this post, share it with all of your programming buddies!

Follow me on Facebook | Twitter


Learn More

Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

Nuxt.js - Vue.js on Steroids

Build Web Apps with Vue JS 2 & Firebase

The Complete JavaScript Course 2019: Build Real Projects!

Building a Vue SPA With Laravel

Vue CLI 3 Full-Stack App Structure

Build a CMS with Laravel and Vue

Vue Authentication And Route Handling Using Vue-router

Vuejs 2 Authentication Tutorial

Build a Progressive Web App In VueJs

Originally published at https://dev.to/vuevixens

How to Copying Javascript Objects in an efficient way

How to Copying Javascript Objects in an efficient way

Copying Javascript objects can be tricky. Most of the time, we will do shallow copy of an object in javascript.

But, there are few problems associated with that approach. But getting into that topic, we will see what is shallow and deep copy in javsacript.

Shallow vs Deep Copy

In javascript, shallow copy only clones the top level of an object. if an object contains the nested or reference object. it will copy only the reference to it.

Shallow Copy

This is image title

For example, let’s say you have an object like this

let data = {
  "id" : 1,
  "name" : "john",
  "address" : {
    "street" : "Sample",
    "country" : "Earth",
    "Street" : "Madison street"
  }
}

you are copying the object to a new variable using Object.assign

copydata = Object.assign({},data);

After that, if you console log the copydata variable. you will get the output like
This is image title

Now, you are changing the variable data’s object

data.address.street = "Changed Street";

if you console log copydata again, you will get output like,

This is image title

it changes the copied object value too because the copied object will refer to the same object.

To solve this problem, deep copying is used in javascript.

Deep Copy

Meanwhile, deep copying in javascript clones the nested objects too and stores it in the different memory location.

So, changing the original object doesn’t affect the cloned object.
This is image title

Deep Clone in Javascript

it can be achieved using lodash util library in javascript which is one of the popular library in javascript ecosystem.

Install lodash in your machine to use it. After that, there is a method called clonedeep in lodash which is used to achieve the deep copying in javascript.

<iframe height="400px" width="100%" src="https://repl.it/@ganeshmani/shallodeepcopy?lite=true" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe>

Thanks for reading !

10 Most Popular JavaScript Frameworks 2020 For Developers

10 Most Popular JavaScript Frameworks 2020 For Developers

JavaScript Frameworks is an application framework which is written in javascript. It is a collection of JavaScript code libraries. JavaScript Framework is used to design application. It is very difficult to choose a framework among the most popular JavaScript framework for any project. So it is very important to know that the top javascript framework and features of that particular JavaScript Framework. In this article, we show Top 10 JavaScript frameworks with features and their pros and cons.

1- ANGULAR JS

This is image title

  • Angular JS is an open source framework built over JavaScript. It was built by the developers at Google. This framework was used to overcome the obstacles encountered while working with Single Page applications.

  • AngularJS was born in 2009 as a component of a more immensely colossal commercial product, called GetAngular.

  • Large organizations like PayPal, Freelancer, LinkedIn, Lego, Hopscotch and several others are powering their UIs by AngularJS.

  • Angular makes it easier to work with dynamic rendering with its JSON based processing and rendering capabilities.

  • Angular has been developed with the vision of making it modular, testable and maintainable.
    The latest version of Angular JS is 1.7.8

Features

  • Dependency Injection – js has built-in dependency injection (DI) that helps natural development, understanding, and testing.

  • Data-binding – The two-way data-binding feature saves developers from writing a lot of code. It is the automatic synchronization of data between model and view components.

  • It can be configured in MVC as well as MVW architecture.

  • Services − are a set of code that can be shared by different components of an application.

  • Directives – With this feature, it becomes easy to create custom HTML tags that act like new custom widgets. It can also be used to manipulate DOM attributes.

PROS OF ANGULAR.JS

  • Two-way data binding -AngularJS facilitates faster and easier data binding which doesn’t require a developer to intervene at all.

  • DOM manipulation -the developer saves time and efforts to code, translate and update the DOM elements.

  • Improved server performance -it only serves static files and responds to the API calls.

  • Responsive web – AngularJS makes it possible by letting responsive, fast-loading and seamlessly -navigating websites and apps.

  • Use of directives -AngularJS makes use of directives that keep the scripts and HTML pages mess-free and extremely organized.

CONS OF ANGULAR.JS

  • Difficult learning – you may have to face great difficulty in getting adapted to the framework.

  • The scopes -Quite layered and arranged hierarchically, scopes can be complex entities to handle if it is your first experience with Angular.

  • Inexperience with MVC -If you are completely unfamiliar with the Model-View-Controller architectural patterns, using Angular can be extremely time-consuming.

Blog: Angular Blog

Getting Started: Angular JS

2- NODE.JS

This is image title

  • Node.js is an open source, a cross-platform runtime environment for executing JavaScript code outside of a browser.

  • It is used for building back-end services or APIs and developing server-side and networking applications.

  • It is a platform which is built on Google Chrome’s JavaScript Engine (V8 Engine).

  • Node.js was originally written by Ryan Dahl in 2009.

  • Node.js is developed by Joyent Inc.

  • The latest version of Node.js is 12.2.0.

  • It is used by companies like Uber, PayPal, and Walmart which is a mirror to its global acceptance as a back-end language.

  • The applications built on Node, are written in JavaScript which can be run within the Node.js runtime on OS like Microsoft Windows, Linux as well as MacOS.

FEATURES

  • The applications in Node never buffer any data. This is because the applications output the data in chunks.

  • Node uses single-threaded models which consist of event looping. This event mechanism helps servers to respond in an asynchronous way that makes the servers highly scalable.

  • Same code for client-side and server-side

  • Node technology helps in streaming data from different sources and can be used to proxy some servers.

  • The APIs of the Node’s library is asynchronous which means that the server doesn’t wait for an API to return data; thus rendering the data asynchronously giving a faster response to every request.

PROS OF NODE.JS

  • Share the same piece of code with both server and client side.

  • better efficiency and overall developer productivity

  • it also serves as a marketplace for open source JavaScript tools, which plays an important role in the advance of this technology.

CONS OF NODE.JS

  • Dealing with the relational database is a pain if you are using Node.

  • Node.js is a single-threaded environment, which is often considered a serious drawback of the technology

  • Without diving in depth of JavaScript, if someone starts Node, he may face a conceptual problem.

Getting Started: Node.js 12.2.0

3- REACT

This is image title

  • React is an open-source JavaScript most popular framework which is used by Facebook, Instagram and much more.

  • React is maintained by Facebook, Instagram and a community of individual developers and corporations, and aims to address the challenges encountered in developing single-page applications.

  • React was created by Jordan Walke, a software engineer at Facebook.

  • Latest React version is 16.8.4

  • React is mainly used for the V (view) in the MVC model since the UI can be updated without having to reach out to the server and fetch a new view.

Features

  • Components – React is declarative and component based. The web pages are divided into small components to create UIs.

  • Data binding – One-way data binding along with an application infrastructure called Flux controls. Flux is a pattern that keeps data unidirectional.

  • Maintaining React is easy and straightforward due to its component-based architecture and reusability of the defined components.

  • React can be used on the server-side as well as on client-side.

  • You can use React with other frameworks.

  • Maintaining React is easy and straightforward due to its component-based architecture.

  • JSX – JSX is a javascript extension which indicates that the script needs to be processed and converted to actual javascript.

PROS OF REACT.JS

  • React is the ability to reuse code components of a different level anytime, another meaningful time-saving effect.

  • Virtual DOM in ReactJS makes the user experience better and the developer’s work faster.

  • Stable code – ReactJS allows for direct work with components and uses downward data binding to ensure that changes in child structures don’t affect their parents.

  • An open-source Facebook library – constantly developing and open to the community.

CONS OF REACT.JS

  • JSX as a barrier – Developers and designers complain about JSX’s complexity and consequent steep learning curve.

  • Poor documentation – developers struggle with integrating tools with ReactJS.

Blog: React Js Blog

Getting Started React Js

4- VUE.JS

This is image title

  • Vue.js is a lightweight progressive JS framework which gets a lot of its concepts from ReactJS and AngularJS.

  • Vue.js is a JavaScript front-end framework that was built to organize and simplify web development.

  • Vue was created by Evan You.

  • It is easy to integrate into other applications and languages. For example, Vue.js bundles with Laravel and couples nicely with it to create frontends for Laravel applications.

  • Vue uses an HTML-based templating syntax, allowing developers to write components quickly and easily.

  • Vue has an incredibly small file size, making it easy to include in projects without creating a slowdown.

  • The latest version of Vue.js is 2.6.8

Features

  • Easy to understand and develop

  • Transitions – Vue allows the application of transition effects when items are inserted, removed or updated from the DOM.

  • Reactivity – Vue has a robust reactivity system.

  • It consists of a clear separation between the components and directives.

  • Vue proves to be more flexible and modular front-end development framework.

PROS OF VUE.JS

  • Flexibility -This flexibility makes it easy to switch to Vue because developers who have experience with React, Angular and JS framework would find Vue’s design very familiar.

  • Small Size – it should be noted that the Vue.js ecosystem is also small and fast.

  • The advantage with Vue.js is that it enables the development of large-scale templates.

  • Vue.js useful both for building entire single page applications and for contributing components into existing apps.

  • For a beginner to write their first application, they just have to know some basic Javascript and HTML.

CONS OF VUE.JS

  • Sometimes flexibility can cause some issues for the developers.

  • Language Barrier – A Majority of the users are non-English speaking communities which are perhaps one of the biggest issues with this framework.

  • Vue doesn’t yet have the widespread support of its fellow frameworks as it is not as popular as other frameworks like Angular.js.

Getting Started: Vue.js

5- EMBER

This is image title

  • Ember.js is an open-source client-side JavaScript web application framework predicated on the model-view-controller (MVC) software architectural pattern.

  • Ember’s roots go way back to 2007. Starting its life as the SproutCore MVC framework, pristinely developed by SproutIt and later by Apple, it was forked in 2011 by Yehuda Katz, a core contributor to the popular jQuery and Ruby on Rails projects.

  • It’s used for TinderBox, Netflix, Apple Music, Yahoo!, LinkedIn, PlayStation Now, and Vine.

  • A complete development stack can be formed by using Ember and other important tools.

  • Handlebars layout and Ember’s backend architecture allows writing developers own application-specific HTML tag.

  • Ember has been a highly opinionated framework which was built to be very flexible.

  • The Ember Inspector allows for easy inspection of Ember objects in your browser’s developer tools. This can be used both while developing and while debugging issues.

  • The latest version of Ember is 3.8.0

Features

  • Excellent data library.

  • Ember’sCLI provides standard application structure.

  • Ember works on the Model-view-view model (MVVM) pattern.

  • Inspector tool is useful for debugging applications.

PROS OF EMBER.JS

  • High performance

  • Faster development due to Ember CLI

  • Understandable documentation

  • Two-way data binding

  • Well-organized

  • Own debugging tool (Ember Inspector).

CONS OF EMBER.JS

  • Smaller community and the extensive amount of outdated tutorials on the web

  • Due to a helper function, two-way data binding is more complex.

  • Too big for small projects

  • Complications with processing quick changes

  • Difficult to learn
    Blog: Ember.js

Getting Started: Ember.js

6- BACKBONE.JS

This is image title

  • Backbone.js is a lightweight MVC framework. Born in 2010, it expeditiously grew popular as a lean alternative to cumbersomely hefty, full-featured MVC frameworks such as ExtJS.

  • Backbone.js is developed by Jeremy Ashkenas.

  • This resulted in many accommodations adopting it, including Pinterest, Sony Entertainment Network, Flixster, Airbnb, SoundCloud, and others.

  • Backbone.js gives structure to web applications by providing models with key-value binding and custom events, accumulations with an affluent API of enumerable functions, views with declarative event handling, and connects it all to your subsisting API over a RESTful JSON interface.

  • The latest version is 1.4.0.

FEATURES

  • RESTful JSON interface – Backbone is a framework/ library that has a RESTful JSON interface, based on the Model-view-presenter (MVP) application model.

  • Event-driven communication between views and models prevents the code from being hard to read.

  • Models in Backbone.js can be tied to a back-end since Backbone provides excellent support for RESTful APIs.

  • In case of any changes in a model, the HTML code is automatically updated.

  • It is a simple library that separates UI and business logic.

PROS OF BACKBONE.JS

  • Backbone gives you a lot more control over performance, particularly in mobile scenarios.

  • Easy, fast and lightweight framework so very easy to understand the documentation and codes.

CONS OF BACKBONE.JS

  • The biggest drawback of Backbone is that, instead of providing structure, it provides some basic tools to create structure. So, somewhere you have to depend on developers to decide how to structure the application.

  • To update the view whenever your model changes, and to update the model whenever your view changes, you have to write a lot of boilerplate, because of lack of support for two-way data binding.

Getting Started: Backbone.js

7- POLYMER

This is image title

  • Polymer.js is the open-source JavaScript library for building web applications using Web components.

  • It was the very first library to allow interactive building applications by composing components.

  • Polymer.js is built to leverage the features that are present in the web platform to let developers build components.

  • Polymer.js is being used by YouTube, Google Play Music and Netflix, to name a few.

  • Polymer.js is considered to be one of the best to work with Spring Boot REST resources when compared to other JS frameworks.

  • Version 3.0 of the Polymer library brings web components into the mainstream, embracing JavaScript modules and npm.

  • The latest version is 3.2.0.

FEATURES

  • Speed – It is three times faster in Chrome and four times faster on Safari.

  • Polymer.js is built on top of the web standards API which allows building custom HTML elements

  • Both one-way and two-way data binding is possible with this library.

  • The web component standards are helpful in the creation of usable widgets in web documentation and application.

  • Polymer elements consist of designs and themes which mean prevents developers from modifying complex web page source code to match the designer’s need.

PROS OF POLYMER.JS

  • Quick -The Polymer is a new library which is three times faster on Chrome, four times faster on Safari.

  • Developers use Polymer elements which include design and themes, which means there is no need to modify complex Web page source code to match designer specifications.

  • Polymer.js provides new functionality such as Shadow DOM which enables the encapsulation of CSS.

CONS OF POLYMER.JS

  • Dependency errors and pointing to a different version of dependencies.

  • Downloading of entire library and Polyfills.

  • Lack of server-side rendering.

Blog: Polymer.js Blog

Getting Started: Polymer 3.0

8- METEOR

This is image title

  • Meteor is a full-stack framework, which allows developers to learn one tool, and use it for almost everything in their application.

  • It also makes it an exciting proposition for new developers who are aiming at full-stack positions or projects, as they can get productive faster with Meteor.

  • Meteor uses a front-end JavaScript that runs on the browser and back-end on meteor server within Node.js.
    The latest version of Meteor is 1.8.

  • Meteor is developed by Meteor Development Group.

  • Companies like Mazda, Honeywell, and Qualcomm use Meteor.

FEATURES

  • Meteor provides a full-stack solution for developing and using web applications.

  • Highly scalable and beginner friendly.

  • Easy to set up and start creating projects.

  • It allows using the same code on the front-end as well as the back-end for mobile and web applications.

  • Integrated live reloading allows refreshing only the required DOM elements without reloading the entire page.

PROS OF METEOR.JS

  • Simplicity – Coding is very simple and beginner friendly.

  • Official and community packages are a huge time saver.

  • Velocity is the name of the Meteor’s testing tool. In addition to its core functions, Velocity enables integration with Mocha or Jasmine syntax.

CONS OF METEOR.JS

  • There is a lot of magic going on when working with Meteor, so developers might find themselves limited in some way.

  • Deployment and tool integration is not as simple as some other platforms.

  • Meteor isn’t very suitable for large and complex applications.

Blog: Meteor Blog

Getting Started: Meteor.js

9- MITHRIL.JS

This is image title

  • Mithril is used for creating single-page applications on the client-side.

  • It supports all the browsers like IE9 without the requirement of any polyfills.

  • It is tiny, fast, provides routing and XHR utilities.

  • Mithril has in-built modules for XHR and routing while React needs third parties for the same along with a lot of memory usage.

  • Mithril is known to be pragmatic since it is straightforward to learn components, routing and XHR in less than 15 minutes to start building applications.

  • Mithril is currently being used by companies like Nike and Fitbit and other open source platforms like Liches.

FEATURES

  • It is Flux compatible, robust and un-opinionated

  • Mithril templates are just JavaScript so that developers can test them in any JavaScript engine without a build step.

  • In Mithril.js, components are created with an optional controller and a required view property.

  • Mithril gives hierarchical MVC components, URL routing, safe-by-default templates, customizable data binding.

PROS OF MITHRIL.JS

  • Easy to learn

  • Mithril’s loading times are very fast. This is because it’s templates are compiled first and then served to the browser and because it uses a virtual DOM.

  • Mithril gives to the developer the flexibility to chose the best JavaScript library to use for a specific task.

  • Mithril’s API is pretty small compared to other frameworks.

CONS OF MITHRIL.JS

  • Mithril isn’t recognized much, it often has a head to head competition with other JavaScript frameworks.

Getting Started: Mithril.js 1.1.6

10- AURELIA

This is image title

  • Aurelia is called as the “next-gen UI framework” written in ECMAScript.

  • Aurelia is a collection of open source modern JavaScript modules.

  • Aurelia is a JavaScript client framework for the web, mobile, and desktop that leverages simple conventions to empower your creativity.

  • Aurelia is the only framework that lets you build components with plain, vanilla JavaScript/TypeScript. The framework stays out of your way so your code remains clean and easy to evolve over time.

-Aurelia provides a CLI for generating and building projects, a browser plugin for debugging and a VS Code plugin as well.

FEATURES

  • Routing and UI Composition – Helps in using an advanced client-side router with its pluggable pipeline, child routers, and asynchronous screen activation.

  • HTML Extensible

  • Aurelia integrates with Web Components with no external dependencies.

  • Aurelia supports ES5, ES2015, ES2016 and TypeScript.

  • Testable for ES2015 using DI container. Unit code testing is very simplified.

PROS OF AURELIA.JS

  • The framework itself is directed towards web standards so you will always stay up to date with modern concepts.

  • it is very agile, knowledgeable and willing to help within short notice.

  • It is directed towards the developers’ experience. It saves you lots of time.

  • You can add or remove any tools that the framework offers and you can also add any other tools that aren’t part of the framework.

  • It has a simple structure which makes the framework quicker and easier to learn.

  • It is easy and quick to configure and set it up for use.

CONS OF AURELIA.JS

  • There are no major limitations.

Blog: Aurelia.js

Getting Started: Aurelia.js.

Thanks for reading !

The perfect architecture flow for your next Node.js project

The perfect architecture flow for your next Node.js project

A good start is half the battle, said someone wiser than me. And I can’t think of any quote that would better describe the situation every developer gets into whenever starting a new project. Laying out a project’s structure in a practical way is one of the hardest points of the development process and, indeed, a delicate one.

We can define a path about discussing Node.js technologies, how to choose what front-end framework to use, and now we can try to dig deeper on how to structure our web apps once we have decided on the tech stack to use.

The importance of good architecture

Having a good starting point when it comes to our project architecture is vital for the life of the project itself and how you will be able to tackle changing needs in the future. A bad, messy project architecture often leads to:

  • Unreadable and messy code, making the development process longer and the product itself harder to test

  • Useless repetition, making code harder to maintain and manage

  • Difficulty implementing new features. Since the structure can become a total mess, adding a new feature without messing up existing code can become a real problem

With these points in mind, we can all agree that our project architecture is extremely important, and we can also declare a few points that can help us determine what this architecture must help us do:

  • Achieve clean and readable code

  • Achieve reusable pieces of code across our application

  • Help us to avoid repetitions

  • Make life easier when adding a new feature into our application

Establishing a flow

Now we can discuss what I usually refer to as the application structure flow. The application structure flow is a set of rules and common practices to adopt while developing our applications. These are the results of years of experience working with a technology and understanding what works properly and what doesn’t.

The goal of this article is to create a quick reference guide to establishing the perfect flow structure when developing Node.js applications. Let’s start to define our rules:

Rule #1: Correctly organize our files into folders

Everything has to have its place in our application, and a folder is the perfect place to group common elements. In particular, we want to define a very important separation, which brings us to rule number #2:

Rule #2: Keep a clear separation between the business logic and the API routes

See, frameworks like Express.js are amazing. They provide us with incredible features for managing requests, views, and routes. With such support, it might be tempting for us to put our business logic into our API routes. But this will quickly make them into giant, monolithic blocks that will reveal themselves to be unmanageable, hard to read, and prone to decomposition.

Please also don’t forget about how the testability of our application will decrease, with consequently longer development times. At this point, you might be wondering, “How do we solve this problem, then? Where can I put my business logic in a clear and intelligent way?” The answer is revealed in rule number #3.

Rule #3: Use a service layer

This is the place where all our business logic should live. It’s basically a collection of classes, each with its methods, that will be implementing our app’s core logic. The only part you should ignore in this layer is the one that accesses the database; that should be managed by the data access layer.

Now that we have defined these three initial rules, we can graphically represent the result like this:
This is image title
Separating our business logic from our API routes.

And the subsequent folder structure sending us back to rule #1 can then become:
This is image title

By looking at this last image, we can also establish two other rules when thinking about our structure.

Rule #4: Use a config folder for configuration files

This is image title

Rule #5: Have a scripts folder for long npm scripts

This is image title

Rule #6: Use dependency injection

Node.js is literally packed with amazing features and tools to make our lives easier. However, as we know, working with dependencies can be quite troublesome most of the time due to problems that can arise with testability and code manageability.

There is a solution for that, and it’s called dependency injection.

Dependency injection is a software design pattern in which one or more dependencies (or services) are injected, or passed by reference, into a dependent object.

By using this inside our Node applications, we:

  • Have an easier unit testing process, passing dependencies directly to the modules we would like to use instead of hardcoding them

  • Avoid useless modules coupling, making maintenance much easier

  • Provide a faster git flow. After we defined our interfaces, they will stay like that, so we can avoid any merge conflicts.
    This is image title
    Using Node.js without dependency injection.

Simple but still not very flexible as an approach to our code. What happens if we want to alter this test to use an example database? We should alter our code to adapt it to this new need. Why not pass the database directly as a dependency instead?
This is image title

Rule #7: Use unit testing

Now that we know we have got dependency injection under our belt, we can also implement unit testing for our project. Testing is an incredibly important stage in developing our applications. The whole flow of the project — not just the final result — depends on it since buggy code would slow down the development process and cause other problems.

A common way to test our applications is to test them by units, the goal of which is to isolate a section of code and verify its correctness. When it comes to procedural programming, a unit may be an individual function or procedure. This process is usually performed by the developers who write the code.

Benefits of this approach include:

Improved code quality

Unit testing improves the quality of your code, helping you to identify problems you might have missed before the code goes on to other stages of development. It will expose the edge cases and makes you write better overall code

Bugs are found earlier

Issues here are found at a very early stage. Since the tests are going to be performed by the developer who wrote the code, bugs will be found earlier, and you will be able to avoid the extremely time-consuming process of debugging

Cost reduction

Fewer flaws in the application means less time spent debugging it, and less time spent debugging it means less money spent on the project. Time here is an especially critical factor since this precious unit can now be allocated to develop new features for our product

Rule #8: Use another layer for third-party services calls

Often, in our application, we may want to call a third-party service to retrieve certain data or perform some operations. And still, very often, if we don’t separate this call into another specific layer, we might run into an out-of-control piece of code that has become too big to manage.

A common way to solve this problem is to use the pub/sub pattern. This mechanism is a messaging pattern where we have entities sending messages called publishers, and entities receiving them called subscribers.

Publishers won’t program the messages to be sent directly to specific receivers. Instead, they will categorize published messages into specific classes without knowledge of which subscribers, if any, may be dealing with them.

In a similar way, the subscribers will express interest in dealing with one or more classes and only receive messages that are of interest to them — all without knowledge of which publishers are out there.

The publish-subscribe model enables event-driven architectures and asynchronous parallel processing while improving performance, reliability, and scalability.

Rule #9: Use a linter

This simple tool will help you to perform a faster and overall better development process, helping you to keep an eye on small errors while keeping the entire application code uniform.
This is image title
Example of using a linter.

Rule #10: Use a style guide

Still thinking about how to properly format your code in a consistent way? Why not adapt one of the amazing style guides that Google or Airbnb have provided to us? Reading code will become incredibly easier, and you won’t get frustrated trying to understand how to correctly position that curly brace.
This is image title
Google’s JavaScript style guide.

Rule #11: Always comment your code

Writing a difficult piece of code where it’s difficult to understand what you are doing and, most of all, why? Never forget to comment it. This will become extremely useful for your fellow developers and to your future self, all of whom will be wondering why exactly you did something six months after you first wrote it.

Rule #12: Keep an eye on your file sizes

Files that are too long are extremely hard to manage and maintain. Always keep an eye on your file length, and if they become too long, try to split them into modules packed in a folder as files that are related together.

Rule #13: Always use gzip compression

The server can use gzip compression to reduce file sizes before sending them to a web browser. This will reduce latency and lag.
This is image title
An example of using gzip compression with Express.

Rule #14: Use promises

Using callbacks is the simplest possible mechanism for handling your asynchronous code in JavaScript. However, raw callbacks often sacrifice the application control flow, error handling, and semantics that were so familiar to us when using synchronous code. A solution for that is using promises in Node.js.

Promises bring in more pros than cons by making our code easier to read and test while still providing functional programming semantics together with a better error-handling platform.
This is image title
A basic example of a promise.

Rule #15: Use promises’ error handling support

Finding yourself in a situation where you have an unexpected error or behavior in your app is not at all pleasant, I can guarantee. Errors are impossible to avoid when writing our code. That’s simply part of being human.

Dealing with them is our responsibility, and we should always not only use promises in our applications, but also make use of their error handling support provided by the catch keyword.
This is image title

Conclusion

Creating a Node.js application can be challenging, I hope this set of rules helped you to put yourself in the right direction when establishing what type of architecture you are going to use, and what practices are going to support that architecture.

Originally published by Piero Borrelli at blog.logrocket.com

Go Top Programming Languages in 2020 from Authentic Surveys

Go Top Programming Languages in 2020 from Authentic Surveys

Comparing Programming Languages is a very complex thing and so there are many graphical illustration/jokes trying to symbolize Programming language. I found few and I am starting this article with those.

This is image title

In simple words, Programming Language empowers human to instruct and control machine. So, it is natural that there will be so many languages which try to make this process more powerful and simple. For this very reason there are hundreds of programming languages, many of those programming languages are now out of active use, few are going to be obsolete in coming years and then there are languages which is going to continue and prove its usage in coming years and then there are new programming language fighting for it acceptance.

This article going to present the trends of top Programming Languages which will continue in the coming year 2020. To predict the trend of the programming language in 2020 this article uses data from authentic surveys, various collected statistics, search results and salary trends according to programming languages. This article will help the new learner to pick a programming language to learn and for expert, it will help to decide either to switch to another language or to continue with his expertise language.

In the next section, I have prepared two tables which summarize the popularity trend of Programming Languages in the last five years (2015-19). The data is taken from Stackoverflow popularity survey 2015-2019. For a clear and accurate understanding, the programming languages are divided into two groups, first, languages which have origin before 2000 and the second group has languages which came after 2000. The selection of 2000 as the boundary is just random but very helpful to understand the programming trend under these two groups. The table also lists origin year and main or documented purpose of these programming/scripting languages.

This is image title
This is image title

Observations:

There is a decrease in the popularity of all languages from 2018 to 2019 except Python.

Python

Python is the only language continuously on rising since last five years. It is a general-purpose language, so someone wants to learn just one programming in 2020 and want to cover more area of software development then Python could be chosen**.**

Java

Java was on rising but fall in 2019, the reason could Kotlin gaining popularity on the Android platform. Java is a good choice for a programming language but now it is under Oracle and Google is promoting Kotlin so it is in the conflicted zone. As a matter of fact still, the large number of the company is using Java and going to continue with Java due to its developers base, framework, and legacy application.

C/C++

C and C++ are still holding with approx 20% and it will be there due to its inherent features and legacy system.

JavaScript

JavaScript popularity can be attributed to the growth of popular JavaScript library and framework like node.js, etc. JS is the language for the dynamic website and this going to be top for coming years because of its active development, support from Mozilla and penalty of libraries and frameworks. So, if someone wants to be web development, javascript is a must.

R

R is gaining popularity in recent years and reason would be growth and popularity of data analysis. It is used by data scientist but again much behind in comparison to Python which has established as general-purpose languages and enjoy active developers with lots of data science libraries and modules. So, one can prefer Python over R if they have to choose only one otherwise if wanted carrier in Data Sciences then learning both will a good option.

<div class="5tjAASx1"><script type="bfa163966612c2c2fba9ece2-text/javascript">(adsbygoogle = window.adsbygoogle || []).push({});</script></div>

Ruby

Like PHP, Ruby is also facing tough competition from JavaScript and even Python to establish as back-end web development programming language. So, again for web development javascript and Python (server-side (Flask, Django, etc.) would be a good choice and will offer more domain flexibility than Ruby.

PHP

There is a sharp decline in PHP popularity in 2019 and it can be traced back to server-side acceptance of javascript and Python. So, if someone wants to go to server-side web development then still PHP is a good choice with a large number of popular framework like CakePHP, Codeigniter, etc. otherwise choosing a general-purpose programming language would be better.

Objective-C

Objective-C was the main language for Apple’s software such as macOS, iOS, etc. before Apple moved to Swift language. So this transition is reflected in the popularity of both languages, i.e. there is a fall in popularity for Objective-C and the popularity of Swift is rising. So, again if someone wants to be a developer for Apple’s products then Swift should be the language of choice.

This is image title

Observations:

Swift

Swift has replaced the Objective-C as the main language for Apple-related software and application. Since it is supported and promoted by Apple so there is an increase in popularity since its inception and as Apple is going to continue with it so if someone is looking for Apple-specific development platform then Swift is going to be a must-know programming language. This is mostly vendor and product-specific language with very less usage outside Apple’s eco-system.

Go

Go (Golang) is getting popularity as maintain, use and promoted by Google. The motivation of Go development was to address criticism of some of the popular languages and keeping the best of them in one place. Since 2017, Go is moving upward in popularity and with Google support, it is going to enjoy this in coming years. Google is also making Go as a primary language for new projects and replacing other languages with Go, this trend going to make useful and important to learn in coming years so one can pick Go as a new programming language.

Kotlin

Kotlin is being offered as an alternative of Java for Android development and again it is supported and promoted by Google so it is also picking up by developers and gaining popularity in recent years. So, with the growth of Android, support of Google and with clean and short syntax it is going to be a choice of Android application developers and is a good choice to learn for Android App developer. Kotlin going to be shine as a prominent programming environment for Android development.

Scala

Scala tries to establish as an alternative to Java but didn’t get very well among developers. It doesn’t have big support from any multi-national company, perceive as functional languages and dependency on JVM doesn’t provide much scope to rise in popularity. There could be steady growth but very slow and surely not a language to learn as a beginner.

Julia

Julia aims to bring the speed of ‘C’ and simplicity of Python but it is strange that didn’t found any popularity in Stackoverflow survey but gaining popularity among data science domain and being seen as a challenger for R and Python in long run. Surely, there will be growth in Julia but still, Python or R is better for job and growth.

C#

C# is the language for the .NET framework and developed by Microsoft. Its popularity is approx constant over past years and going to continue with a similar trend. This is vendor-specific language so one can pick this language if want to work in the Microsoft development environment. Recently, Microsoft has open-sourced the .NET so there would be some upward trend but again it is vendor-specific so there won’t be much affected.

Rust

Rust, Clojure, etc. are languages which have a user-base but not so popular so surely not going to have an upward swing in popularity.


A Picture Says a Thousand Words

To understand a clear trend and picture of top programming language growth let keep a picture of it by the various chart. The figure 1 and figure2 gives a very clear picture that in old language stack JavaScript is far ahead than others and credit goes to boom in web development, then C and C++ together competing very closer to Java. Python is moving upward in popularity and only language which popularity is constantly increasing in the last 5 years. New languages are getting popularity and most of them are supported by the multi-national company and bit IT giant like Microsoft, Google and Apple.

This is image title

This is image title

Loved and Wanted Languages

This is image title

This is image title

From above Table and Figure, few observations are very obvious, Love of Rust is growing in last five years whereas Swift is loosing love from developers and Python is in between these two and last two years have gain for Python. One more unique observation is that out of 5 loved languages 4 are from post 2000 group while only Python is the older language and Kotlin love started with addition of Kotlin for Android development post 2017.

This is image title

From above table, wish of developing in javascript and Python is growing in last years and this reflect in popularity and love for the language. There is a sharp decline in Java and this is due to the addition of Kotlin as alternative for Android app development and also change of policy by Oracle who own Java now.

This is image title

Technologies and Programming Languages

This is image title

In this figure, one can see that the largest cluster is for Web development and JavaScript and its various framework is dominating the cluster this is USP of JavaScript growth. The second-largest cluster is of Microsoft technologies and Python technologies which again clear the popularity and love for the language. Python cluster is linked with data science technologies which highlight the growth story of Python.

TIOBE Index

TIOBE index rank programming language based on search engine search result. The selection of search engines and programming language is defined in its page. The ratings are calculated by counting hits of the most popular search engines. The search query that is used is +”<language> programming”. In TIOBE index Java is dominating the ranking in the last two decades where C is holding the 1st and 2nd rank for the last 30 years. Python has come a long way in the last two decades i.e. 24th in 1999 to 3rd in 2019. If someone merges the C and C++ then it would hold the 1st positions forever.

This is image title

In the new languages (post-2000), Rust moved up in ranking i.e. from 33rd to 28th, and Julia from 50th to 39th. It is also interesting to note that Kotlin doesn’t seem to come closer to the top 20.

Popularity of Programming Language (PYPL) Index

The PYPL index is created by analyzing how often language tutorials are searched on Google. The more a language tutorial is searched, the more popular the language is assumed to be. It is a leading indicator. The raw data comes from Google Trends.

Below Figure verifies that the top 3 languages are Python, Java, and JavaScript. C#, PHP, C/C++ also secure top position, this trend is again similar to stack-overflow, and TIOBE index.

This is image title

Above Figure indicates that among new programming Language i.e. post 2000 Kotlin, Go, Rust, and Julia is moving up in the ranking.

This is image title

Job Market and Salary

Salary depends upon the geographical area and demand of the products, a programming language based salary comparison is just a tool to predict or estimate the salary trend. We have summarized salary based on programming language from popular survey i.e. Dice salary survey 2018 and Stack-overflow survey 2018 and 2019.

This is image title

From the above table, it is very clear from both survey that Go/Golang is a very high paid job in the market and even stands 1st rank in a high paid job in stack-overflow 2019 survey and Dice Salary Survey 2018.

Language Predictability

So, as closing remarks, It is easy to predict a language trend but choosing only one language to learn is a really difficult choice and totally depend upon the individual choice and their future plans, for example, if you want to work in Web Development you can’t afford neglecting Javascript, if you want to work with Apple’s products you can’t neglect Swift now, if your taste is in system-level programming then C and C++ is your friend, Python makes you run faster in many domains and currently darling in Data science. You see each language takes you on a different journey. Choose your destination and then drive with the language of that path.

You may also like: Programming Languages - Trend Predictions in 2020 and Next Years.

We’ll love to know your opinion. What is the Best Programming Language for you?

Thank for reading! If you enjoyed this article, please share it with others who may enjoy it as well.!

Build a CMS with Laravel and Vue

Build a CMS with Laravel and Vue

Build a CMS with Laravel and Vue - Part 1: Setting up

The birth of the internet has since redefined content accessibility for the better, causing a distinct rise in content consumption across the globe. The average user of the internet consumes and produces some form of content formally or informally.

An example of an effort at formal content creation is when an someone makes a blog post about their work so that a targeted demographic can easily find their website. This type of content is usually served and managed by a CMS (Content Management System). Some popular ones are WordPress, Drupal, and SilverStripe.

A CMS helps content creators produce content in an easily consumable format. In this tutorial series, we will consider how to build a simple CMS from scratch using Laravel and Vue.

Our CMS will be able to make new posts, update existing posts, delete posts that we do not need anymore, and also allow users make comments to posts which will be updated in realtime using Pusher. We will also be able to add featured images to posts to give them some visual appeal.

When we are done, we will be able to have a CMS that looks like this:


Prerequisites

To follow along with this series, a few things are required:

  • Basic knowledge of PHP.
  • Basic knowledge of the Laravel framework.
  • Basic knowledge of JavaScript (ES6 syntax).
  • Basic knowledge of Vue.
  • Postman installed on your machine.
The source code for this project is available here on GitHub.

Installing the Laravel CLI

If you already have the Laravel CLI installed on your machine, please skip this section.

The first thing we need to do is install the Laravel CLI, and the Laravel dependencies. The CLI will be instrumental in creating new Laravel projects whenever we need to create one. Laravel requires PHP and a few other tools and extensions, so we need to first install these first before installing the CLI.

Here’s a list of the dependencies as documented on the official Laravel documentation:

Let’s install them one at a time.


Installing PHP

An equivalent for Windows users could be to download and install XAMPP here. XAMPP comes with a UI for installing most of the other things you have to install manually below. Hence, Windows users may skip the next few steps until the Installing Composer sub-heading.

Open a fresh instance of the terminal and paste the following command:

<pre class="ql-syntax" spellcheck="false"> # Linux Users $ sudo apt-get install php7.2
# Mac users
$ brew install php72

</pre>

As at the time of writing this article, PHP 7.2 is the latest stable version of PHP so the command above installs it on your machine.

On completion, you can check that PHP has been installed to your machine with the following command:

<pre class="ql-syntax" spellcheck="false"> $ php -v

</pre>

Installing the Mbstring extension

To install the mbstring extension for PHP, paste the following command in the open terminal:

<pre class="ql-syntax" spellcheck="false"> # Linux users
$ sudo apt-get install php7.2-mbstring

# Mac users
# You don't have to do anything as it is installed automatically.

</pre>

To check if the mbstring extension has been installed successfully, you can run the command below:

<pre class="ql-syntax" spellcheck="false"> $ php -m | grep mbstring

</pre>

Installing the XML PHP extension

To install the XML extension for PHP, paste the following command in the open terminal:

<pre class="ql-syntax" spellcheck="false"> # Linux users
$ sudo apt-get install php-xml

# Mac users
# You don't have to do anything as it is installed automatically.

</pre>

To check if the xml extension has been installed successfully, you can run the command below:

<pre class="ql-syntax" spellcheck="false"> $ php -m | grep xml

</pre>

Installing the ZIP PHP extension

To install the zip extension for PHP, paste the following command in your terminal:

<pre class="ql-syntax" spellcheck="false"> # Linux users
$ sudo apt-get install php7.2-zip

# Mac users
# You don't have to do anything as it is installed automatically.

</pre>

To check if the zip extension has been installed successfully, you can run the command below:

<pre class="ql-syntax" spellcheck="false"> $ php -m | grep zip

</pre>

Installing curl

Windows users may need to download curl from here.

To install curl, paste the following command in your terminal:

<pre class="ql-syntax" spellcheck="false"> # Linux users
$ sudo apt-get install curl

# Mac users using Homebrew (https://brew.sh)
$ brew install curl

</pre>

To verify that curl has been installed successfully, run the following command:

<pre class="ql-syntax" spellcheck="false"> $ curl --version

</pre>

Installing Composer

Windows users can download and install Composer here. After the installation is complete, start a fresh instance of the command prompt as administrator and run this command anytime you need composer:
php composer.phar

Now that we have curl installed on our machine, let’s pull in Composer with this command:

<pre class="ql-syntax" spellcheck="false"> $ curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer

</pre>

For us to run Composer in the future without calling sudo, we may need to change the permission, however you should only do this if you have problems installing packages:

<pre class="ql-syntax" spellcheck="false"> $ sudo chown -R $USER ~/.composer/

</pre>

Installing the Laravel installer

At this point, we can already create a new Laravel project using Composer’s create-project command, which looks like this:

<pre class="ql-syntax" spellcheck="false"> $ composer create-project --prefer-dist laravel/laravel project-name

</pre>

But we will go one step further and install the Laravel installer using composer:

<pre class="ql-syntax" spellcheck="false"> $ composer global require "laravel/installer"

</pre>

If you are on Windows, you may need to run the previous command in an advanced terminal such as PowerShell or the Gitbash terminal. Windows users can also skip the steps below.

After the installation, we will need to add the PATH to the bashrc file so that our terminal can recognize the laravel command:

<pre class="ql-syntax" spellcheck="false"> $ echo 'export PATH="$HOME/.composer/vendor/bin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc

</pre>

Creating the CMS project

Now that we have the official Laravel CLI installed on our machine, let’s create our CMS project using the installer. In your terminal window, cd to the project directory you want to create the project in and run the following command:

<pre class="ql-syntax" spellcheck="false"> $ laravel new cms

</pre>

At the time of writing this article, the latest version of Laravel is 5.6

We will navigate into the project directory and serve the application using PHP’s web server:

<pre class="ql-syntax" spellcheck="false"> $ cd cms
$ php artisan serve

</pre>

Now, when we visit http://127.0.0.1:8000/, we will see the default Laravel template:


Setting up the database

In this series, we will be using MySQL as our database system so a prerequisite for this section is that you have MySQL installed on your machine.

You can follow the steps below to install and configure MySQL:

  • Linux users - check here for a detailed guide.
  • Mac users, you can just run the command brew install mysql.
  • Windows users who installed XAMPP, as suggested earlier, do not need to install MySQL as it comes preinstalled.

You will also need a special driver that makes it possible for PHP to work with MySQL, you can install it with this command:

<pre class="ql-syntax" spellcheck="false"> # Linux users
$ sudo apt-get install php7.2-mysql

# Mac Users
# You don't have to do anything as it is installed automatically.

</pre>

Load the project directory in your favorite text editor and there should be a .env file in the root of the folder. This is where Laravel stores its environment variables.

Create a new MySQL database and call it laravelcms. In the .env file, update the database configuration keys as seen below:

<pre class="ql-syntax" spellcheck="false"> DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravelcms
DB_USERNAME=YourUsername
DB_PASSWORD=YourPassword

</pre>

Replace the DB_USERNAME and DB_PASSWORD with your MySQL database credentials.

Setting up user roles

Like most content management systems, we are going to have a user role system so that our blog can have multiple types of users; the admin and regular user. The admin should be able to create a post and perform other CRUD operations on a post. The regular user, on the other hand, should be able to view and comment on a post.

For us to implement this functionality, we need to implement user authentication and add a simple role authorization system.


Setting up user authentication

Laravel provides user authentication out of the box, which is great, and we can key into the feature by running a single command:

<pre class="ql-syntax" spellcheck="false"> $ php artisan make:auth

</pre>

The above will create all that’s necessary for authentication in our application so we do not need to do anything extra.


Setting up role authorization

We need a model for the user roles so let’s create one and an associated migration file:

<pre class="ql-syntax" spellcheck="false"> $ php artisan make:model Role -m

</pre>

In the database/migrations folder, find the newly created migration file and update the CreateRolesTable class with this snippet:

<pre class="ql-syntax" spellcheck="false"> <?php // File: ./database/migrations/*_create_roles_table.php

// [...]

class CreateRolesTable extends Migration
{
    public function up()
    {
        Schema::create('roles', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;string('name');
            $table-&gt;string('description');
            $table-&gt;timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('roles');
    }
}

</pre>

We intend to create a many-to-many relationship between the User and Role models so let’s add a relationship method on both models.

Open the User model and add the following method:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/User.php
public function roles()
{
return $this->belongsToMany(Role::class);
}
</pre>

Open the Role model and include the following method:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Role.php
public function users()
{
return $this->belongsToMany(User::class);
}
</pre>

We are also going to need a pivot table to associate each user with a matching role so let’s create a new migration file for the role_user table:

<pre class="ql-syntax" spellcheck="false"> $ php artisan make:migration create_role_user_table

</pre>

In the database/migrations folder, find the newly created migration file and update the CreateRoleUserTable class with this snippet:

<pre class="ql-syntax" spellcheck="false"> // File: ./database/migrations/*_create_role_user_table.php
<?php

// [...]

class CreateRoleUserTable extends Migration
{

    public function up()
    {
        Schema::create('role_user', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;integer('role_id')-&gt;unsigned();
            $table-&gt;integer('user_id')-&gt;unsigned();
        });
    }

    public function down()
    {
        Schema::dropIfExists('role_user');
    }
}

</pre>

Next, let’s create seeders that will populate the users and roles tables with some data. In your terminal, run the following command to create the database seeders:

<pre class="ql-syntax" spellcheck="false"> $ php artisan make:seeder RoleTableSeeder
$ php artisan make:seeder UserTableSeeder

</pre>

In the database/seeds folder, open the RoleTableSeeder.php file and replace the contents with the following code:

<pre class="ql-syntax" spellcheck="false"> // File: ./database/seeds/RoleTableSeeder.php
<?php

use App\Role;
use Illuminate\Database\Seeder;

class RoleTableSeeder extends Seeder
{
    public function run()
    {
        $role_regular_user = new Role;
        $role_regular_user-&gt;name = 'user';
        $role_regular_user-&gt;description = 'A regular user';
        $role_regular_user-&gt;save();

        $role_admin_user = new Role;
        $role_admin_user-&gt;name = 'admin';
        $role_admin_user-&gt;description = 'An admin user';
        $role_admin_user-&gt;save();
    }
}

</pre>

Open the UserTableSeeder.php file and replace the contents with the following code:

<pre class="ql-syntax" spellcheck="false"> // File: ./database/seeds/UserTableSeeder.php
<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use App\User;
use App\Role;

class UserTableSeeder extends Seeder
{

    public function run()
    {
        $user = new User;
        $user-&gt;name = 'Samuel Jackson';
        $user-&gt;email = '[email protected]';
        $user-&gt;password = bcrypt('samuel1234');
        $user-&gt;save();
        $user-&gt;roles()-&gt;attach(Role::where('name', 'user')-&gt;first());

        $admin = new User;
        $admin-&gt;name = 'Neo Ighodaro';
        $admin-&gt;email = '[email protected]';
        $admin-&gt;password = bcrypt('neo1234');
        $admin-&gt;save();
        $admin-&gt;roles()-&gt;attach(Role::where('name', 'admin')-&gt;first());
    }
}

</pre>

We also need to update the DatabaseSeeder class. Open the file and update the run method as seen below:

<pre class="ql-syntax" spellcheck="false"> // File: ./database/seeds/DatabaseSeeder.php
<?php

// [...]

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this-&gt;call([
            RoleTableSeeder::class, 
            UserTableSeeder::class,
        ]);
    }
}

</pre>

Next, let’s update the User model. We will be adding a checkRoles method that checks what role a user has. We will return a 404 page where a user doesn’t have the expected role for a page. Open the User model and add these methods:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/User.php
public function checkRoles($roles)
{
if ( ! is_array($roles)) {
$roles = [$roles];
}

    if ( ! $this-&gt;hasAnyRole($roles)) {
        auth()-&gt;logout();
        abort(404);
    }
}

public function hasAnyRole($roles): bool
{
    return (bool) $this-&gt;roles()-&gt;whereIn('name', $roles)-&gt;first();
}

public function hasRole($role): bool
{
    return (bool) $this-&gt;roles()-&gt;where('name', $role)-&gt;first();
}

</pre>

Let’s modify the RegisterController.php file in the Controllers/Auth folder so that a default role, the user role, is always attached to a new user at registration.

Open the RegisterController and update the create action with the following code:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/Auth/RegisterController.php
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);

    $user-&gt;roles()-&gt;attach(\App\Role::where('name', 'user')-&gt;first());

    return $user;
}

</pre>

Now let’s migrate and seed the database so that we can log in with the sample accounts. To do this, run the following command in your terminal:

<pre class="ql-syntax" spellcheck="false"> $ php artisan migrate:fresh --seed

</pre>

In order to test that our roles work as they should, we will make an update to the HomeController.php file. Open the HomeController and update the index method as seen below:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/HomeController.php
public function index(Request $request)
{
$request->user()->checkRoles('admin');

    return view('home');
}

</pre>

Now, only administrators should be able to see the dashboard. In a more complex application, we would use a middleware to do this instead.

We can test that this works by serving the application and logging in both user accounts; Samuel Jackson and Neo Ighodaro.

Remember that in our UserTableSeeder.php file, we defined Samuel as a regular user and Neo as an admin, so Samuel should see a 404 error after logging in and Neo should be able to see the homepage.


Testing the application

Let’s serve the application with this command:

<pre class="ql-syntax" spellcheck="false"> $ php artisan serve

</pre>

When we try logging in with Samuel’s credentials, we should see this:

On the other hand, we will get logged in with Neo’s credentials because he has an admin account:

We will also confirm that whenever a new user registers, he is assigned a role and it is the role of a regular user. We will create a new user and call him Greg, he should see a 404 error right after:

It works just as we wanted it to, however, it doesn’t really make any sense for us to redirect a regular user to a 404 page. Instead, we will edit the HomeController so that it redirects users based on their roles, that is, it redirects a regular user to a regular homepage and an admin to an admin dashboard.

Open the HomeController.php file and update the index method as seen below:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/HomeController.php
public function index(Request $request)
{
if ($request->user()->hasRole('user')) {
return redirect('/');
}

    if ($request-&gt;user()-&gt;hasRole('admin')){
        return redirect('/admin/dashboard');
    }
}

</pre>

If we serve our application and try to log in using the admin account, we will hit a 404 error because we do not have a controller or a view for the admin/dashboard route. In the next article, we will start building the basic views for the CMS.


Conclusion

In this tutorial, we learned how to install a fresh Laravel app on our machine and pulled in all the needed dependencies. We also learned how to configure the Laravel app to work with a MySQL database. We also created our models and migrations files and seeded the database using database seeders.

In the next part of this series, we will start building the views for the application.

The source code for this project is available on Github.


Build a CMS with Laravel and Vue - Part 2: Implementing posts

In the previous part of this series, we set up user authentication and role authorization but we didn’t create any views for the application yet. In this section, we will create the Post model and start building the frontend for the application.

Our application allows different levels of accessibility for two kinds of users; the regular user and admin. In this chapter, we will focus on building the view that the regular users are permitted to see.

Before we build any views, let’s create the Post model as it is imperative to rendering the view.

The source code for this project is available here on GitHub.

Prerequisites

To follow along with this series, a few things are required:

  • Basic knowledge of PHP.
  • Basic knowledge of the Laravel framework.
  • Basic knowledge of JavaScript (ES6 syntax).
  • Basic knowledge of Vue.
  • Postman installed on your machine.

Setting up the Post model

We will create the Post model with an associated resource controller and a migration file using this command:

<pre class="ql-syntax" spellcheck="false"> $ php artisan make:model Post -mr

</pre>

We added the r flag because we want the controller to be a resource controller. The m flag will generate a migration for the model.

Let’s navigate into the database/migrations folder and update the CreatePostsTable class that was generated for us:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/database/migrations/*_create_posts_table.php
<?php

// [...]

class CreatePostsTable extends Migration
{
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table-&gt;increments('id');
            $table-&gt;integer('user_id')-&gt;unsigned();
            $table-&gt;string('title');
            $table-&gt;text('body');
            $table-&gt;binary('image')-&gt;nullable();
            $table-&gt;timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

</pre>

We included a user_id property because we want to create a relationship between the User and Post models. A Post also has an image field, which is where its associated image’s address will be stored.


Creating a database seeder for the Post table

We will create a new seeder file for the posts table using this command:

<pre class="ql-syntax" spellcheck="false"> $ php artisan make:seeder PostTableSeeder

</pre>

Let’s navigate into the database/seeds folder and update the PostTableSeeder.php file:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/database/seeds/PostsTableSeeder.php
<?php

use App\Post;
use Illuminate\Database\Seeder;

class PostTableSeeder extends Seeder
{
    public function run()
    {
        $post = new Post;
        $post-&gt;user_id = 2;
        $post-&gt;title = "Using Laravel Seeders";
        $post-&gt;body = "Laravel includes a simple method of seeding your database with test data using seed classes. All seed classes are stored in the database/seeds directory. Seed classes may have any name you wish, but probably should follow some sensible convention, such as UsersTableSeeder, etc. By default, a DatabaseSeeder class is defined for you. From this class, you may use the  call method to run other seed classes, allowing you to control the seeding order.";
        $post-&gt;save();

        $post = new Post;
        $post-&gt;user_id = 2;
        $post-&gt;title = "Database: Migrations";
        $post-&gt;body = "Migrations are like version control for your database, allowing your team to easily modify and share the application's database schema. Migrations are typically paired with Laravel's schema builder to easily build your application's database schema. If you have ever had to tell a teammate to manually add a column to their local database schema, you've faced the problem that database migrations solve.";
        $post-&gt;save();
    }
}

</pre>

When we run this seeder, it will create two new posts and assign both of them to the admin user whose ID is 2. We are attaching both posts to the admin user because the regular users are only allowed to view posts and make comments; they can’t create a post.

Let’s open the DatabaseSeeder and update it with the following code:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/database/seeds/DatabaseSeeder.php
<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this-&gt;call([
            RoleTableSeeder::class,
            UserTableSeeder::class,
            PostTableSeeder::class,
        ]);
    }
}

</pre>

We created the RoleTableSeeder and UserTableSeeder files in the previous chapter.

We will use this command to migrate our tables and seed the database:

<pre class="ql-syntax" spellcheck="false"> $ php artisan migrate:fresh --seed

</pre>

Defining the relationships

Just as we previously created a many-to-many relationship between the User and Role models, we need to create a different kind of relationship between the Post and User models.

We will define the relationship as a one-to-many relationship because a user will have many posts but a post will only ever belong to one user.

Open the User model and include the method below:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/User.php
public function posts()
{
return $this->hasMany(Post::class);
}
</pre>

Open the Post model and include the method below:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Post.php
public function user()
{
return $this->belongsTo(User::class);
}
</pre>

Setting up the routes

At this point in our application, we do not have a front page with all the posts listed. Let’s create so anyone can see all of the created posts. Asides from the front page, we also need a single post page in case a user needs to read a specific post.

Let’s include two new routes to our routes/web.php file:

  • The first route will match requests to the root of our application and will be handled by the [email protected] action:
<pre class="ql-syntax" spellcheck="false"> Route::get('/', '[email protected]');
</pre>
In the routes/web.php file, there will already be a route definition for the / address, you will have to replace it with the new route definition above.
  • The second route will handle requests for specific Post items and will be handled by the [email protected] action:
<pre class="ql-syntax" spellcheck="false"> Route::get('/posts/{post}', '[email protected]');
</pre>

With these two new routes added, here’s what the routes/web.php file should look like this:

<pre class="ql-syntax" spellcheck="false"> // File: ./routes/web.php
<?php

Auth::routes();
Route::get('/posts/{post}', '[email protected]');
Route::get('/home', '[email protected]')-&gt;name('home');
Route::get('/', '[email protected]');

</pre>

Setting up the Post controller

In this section, we want to define the handler action methods that we registered in the routes/web.php file so that our application know how to render the matching views.

First, let’s add the all() method:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/PostController.php
public function all()
{
return view('landing', [
'posts' => Post::latest()->paginate(5)
]);
}
</pre>

Here, we want to retrieve five created posts per page and send to the landing view. We will create this view shortly.

Next, let’s add the single() method to the controller:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/PostController.php
public function single(Post $post)
{
return view('single', compact('post'));
}
</pre>

In the method above, we used a feature of Laravel named route model binding to map the URL parameter to a Post instance with the same ID. We are returning a single view, which we will create shortly. This will be the view for the single post page.


Building our views

Laravel uses a templating engine called Blade for its frontend. We will use Blade to build these parts of the frontend before switching to Vue in the next chapter.

Navigate to the resources/views folder and create two new Blade files:

  1. landing.blade.php
  2. single.blade.php

These are the files that will load the views for the landing page and single post page. Before we start writing any code in these files, we want to create a simple layout template that our page views can use as a base.

In the resources/views/layouts folder, create a Blade template file and call it master.blade.php. This is where we will define the inheritable template for our single and landing pages.

Open the master.blade.php file and update it with this code:

<pre class="ql-syntax" spellcheck="false"> <!-- File: ./resources/views/layouts/master.blade.php -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="Neo Ighodaro">
<title>LaravelCMS</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<style>
body {
padding-top: 54px;
}
@media (min-width: 992px) {
body {
padding-top: 56px;
}
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="/">LaravelCMS</a>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
@if (Route::has('login'))
@auth
<li class="nav-item">
<a class="nav-link" href="{{ url('/home') }}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
Log out
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
@csrf
</form>
</li>
@else
<li class="nav-item">
<a class="nav-link" href="{{ route('login') }}">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('register') }}">Register</a>
</li>
@endauth
@endif
</ul>
</div>
</div>
</nav>

    &lt;div id="app"&gt;
        @yield('content')
    &lt;/div&gt;

    &lt;footer class="py-5 bg-dark"&gt;
      &lt;div class="container"&gt;
        &lt;p class="m-0 text-center text-white"&gt;Copyright &amp;copy; LaravelCMS 2018&lt;/p&gt;
      &lt;/div&gt;
    &lt;/footer&gt;
  &lt;/body&gt;
&lt;/html&gt;

</pre>

Now we can inherit this template in the landing.blade.php file, open it and update it with this code:

<pre class="ql-syntax" spellcheck="false"> {{-- File: ./resources/views/landing.blade.php --}}
@extends('layouts.master')

@section('content')
&lt;div class="container"&gt;
  &lt;div class="row align-items-center"&gt;
    &lt;div class="col-md-8 mx-auto"&gt;
      &lt;h1 class="my-4 text-center"&gt;Welcome to the Blog &lt;/h1&gt;

      @foreach ($posts as $post)
      &lt;div class="card mb-4"&gt;
        &lt;img class="card-img-top" src=" {!! !empty($post-&gt;image) ? '/uploads/posts/' . $post-&gt;image :  'http://placehold.it/750x300' !!} " alt="Card image cap"&gt;
        &lt;div class="card-body"&gt;
          &lt;h2 class="card-title text-center"&gt;{{ $post-&gt;title }}&lt;/h2&gt;
          &lt;p class="card-text"&gt; {{ str_limit($post-&gt;body, $limit = 280, $end = '...') }} &lt;/p&gt;
          &lt;a href="/posts/{{ $post-&gt;id }}" class="btn btn-primary"&gt;Read More &amp;rarr;&lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="card-footer text-muted"&gt;
          Posted {{ $post-&gt;created_at-&gt;diffForHumans() }} by
          &lt;a href="#"&gt;{{ $post-&gt;user-&gt;name }} &lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      @endforeach

    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
@endsection

</pre>

Let’s do the same with the single.blade.php file, open it and update it with this code:

<pre class="ql-syntax" spellcheck="false"> {{-- File: ./resources/views/single.blade.php --}}
@extends('layouts.master')

@section('content')
&lt;div class="container"&gt;
  &lt;div class="row"&gt;
    &lt;div class="col-lg-10 mx-auto"&gt;
      &lt;h3 class="mt-4"&gt;{{ $post-&gt;title }} &lt;span class="lead"&gt; by &lt;a href="#"&gt; {{ $post-&gt;user-&gt;name }} &lt;/a&gt;&lt;/span&gt; &lt;/h3&gt;
      &lt;hr&gt;
      &lt;p&gt;Posted {{ $post-&gt;created_at-&gt;diffForHumans() }} &lt;/p&gt;
      &lt;hr&gt;
      &lt;img class="img-fluid rounded" src=" {!! !empty($post-&gt;image) ? '/uploads/posts/' . $post-&gt;image :  'http://placehold.it/750x300' !!} " alt=""&gt;
      &lt;hr&gt;
      &lt;p class="lead"&gt;{{ $post-&gt;body }}&lt;/p&gt;
      &lt;hr&gt;
      &lt;div class="card my-4"&gt;
        &lt;h5 class="card-header"&gt;Leave a Comment:&lt;/h5&gt;
        &lt;div class="card-body"&gt;
          &lt;form&gt;
            &lt;div class="form-group"&gt;
              &lt;textarea class="form-control" rows="3"&gt;&lt;/textarea&gt;
            &lt;/div&gt;
            &lt;button type="submit" class="btn btn-primary"&gt;Submit&lt;/button&gt;
          &lt;/form&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
@endsection

</pre>

Testing the application

We can test the application to see that things work as we expect. When we serve the application, we expect to see a landing page and a single post page. We also expect to see two posts because that’s the number of posts we seeded into the database.

We will serve the application using this command:

<pre class="ql-syntax" spellcheck="false"> $ php artisan serve

</pre>

We can visit this address to see the application:

We have used simple placeholder images here because we haven’t built the admin dashboard that allows CRUD operations to be performed on posts.

In the coming chapters, we will add the ability for an admin to include a custom image when creating a new post.


Conclusion

In this chapter, we created the Post model and defined a relationship on it to the User model. We also built the landing page and single page.

In the next part of this series, we will develop the API that will be the medium for communication between the admin user and the post items.

The source code for this project is available here on Github.


Build a CMS with Laravel and Vue - Part 3: Building an API

In the previous part of this series, we initialized the posts resource and started building the frontend of the CMS. We designed the front page that shows all the posts and the single post page using Laravel’s templating engine, Blade.

In this part of the series, we will start building the API for the application. We will create an API for CRUD operations that an admin will perform on posts and we will test the endpoints using Postman.

The source code for this project is available here on GitHub.

Prerequisites

To follow along with this series, a few things are required:

  • Basic knowledge of PHP.
  • Basic knowledge of the Laravel framework.
  • Basic knowledge of JavaScript (ES6 syntax).
  • Basic knowledge of Vue.
  • Postman installed on your machine.

Building the API using Laravel’s API resources

The Laravel framework makes it very easy to build APIs. It has an API resources feature that we can easily adopt in our project. You can think of API resources as a transformation layer between Eloquent models and the JSON responses that will be sent back by our API.


Allowing mass assignment on specified fields

Since we are going to be performing CRUD operations on the posts in the application, we have to explicitly specify that it’s permitted for some fields to be mass-assigned data. For security reasons, Laravel prevents mass assignment of data to model fields by default.

Open the Post.php file and include this line of code:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Post.php
protected $fillable = ['user_id', 'title', 'body', 'image'];
</pre>

Defining API routes

We will use the apiResource()method to generate only API routes. Open the routes/api.php file and add the following code:

<pre class="ql-syntax" spellcheck="false"> // File: ./routes/api.php
Route::apiResource('posts', 'PostController');

</pre>

Because we will be handling the API requests on the /posts URL using the PostController, we will have to include some additional action methods in our post controller.

Creating the Post resource

At the beginning of this section, we already talked about what Laravel’s API resources are. Here, we create a resource class for our Post model. This will enable us to retrieve Post data and return formatted JSON format.

To create a resource class for our Post model run the following command in your terminal:

<pre class="ql-syntax" spellcheck="false"> $ php artisan make:resource PostResource

</pre>

A new PostResource.php file will be available in the app/Http/Resources directory of our application. Open up the PostResource.php file and replace the toArray() method with the following:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Resources/PostResource.php
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'body' => $this->body,
'image' => $this->image,
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at,
];
}
</pre>

The job of this toArray() method is to convert our P``ost resource into an array. As seen above, we have specified the fields on our Post model, which we want to be returned as JSON when we make a request for posts.

We are also explicitly casting the dates, created_at and update_at, to strings so that they would be returned as date strings. The dates are normally an instance of Carbon.

Now that we have created a resource class for our Post model, we can start building the API’s action methods in our PostController and return instances of the PostResource where we want.


Adding the action methods to the Post controller

The usual actions performed on a post include the following:

  1. Create - the process of creating a new post.
  2. Read - the process of reading one or more posts.
  3. Update - the process of updating an already published post.
  4. Delete - the process of deleting a post.

In the last article, we already implemented a kind of ‘Read’ functionality when we defined the all and single methods. These methods allow users to browse through posts on the homepage.

In this section, we will define the methods that will resolve our API requests for creating, reading, updating and deleting posts.

The first thing we want to do is import the PostResource class at the top of the PostController.php file:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/PostController.php
use App\Http\Resources\PostResource;
</pre>
Because we created the PostController as a resource controller, we already have the resource action methods included for us in the PostController.php file, we will be updating them with fitting snippets of code.

Building the handler action for the create operation

In the PostController update the store() action method with the code snippet below. It will allow us to validate and create a new post:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/PostController.php
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required',
'body' => 'required',
'user_id' => 'required',
'image' => 'required|mimes:jpeg,png,jpg,gif,svg',
]);

    $post = new Post;

    if ($request-&gt;hasFile('image')) {
        $image = $request-&gt;file('image');
        $name = str_slug($request-&gt;title).'.'.$image-&gt;getClientOriginalExtension();
        $destinationPath = public_path('/uploads/posts');
        $imagePath = $destinationPath . "/" . $name;
        $image-&gt;move($destinationPath, $name);
        $post-&gt;image = $name;
    }

    $post-&gt;user_id = $request-&gt;user_id;
    $post-&gt;title = $request-&gt;title;
    $post-&gt;body = $request-&gt;body;
    $post-&gt;save();

    return new PostResource($post);
}

</pre>

Here’s a breakdown of what this method does:

  1. Receives a new request.
  2. Validates the request.
  3. Creates a new post.
  4. Returns the post as a PostResource, which in turn returns a JSON formatted response.

Building the handler action for the read operations

What we want here is to be able to read all the created posts or a single post. This is possible because the apiResource() method defines the API routes using standard REST rules.

This means that a GET request to this address, http://127.0.0.1:800/api/posts, should be resolved by the index() action method. Let’s update the index method with the following code:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/PostController.php
public function index()
{
return PostResource::collection(Post::latest()->paginate(5));
}
</pre>

This method will allow us to return a JSON formatted collection of all of the stored posts. We also want to paginate the response as this will allow us to create a better view on the admin dashboard.

Following the RESTful conventions as we discussed above, a GET request to this address, http://127.0.0.1:800/api/posts/id, should be resolved by the show() action method. Let’s update the method with the fitting snippet:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/PostController.php
public function show(Post $post)
{
return new PostResource($post);
}
</pre>

Awesome, now this method will return a single instance of a post resource upon API query.


Building the handler action for the update operation

Next, let’s update the update() method in the PostController class. It will allow us to modify an existing post:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/PostController.php
public function update(Request $request, Post $post)
{
$this->validate($request, [
'title' => 'required',
'body' => 'required',
]);

    $post-&gt;update($request-&gt;only(['title', 'body']));

    return new PostResource($post);
}

</pre>

This method receives a request and a post id as parameters, then we use route model binding to resolve the id into an instance of a Post. First, we validate the $request attributes, then we update the title and body fields of the resolved post.


Building the handler action for the delete operation

Let’s update the destroy() method in the PostController class. This method will allow us to remove an existing post:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/PostController.php
public function destroy(Post $post)
{
$post->delete();

    return response()-&gt;json(null, 204);
}

</pre>

In this method, we resolve the Post instance, then delete it and return a 204 response code.

Our methods are complete. We have a method to handle our CRUD operations, however, we haven’t built the frontend for the admin dashboard.

At the end of the second article, we defined the [email protected]() action method like this:

<pre class="ql-syntax" spellcheck="false"> public function index(Request $request)
{
if ($request->user()->hasRole('user')) {
return view('home');
}

    if ($request-&gt;user()-&gt;hasRole('admin')) {
        return redirect('/admin/dashboard');
    }
}

</pre>

This allowed us to redirect regular users to the view home, and admin users to the URL /admin/dashboard. At this point in this series, a visit to /admin/dashboard will fail because we have neither defined it as a route with a handler Controller nor built a view for it.

Let’s create the AdminController with this command:

<pre class="ql-syntax" spellcheck="false"> $ php artisan make:controller AdminController

</pre>

We will add the /admin/ route to our routes/web.php file:

<pre class="ql-syntax" spellcheck="false"> Route::get('/admin/{any}', '[email protected]')->where('any', '.*');
</pre>
Note that we wrote /admin/{any} here because we intend to serve every page of the admin dashboard using the Vue router. When we start building the admin dashboard in the next article, we will let Vue handle all the routes of the /admin pages.

Let’s update the AdminController.php file to use the auth middleware and include an index() action method:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/AdminController.php
<?php

namespace App\Http\Controllers;

class AdminController extends Controller
{
    public function __construct()
    {
        $this-&gt;middleware('auth');
    }

    public function index()
    {
        if (request()-&gt;user()-&gt;hasRole('admin')) {
            return view('admin.dashboard');
        }

        if (request()-&gt;user()-&gt;hasRole('user')) {
            return redirect('/home');
        }
    }
}

</pre>

In the index()action method, we included a snippet that will ensure that only admin users can visit the admin dashboard and perform CRUD operations on posts.

We will not start building the admin dashboard in this article but will test that our API works properly. We will use Postman to make requests to the application.


Testing the application

Let’s test that our API works as expected. We will, first of all, serve the application using this command:

<pre class="ql-syntax" spellcheck="false"> $ php artisan serve

</pre>

We can visit http://localhost:8000 to see our application and there should be exactly two posts available; these are the posts we seeded into the database during the migration:

When testing with Postman always set the Content-Type header to application/json.

Now let’s create a new post over the API interface using Postman. Send a POST request as seen below:

Now let’s update this post we just created. In Postman, we will pass only the title and body fields to a PUT request.

To make it easy, you can just copy the payload below and use the raw request data type for the Body:

<pre class="ql-syntax" spellcheck="false"> {
"title": "We made an edit to the Post on APIs",
"body": "To a developer, 'What's an API?' might be a straightforward - if not exactly simple - question. But to anyone who doesn't have experience with code. APIs can come across as confusing or downright intimidating."
}

</pre>

We could have used the PATCH method to make this update, the PUT and PATCH HTTP verbs both work well for editing an already existing item.

Finally, let’s delete the post using Postman:

We are sure the post is deleted because the response status is 204 No Content as we specified in the PostController.


Conclusion

In this chapter, we learned about Laravel’s API resources and we created a resource class for the Post model. We also used the apiResources() method to generate API only routes for our application. We wrote the methods to handle the API operations and tested them using Postman.

In the next part, we will build the admin dashboard and develop the logic that will enable the admin user to manage posts over the API.

The source code for this project is available here on Github.


Build a CMS with Laravel and Vue - Part 4: Building the dashboard

In the last article of this series, we built the API interface and used Laravel API resources to return neatly formatted JSON responses. We tested that the API works as we defined it to using Postman.

In this part of the series, we will start building the admin frontend of the CMS. This is the first part of the series where we will integrate Vue and explore Vue’s magical abilities.

When we are done with this part, our application will have some added functionalities as seen below:

The source code for this project is available here on GitHub.

Prerequisites

To follow along with this series, a few things are required:

  • Basic knowledge of PHP.
  • Basic knowledge of the Laravel framework.
  • Basic knowledge of JavaScript (ES6 syntax).
  • Basic knowledge of Vue.

Building the frontend

Laravel ships with Vue out of the box so we do not need to use the Vue-CLI or reference Vue from a CDN. This makes it possible for us to have all of our application, the frontend, and backend, in a single codebase.

Every newly created instance of a Laravel installation has some Vue files included by default, we can see these files when we navigate into the resources/assets/js/components folder.


Setting up Vue and VueRouter

Before we can start using Vue in our application, we need to first install some dependencies using NPM. To install the dependencies that come by default with Laravel, run the command below:

<pre class="ql-syntax" spellcheck="false"> $ npm install

</pre>

We will be managing all of the routes for the admin dashboard using vue-router so let’s pull it in:

<pre class="ql-syntax" spellcheck="false"> $ npm install --save vue-router

</pre>

When the installation is complete, the next thing we want to do is open the resources/assets/js/app.js file and replace its contents with the code below:

<pre class="ql-syntax" spellcheck="false"> // File: ./resources/assets/js/app.js
require('./bootstrap');

import Vue from 'vue'
import VueRouter from 'vue-router'
import Homepage from './components/Homepage'
import Read from './components/Read'

Vue.use(VueRouter)

const router = new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/admin/dashboard',
            name: 'read',
            component: Read,
            props: true
        },
    ],
});

const app = new Vue({
    el: '#app',
    router,
    components: { Homepage },
});

</pre>

In the snippet above, we imported the VueRouter and added it to the Vue application. We also imported a Homepage and a Read component. These are the components where we will write our markup so let’s create both files.

Open the resources/assets/js/components folder and create four files:

  1. Homepage.vue - this will be the parent component for the admin dashboard frontend.
  2. Read.vue - this will be component that displays all the available posts on the admin dashboard.
  3. Create.vue - this will be the component where an admin user can create a new post.
  4. Update.vue - this will be the component that displays the view where an admin user can update an existing post.
Note that we didn’t create a component file for the delete operation, this is because it is going to be possible to delete a post from the Read component. There is no need for a view.

In the resources/assets/js/app.js file, we defined a routes array and in it, we registered a read route. During render time, this route’s path will be mapped to the Read component.

In the previous article, we specified that admin users should be shown an admin.dashboard view in the index method, however, we didn’t create this view. Let’s create the view. Open the resources/views folder and create a new folder called admin. Within the new resources/views/admin folder, create a new file and called dashboard.blade.php. This is going to be the entry point to the admin dashboard, further from this route, we will let the VueRouter handle everything else.

Open the resources/views/admin/dashboard.blade.php file and paste in the following code:

<pre class="ql-syntax" spellcheck="false"> <!-- File: ./resources/views/admin/dashboard.blade.php -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> Welcome to the Admin dashboard </title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<style>
html, body {
background-color: #202B33;
color: #738491;
font-family: "Open Sans";
font-size: 16px;
font-smoothing: antialiased;
overflow: hidden;
}
</style>
</head>
<body>

  &lt;script src="{{ asset('js/app.js') }}"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

</pre>

Our goal here is to integrate Vue into the application, so we included the resources/assets/js/app.js file with this line of code:

<pre class="ql-syntax" spellcheck="false"> <script src="{{ asset('js/app.js') }}"></script>

</pre>

For our app to work, we need a root element to bind our Vue instance unto. Before the <script> tag, add this snippet of code:

<pre class="ql-syntax" spellcheck="false"> <div id="app">
<Homepage
:user-name='@json(auth()->user()->name)'
:user-id='@json(auth()->user()->id)'
></Homepage>
</div>
</pre>

We earlier defined the Homepage component as the wrapping component, that’s why we pulled it in here as the root component. For some of the frontend components to work correctly, we require some details of the logged in admin user to perform CRUD operations. This is why we passed down the userName and userId props to the Homepage component.

We need to prevent the CSRF error from occurring in our Vue frontend, so include this snippet of code just before the <title> tag:

<pre class="ql-syntax" spellcheck="false"> <meta name="csrf-token" content="{{ csrf_token() }}">
<script> window.Laravel = { csrfToken: 'csrf_token() ' } </script>
</pre>

This snippet will ensure that the correct token is always included in our frontend, Laravel provides the CSRF protection for us out of the box.

At this point, this should be the contents of your resources/views/admin/dashboard.blade.php file:

<pre class="ql-syntax" spellcheck="false"> <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="csrf-token" content="{{ csrf_token() }}">
<script> window.Laravel = { csrfToken: 'csrf_token() ' } </script>
<title> Welcome to the Admin dashboard </title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<style>
html, body {
background-color: #202B33;
color: #738491;
font-family: "Open Sans";
font-size: 16px;
font-smoothing: antialiased;
overflow: hidden;
}
</style>
</head>
<body>
<div id="app">
<Homepage
:user-name='@json(auth()->user()->name)'
:user-id='@json(auth()->user()->id)'>
</Homepage>
</div>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
</pre>

Setting up the Homepage view

Open the Homepage.vue file that we created some time ago and include this markup template:

<pre class="ql-syntax" spellcheck="false"> <!-- File: ./resources/app/js/components/Homepage.vue -->
<template>
<div>
<nav>
<section>
<a style="color: white" href="/admin/dashboard">Laravel-CMS</a> &nbsp; || &nbsp;
<a style="color: white" href="/">HOME</a>
<hr>
<ul>
<li>
<router-link :to="{ name: 'create', params: { userId } }">
NEW POST
</router-link>
</li>
</ul>
</section>
</nav>
<article>
<header>
<header class="d-inline">Welcome, {{ userName }}</header>
<p @click="logout" class="float-right mr-3" style="cursor: pointer">Logout</p>
</header>
<div>
<router-view></router-view>
</div>
</article>
</div>
</template>
</pre>

We added a router-link in this template, which routes to the Create component.

We are passing the userId data to the create component because a userId is required during Post creation.

Let’s include some styles so that the page looks good. Below the closing template tag, paste the following code:

<pre class="ql-syntax" spellcheck="false"> <style scoped>
@import url(https://fonts.googleapis.com/css?family=Dosis:300|Lato:300,400,600,700|Roboto+Condensed:300,700|Open+Sans+Condensed:300,600|Open+Sans:400,300,600,700|Maven+Pro:400,700);
@import url("https://netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.css");
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
header {
color: #d3d3d3;
}
nav {
position: absolute;
top: 0;
bottom: 0;
right: 82%;
left: 0;
padding: 22px;
border-right: 2px solid #161e23;
}
nav > header {
font-weight: 700;
font-size: 0.8rem;
text-transform: uppercase;
}
nav section {
font-weight: 600;
}
nav section header {
padding-top: 30px;
}
nav section ul {
list-style: none;
padding: 0px;
}
nav section ul a {
color: white;
text-decoration: none;
font-weight: bold;
}
article {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 18%;
overflow: auto;
border-left: 2px solid #2a3843;
padding: 20px;
}
article > header {
height: 60px;
border-bottom: 1px solid #2a3843;
}
</style>
</pre>
We are using the scoped attribute on the <style> tag because we want the CSS to only be applied on the Homepage component.

Next, let’s add the <script> section that will use the props we passed down from the parent component. We will also define the method that controls the log out feature here. Below the closing style tag, paste the following code:

<pre class="ql-syntax" spellcheck="false"> <script>
export default {
props: {
userId: {
type: Number,
required: true
},
userName: {
type: String,
required: true
}
},
data() {
return {};
},
methods: {
logout() {
axios.post("/logout").then(() => {
window.location = "/";
});
}
}
};
</script>
</pre>

Setting up the Read view

In the resources/assets/js/app.js file, we defined the path of the read component as /admin/dashboard, which is the same address as the Homepage component. This will make sure the Read component always loads by default.

In the Read component, we want to load all of the available posts. We are also going to add Update and Delete options to each post. Clicking on these options will lead to the update and delete views respectively.

Open the Read.vue file and paste the following:

<pre class="ql-syntax" spellcheck="false"> <!-- File: ./resources/app/js/components/Read.vue -->
<template>
<div id="posts">
<p class="border p-3" v-for="post in posts">
{{ post.title }}
<router-link :to="{ name: 'update', params: { postId : post.id } }">
<button type="button" class="p-1 mx-3 float-right btn btn-light">
Update
</button>
</router-link>
<button
type="button"
@click="deletePost(post.id)"
class="p-1 mx-3 float-right btn btn-danger"
>
Delete
</button>
</p>
<div>
<button
v-if="next"
type="button"
@click="navigate(next)"
class="m-3 btn btn-primary"
>
Next
</button>
<button
v-if="prev"
type="button"
@click="navigate(prev)"
class="m-3 btn btn-primary"
>
Previous
</button>
</div>
</div>
</template>
</pre>

Above, we have the template to handle the posts that are loaded from the API. Next, paste the following below the closing template tag:

<pre class="ql-syntax" spellcheck="false"> <script>
export default {
mounted() {
this.getPosts();
},
data() {
return {
posts: {},
next: null,
prev: null
};
},
methods: {
getPosts(address) {
axios.get(address ? address : "/api/posts").then(response => {
this.posts = response.data.data;
this.prev = response.data.links.prev;
this.next = response.data.links.next;
});
},
deletePost(id) {
axios.delete("/api/posts/" + id).then(response => this.getPosts())
},
navigate(address) {
this.getPosts(address)
}
}
};
</script>
</pre>

In the script above, we defined a getPosts() method that requests a list of posts from the backend server. We also defined a posts object as a data property. This object will be populated whenever posts are received from the backend server.

We defined next and prev data string properties to store pagination links and only display the pagination options where it is available.

Lastly, we defined a deletePost() method that takes the id of a post as a parameter and sends a DELETE request to the API interface using Axios.


Testing the application

Now that we have completed the first few components, we can serve the application using this command:

<pre class="ql-syntax" spellcheck="false"> $ php artisan serve

</pre>

We will also build the assets so that our JavaScript is compiled for us. To do this, will run the command below in the root of the project folder:

<pre class="ql-syntax" spellcheck="false"> $ npm run dev

</pre>

We can visit the application’s URL http://localhost:8000 and log in as an admin user, and delete a post:


Conclusion

In this part of the series, we started building the admin dashboard using Vue. We installed VueRouter to make the admin dashboard a SPA. We added the homepage view of the admin dashboard and included read and delete functionalities.

We are not done with the dashboard just yet. In the next part, we will add the views that lets us create and update posts.

The source code for this project is available here on Github.


Build a CMS with Laravel and Vue - Part 5: Completing our dashboards

In the previous part of this series, we built the first parts of the admin dashboard using Vue. We also made it into an SPA with the VueRouter, this means that visiting the pages does not cause a reload to the web browser.

We only built the wrapper component and the Read component that retrieves the posts to be loaded so an admin can manage them.

Here’s a recording of what we ended up with, in the last article:

In this article, we will build the view that will allow users to create and update posts. We will start writing code in the Update.vue and Create.vue files that we created in the previous article.

When we are done with this part, we will have additional functionalities like create and updating:

The source code for this project is available here on Github.

Prerequisites

To follow along with this series, a few things are required:

  • Basic knowledge of PHP.
  • Basic knowledge of the Laravel framework.
  • Basic knowledge of JavaScript (ES6 syntax).
  • Basic knowledge of Vue.

Including the new routes in VueRouter

In the previous article, we only defined the route for the Read component, we need to include the route configuration for the new components that we are about to build; Update and Create.

Open the resources/assets/js/app.js file and replace the contents with the code below:

<pre class="ql-syntax" spellcheck="false"> require('./bootstrap');

import Vue from 'vue'
import VueRouter from 'vue-router'
import Homepage from './components/Homepage'
import Create from './components/Create'
import Read from './components/Read'
import Update from './components/Update'

Vue.use(VueRouter)

const router = new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/admin/dashboard',
            name: 'read',
            component: Read,
            props: true
        },
        {
            path: '/admin/create',
            name: 'create',
            component: Create,
            props: true
        },
        {
            path: '/admin/update',
            name: 'update',
            component: Update,
            props: true
        },
    ],
});

const app = new Vue({
    el: '#app',
    router,
    components: { Homepage },
});

</pre>

Above, we have added two new components to the JavaScript file. We have the Create and Read components. We also added them to the router so that they can be loaded using the specified URLs.


Building the create view

Open the Create.vue file and update it with this markup template:

<pre class="ql-syntax" spellcheck="false"> <!-- File: ./resources/app/js/components/Create.vue -->
<template>
<div class="container">
<form>
<div :class="['form-group m-1 p-3', (successful ? 'alert-success' : '')]">
<span v-if="successful" class="label label-sucess">Published!</span>
</div>
<div :class="['form-group m-1 p-3', error ? 'alert-danger' : '']">
<span v-if="errors.title" class="label label-danger">
{{ errors.title[0] }}
</span>
<span v-if="errors.body" class="label label-danger">
{{ errors.body[0] }}
</span>
<span v-if="errors.image" class="label label-danger">
{{ errors.image[0] }}
</span>
</div>

      &lt;div class="form-group"&gt;
        &lt;input type="title" ref="title" class="form-control" id="title" placeholder="Enter title" required&gt;
      &lt;/div&gt;

      &lt;div class="form-group"&gt;
        &lt;textarea class="form-control" ref="body" id="body" placeholder="Enter a body" rows="8" required&gt;&lt;/textarea&gt;
      &lt;/div&gt;

      &lt;div class="custom-file mb-3"&gt;
        &lt;input type="file" ref="image" name="image" class="custom-file-input" id="image" required&gt;
        &lt;label class="custom-file-label" &gt;Choose file...&lt;/label&gt;
      &lt;/div&gt;

      &lt;button type="submit" @click.prevent="create" class="btn btn-primary block"&gt;
        Submit
      &lt;/button&gt;
    &lt;/form&gt;
  &lt;/div&gt;
&lt;/template&gt;

</pre>

Above we have the template for the Create component. If there is an error during post creation, there will be a field indicating the specific error. When a post is successfully published, there will also a message saying it was successful.

Let’s include the script logic that will perform the sending of posts to our backend server and read back the response.

After the closing template tag add this:

<pre class="ql-syntax" spellcheck="false"> <script>
export default {
props: {
userId: {
type: Number,
required: true
}
},
data() {
return {
error: false,
successful: false,
errors: []
};
},
methods: {
create() {
const formData = new FormData();
formData.append("title", this.$refs.title.value);
formData.append("body", this.$refs.body.value);
formData.append("user_id", this.userId);
formData.append("image", this.$refs.image.files[0]);

      axios
        .post("/api/posts", formData)
        .then(response =&gt; {
          this.successful = true;
          this.error = false;
          this.errors = [];
        })
        .catch(error =&gt; {
          if (!_.isEmpty(error.response)) {
            if ((error.response.status = 422)) {
              this.errors = error.response.data.errors;
              this.successful = false;
              this.error = true;
            }
          }
        });

      this.$refs.title.value = "";
      this.$refs.body.value = "";
    }
  }
};
&lt;/script&gt;

</pre>

In the script above, we defined a create() method that takes the values of the input fields and uses the Axios library to send them to the API interface on the backend server. Within this method, we also update the status of the operation, so that an admin user can know when a post is created successfully or not.


Building the update view

Let’s start building the Update component. Open the Update.vue file and update it with this markup template:

<pre class="ql-syntax" spellcheck="false"> <!-- File: ./resources/app/js/components/Update.vue -->
<template>
<div class="container">
<form>
<div :class="['form-group m-1 p-3', successful ? 'alert-success' : '']">
<span v-if="successful" class="label label-sucess">Updated!</span>
</div>

      &lt;div :class="['form-group m-1 p-3', error ? 'alert-danger' : '']"&gt;
        &lt;span v-if="errors.title" class="label label-danger"&gt;
          {{ errors.title[0] }}
        &lt;/span&gt;
        &lt;span v-if="errors.body" class="label label-danger"&gt;
          {{ errors.body[0] }}
        &lt;/span&gt;
      &lt;/div&gt;

      &lt;div class="form-group"&gt;
        &lt;input type="title" ref="title" class="form-control" id="title" placeholder="Enter title" required&gt;
      &lt;/div&gt;

      &lt;div class="form-group"&gt;
        &lt;textarea class="form-control" ref="body" id="body" placeholder="Enter a body" rows="8" required&gt;&lt;/textarea&gt;
      &lt;/div&gt;

      &lt;button type="submit" @click.prevent="update" class="btn btn-primary block"&gt;
        Submit
      &lt;/button&gt;
    &lt;/form&gt;
  &lt;/div&gt;
&lt;/template&gt;

</pre>

This template is similar to the one in the Create component. Let’s add the script for the component.

Below the closing template tag, paste the following:

<pre class="ql-syntax" spellcheck="false"> <script>
export default {
mounted() {
this.getPost();
},
props: {
postId: {
type: Number,
required: true
}
},
data() {
return {
error: false,
successful: false,
errors: []
};
},
methods: {
update() {
let title = this.$refs.title.value;
let body = this.$refs.body.value;

      axios
        .put("/api/posts/" + this.postId, { title, body })
        .then(response =&gt; {
          this.successful = true;
          this.error = false;
          this.errors = [];
        })
        .catch(error =&gt; {
          if (!_.isEmpty(error.response)) {
            if ((error.response.status = 422)) {
              this.errors = error.response.data.errors;
              this.successful = false;
              this.error = true;
            }
          }
        });
    },
    getPost() {
      axios.get("/api/posts/" + this.postId).then(response =&gt; {
        this.$refs.title.value = response.data.data.title;
        this.$refs.body.value = response.data.data.body;
      });
    }
  }
};
&lt;/script&gt;

</pre>

In the script above, we make a call to the getPosts() method as soon as the component is mounted. The getPosts() method fetches the data of a single post from the backend server, using the postId.

When Axios sends back the data for the post, we update the input fields in this component so they can be updated.

Finally, the update() method takes the values of the fields in the components and attempts to send them to the backend server for an update. In a situation where the fails, we get instant feedback.


Testing the application

To test that our changes work, we want to refresh the database and restore it back to a fresh state. To do this, run the following command in your terminal:

<pre class="ql-syntax" spellcheck="false"> $ php artisan migrate:fresh --seed

</pre>

Next, let’s compile our JavaScript files and assets. This will make sure all the changes we made in the Vue component and the app.js file gets built. To recompile, run the command below in your terminal:

<pre class="ql-syntax" spellcheck="false"> $ npm run dev

</pre>

Lastly, we need to serve the application. To do this, run the following command in your terminal window:

<pre class="ql-syntax" spellcheck="false"> $ php artisan serve

</pre>

If you had the serve command running before, then you might need to restart it.

We will visit the application’s http://localhost:8000 and log in as an admin user. From the dashboard, you can test the create and update feature:


Conclusion

In this part of the series, we updated the dashboard to include the Create and Update component so the administrator can add and update posts.

In the next article, we will build the views that allow for the creation and updating of a post.

The source code for this project is available here on Github.


Build a CMS with Laravel and Vue - Part 6: Adding Realtime Comments

In the previous part of this series, we finished building the backend of the application using Vue. We were able to add the create and update component, which is used for creating a new post and updating an existing post.

Here’s a screen recording of what we have been able to achieve:

In this final part of the series, we will be adding support for comments. We will also ensure that the comments on each post are updated in realtime, so a user doesn’t have to refresh the page to see new comments.

When we are done, our application will have new features and will work like this:

The source code for this project is available here on Github.

Prerequisites

To follow along with this series, a few things are required:

  • A Pusher account. Sign up here.
  • Basic knowledge of PHP.
  • Basic knowledge of the Laravel framework.
  • Basic knowledge of JavaScript (ES6 syntax).
  • Basic knowledge of Vue.

Adding comments to the backend

When we were creating the API, we did not add the support for comments to the post resource, so we will have to do so now. Open the API project in your text editor as we will be modifying the project a little.

The first thing we want to do is create a model, controller, and a migration for the comment resource. To do this, open your terminal and cd to the project directory and run the following command:

<pre class="ql-syntax" spellcheck="false"> $ php artisan make:model Comment -mc

</pre>

The command above will create a model called Comment, a controller called CommentController, and a migration file in the database/migrations directory.


Updating the comments migration file

To update the comments migration navigate to the database/migrations folder and find the newly created migration file for the Comment model. Let’s update the up() method in the file:

<pre class="ql-syntax" spellcheck="false"> // File: ./database/migrations/*_create_comments_table.php
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->integer('user_id')->unsigned();
$table->integer('post_id')->unsigned();
$table->text('body');
});
}
</pre>

We included user_id and post_id fields because we intend to create a link between the comments, users, and posts. The body field will contain the actual comment.


Defining the relationships among the Comment, User, and Post models

In this application, a comment will belong to a user and a post because a user can make a comment on a specific post, so we need to define the relationship that ties everything up.

Open the User model and include this method:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/User.php
public function comments()
{
return $this->hasMany(Comment::class);
}
</pre>

This is a relationship that simply says that a user can have many comments. Now let’s define the same relationship on the Post model. Open the Post.php file and include this method:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Post.php
public function comments()
{
return $this->hasMany(Comment::class);
}
</pre>

Finally, we will include two methods in the Comment model to complete the second half of the relationships we defined in the User and Post models.

Open the app/Comment.php file and include these methods:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Comment.php
public function user()
{
return $this->belongsTo(User::class);
}

public function post()
{
    return $this-&gt;belongsTo(Post::class);
}

</pre>

Since we want to be able to mass assign data to specific fields of a comment instance during comment creation, we will include this array of permitted assignments in the app/Comment.php file:

<pre class="ql-syntax" spellcheck="false"> protected $fillable = ['user_id', 'post_id', 'body'];
</pre>

We can now run our database migration for our comments:

<pre class="ql-syntax" spellcheck="false"> $ php artisan migrate

</pre>

Configuring Laravel to broadcast events using Pusher

We already said that the comments will have a realtime functionality and we will be building this using Pusher, so we need to enable Laravel’s event broadcasting feature.

Open the config/app.php file and uncomment the following line in the providers array:

<pre class="ql-syntax" spellcheck="false"> App\Providers\BroadcastServiceProvider

</pre>

Next, we need to configure the broadcast driver in the .env file:

<pre class="ql-syntax" spellcheck="false"> BROADCAST_DRIVER=pusher

</pre>

Let’s pull in the Pusher PHP SDK using composer:

<pre class="ql-syntax" spellcheck="false"> $ composer require pusher/pusher-php-server

</pre>

Configuring Pusher

For us to use Pusher in this application, it is a prerequisite that you have a Pusher account. You can create a free Pusher account here then login to your dashboard and create an app.

Once you have created an app, we will use the app details to configure pusher in the .env file:

<pre class="ql-syntax" spellcheck="false"> PUSHER_APP_ID=xxxxxx
PUSHER_APP_KEY=xxxxxxxxxxxxxxxxxxxx
PUSHER_APP_SECRET=xxxxxxxxxxxxxxxxxxxx
PUSHER_APP_CLUSTER=xx

</pre>

Update the Pusher keys with the app credentials provided for you under the Keys section on the Overview tab on the Pusher dashboard.


Broadcasting an event for when a new comment is sent

To make the comment update realtime, we have to broadcast an event based on the comment creation activity. We will create a new event and call it CommentSent. It is to be fired when there is a successful creation of a new comment.

Run command in your terminal:

<pre class="ql-syntax" spellcheck="false"> php artisan make:event CommentSent

</pre>

There will be a newly created file in the app\Events directory, open the CommentSent.php file and ensure that it implements the ShouldBroadcast interface.

Open and replace the file with the following code:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Events/CommentSent.php
<?php

namespace App\Events;

use App\Comment;
use App\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class CommentSent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $user;

    public $comment;

    public function __construct(User $user, Comment $comment)
    {
        $this-&gt;user = $user;

        $this-&gt;comment = $comment;
    }

    public function broadcastOn()
    {
        return new PrivateChannel('comment');
    }
}

</pre>

In the code above, we created two public properties, user and comment, to hold the data that will be passed to the channel we are broadcasting on. We also created a private channel called comment. We are using a private channel so that only authenticated clients can subscribe to the channel.


Defining the routes for handling operations on a comment

We created a controller for the comment model earlier but we haven’t defined the web routes that will redirect requests to be handled by that controller.

Open the routes/web.php file and include the code below:

<pre class="ql-syntax" spellcheck="false"> // File: ./routes/web.php
Route::get('/{post}/comments', '[email protected]');
Route::post('/{post}/comments', '[email protected]');
</pre>

Setting up the action methods in the CommentController

We need to include two methods in the CommentController.php file, these methods will be responsible for storing and retrieving methods. In the store() method, we will also be broadcasting an event when a new comment is created.

Open the CommentController.php file and replace its contents with the code below:

<pre class="ql-syntax" spellcheck="false"> // File: ./app/Http/Controllers/CommentController.php
<?php

namespace App\Http\Controllers;

use App\Comment;
use App\Events\CommentSent;
use App\Post;
use Illuminate\Http\Request;

class CommentController extends Controller
{
    public function store(Post $post)
    {
        $this-&gt;validate(request(), [
            'body' =&gt; 'required',
        ]);

        $user = auth()-&gt;user();

        $comment = Comment::create([
            'user_id' =&gt; $user-&gt;id,
            'post_id' =&gt; $post-&gt;id,
            'body' =&gt; request('body'),
        ]);

        broadcast(new CommentSent($user, $comment))-&gt;toOthers();

        return ['status' =&gt; 'Message Sent!'];
    }

    public function index(Post $post)
    {
        return $post-&gt;comments()-&gt;with('user')-&gt;get();
    }
}

</pre>

In the store method above, we are validating then creating a new post comment. After the comment has been created, we broadcast the CommentSent event to other clients so they can update their comments list in realtime.

In the index method we just return the comments belonging to a post along with the user that made the comment.


Adding a layer of authentication

Let’s add a layer of authentication that ensures that only authenticated users can listen on the private comment channel we created.

Add the following code to the routes/channels.php file:

<pre class="ql-syntax" spellcheck="false"> // File: ./routes/channels.php
Broadcast::channel('comment', function ($user) {
return auth()->check();
});
</pre>

Adding comments to the frontend

In the second article of this series, we created the view for the single post landing page in the single.blade.php file, but we didn’t add the comments functionality. We are going to add it now. We will be using Vue to build the comments for this application so the first thing we will do is include Vue in the frontend of our application.

Open the master layout template and include Vue to its <head> tag. Just before the <title> tag appears in the master.blade.php file, include this snippet:

<pre class="ql-syntax" spellcheck="false"> <!-- File: ./resources/views/layouts/master.blade.php -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<script src="{{ asset('js/app.js') }}" defer></script>
</pre>

The csrf_token() is there so that users cannot forge requests in our application. All our requests will pick the randomly generated csrf-token and use that to make requests.

Related: CSRF in Laravel: how VerifyCsrfToken works and how to prevent attacks

Now the next thing we want to do is update the resources/assets/js/app.js file so that it includes a template for the comments view.

Open the file and replace its contents with the code below:

<pre class="ql-syntax" spellcheck="false"> require('./bootstrap');

import Vue          from 'vue'
import VueRouter    from 'vue-router'
import Homepage from './components/Homepage'
import Create   from './components/Create'
import Read     from './components/Read'
import Update   from './components/Update'
import Comments from './components/Comments'

Vue.use(VueRouter)

const router = new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/admin/dashboard',
            name: 'read',
            component: Read,
            props: true
        },
        {
            path: '/admin/create',
            name: 'create',
            component: Create,
            props: true
        },
        {
            path: '/admin/update',
            name: 'update',
            component: Update,
            props: true
        },
    ],
});

const app = new Vue({
    el: '#app',
    components: { Homepage, Comments },
    router,
});

</pre>

Above we imported the Comment component and then we added it to the list of components in the applications Vue instance.

Now create a Comments.vue file in the resources/assets/js/components directory. This is where all the code for our comment view will go. We will populate this file later on.


Installing Pusher and Laravel Echo

For us to be able to use Pusher and subscribe to events on the frontend, we need to pull in both Pusher and Laravel Echo. We will do so by running this command:

<pre class="ql-syntax" spellcheck="false"> $ npm install --save laravel-echo pusher-js

</pre>

Laravel Echo is a JavaScript library that makes it easy to subscribe to channels and listen for events broadcast by Laravel.

Now let’s configure Laravel Echo to work in our application. In the resources/assets/js/bootstrap.js file, find and uncomment this snippet of code:

<pre class="ql-syntax" spellcheck="false"> import Echo from 'laravel-echo'

window.Pusher = require('pusher-js');

window.Echo = new Echo({
     broadcaster: 'pusher',
     key: process.env.MIX_PUSHER_APP_KEY,
     cluster: process.env.MIX_PUSHER_APP_CLUSTER,
     encrypted: true
});

</pre>

The key and cluster will pull the keys from your .env file so no need to enter them manually again.

Now let’s import the Comments component into the single.blade.php file and pass along the required the props.

Open the single.blade.php file and replace its contents with the code below:

<pre class="ql-syntax" spellcheck="false"> {{-- File: ./resources/views/single.blade.php --}}
@extends('layouts.master')

@section('content')
&lt;div class="container"&gt;
  &lt;div class="row"&gt;
    &lt;div class="col-lg-10 mx-auto"&gt;
      &lt;br&gt;
      &lt;h3 class="mt-4"&gt;
        {{ $post-&gt;title }} 
        &lt;span class="lead"&gt;by &lt;a href="#"&gt;{{ $post-&gt;user-&gt;name }}&lt;/a&gt;&lt;/span&gt;
      &lt;/h3&gt;
      &lt;hr&gt;
      &lt;p&gt;Posted {{ $post-&gt;created_at-&gt;diffForHumans() }}&lt;/p&gt;
      &lt;hr&gt;
      &lt;img class="img-fluid rounded" src="{!! !empty($post-&gt;image) ? '/uploads/posts/' . $post-&gt;image : 'http://placehold.it/750x300' !!}" alt=""&gt;
      &lt;hr&gt;
      &lt;div&gt;
        &lt;p&gt;{{ $post-&gt;body }}&lt;/p&gt;
        &lt;hr&gt;
        &lt;br&gt;
      &lt;/div&gt;

      @auth
      &lt;Comments
          :post-id='@json($post-&gt;id)' 
          :user-name='@json(auth()-&gt;user()-&gt;name)'&gt;
      &lt;/Comments&gt;
      @endauth
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
@endsection

</pre>

Building the comments view

Open the Comments.vue file and add the following markup template below:

<pre class="ql-syntax" spellcheck="false"> <template>
<div class="card my-4">
<h5 class="card-header">Leave a Comment:</h5>
<div class="card-body">
<form>
<div class="form-group">
<textarea ref="body" class="form-control" rows="3"></textarea>
</div>
<button type="submit" @click.prevent="addComment" class="btn btn-primary">
Submit
</button>
</form>
</div>
<p class="border p-3" v-for="comment in comments">
<strong>{{ comment.user.name }}</strong>:
<span>{{ comment.body }}</span>
</p>
</div>
</template>
</pre>

Now, we’ll add a script that defines two methods:

  1. fetchComments() - this will fetch all the existing comments when the component is created.
  2. addComment() - this will add a new comment by hitting the backend server. It will also trigger a new event that will be broadcast so all clients receive them in realtime.

In the same file, add the following below the closing template tag:

<pre class="ql-syntax" spellcheck="false"> <script>
export default {
props: {
userName: {
type: String,
required: true
},
postId: {
type: Number,
required: true
}
},
data() {
return {
comments: []
};
},

  created() {
    this.fetchComments();

    Echo.private("comment").listen("CommentSent", e =&gt; {
        this.comments.push({
          user: {name: e.user.name},
          body: e.comment.body,
        });
    });
  },

  methods: {
    fetchComments() {
      axios.get("/" + this.postId + "/comments").then(response =&gt; {
        this.comments = response.data;
      });
    },

    addComment() {
      let body = this.$refs.body.value;
      axios.post("/" + this.postId + "/comments", { body }).then(response =&gt; {
        this.comments.push({
          user: {name: this.userName},
          body: this.$refs.body.value
        });
        this.$refs.body.value = "";
      });
    }
  }
};
&lt;/script&gt;

</pre>

In the created() method above, we first made a call to the fetchComments() method, then we created a listener to the private comment channel using Laravel Echo. Once this listener is triggered, the comments property is updated.


Testing the application

Now let’s test the application to see if it is working as intended. Before running the application, we need to refresh our database so as to revert any changes. To do this, run the command below in your terminal:

<pre class="ql-syntax" spellcheck="false"> $ php artisan migrate:fresh --seed

</pre>

Next, let’s build the application so that all the changes will be compiled and included as a part of the JavaScript file. To do this, run the following command on your terminal:

<pre class="ql-syntax" spellcheck="false"> $ npm run dev

</pre>

Finally, let’s serve the application using this command:

<pre class="ql-syntax" spellcheck="false"> $ php artisan serve

</pre>

To test that our application works visit the application URL http://localhost:8000 on two separate browser windows, we will log in to our application on each of the windows as a different user.

We will finally make a comment on the same post on each of the browser windows and check that it updates in realtime on the other window:


Conclusion

In this final tutorial of this series, we created the comments feature of the CMS and also made it realtime. We were able to accomplish the realtime functionality using Pusher.

In this entire series, we learned how to build a CMS using Laravel and Vue.

The source code for this article series is available here on Github.


Learn More

Build a Basic CRUD App with Laravel and Vue

Fullstack Vue App with Node, Express and MongoDB

Build a Simple CRUD App with Spring Boot and Vue.js

Build a Basic CRUD App with Laravel and Angular

Build a Basic CRUD App with Laravel and React

PHP Programming Language - PHP Tutorial for Beginners

Vuejs 2 Authentication Tutorial

Vue Authentication And Route Handling Using Vue-router

Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

Nuxt.js - Vue.js on Steroids

MEVP Stack Vue JS 2 Course: MySQL + Express.js + Vue.js +PHP

Build Web Apps with Vue JS 2 & Firebase

Originally published by Neo Ighodaro at https://pusher.com