Wednesday, October 25, 2017

How To Add Custom Helpers on Handlebars?

You can extend handlebars with your own custom helpers. This allows you to create complex logic using handlebar’s expression system. There are 2 kinds of helpers, a function helper and a block helper. The difference is that one is meant for a single expression and the other uses a block expression.


Custom Function Helpers
Creating function helpers is relatively easy. To create one, we have to register it using the registerHelper() method. It takes the name of the helper and the helper function as arguments. Handlebars.js takes whatever is returned from the helper function and writes it out to the template, so be sure to always return a string from your custom helpers.

To write an expression helper function to output a formatted phone number, you could define the following helper:
Handlebars.registerHelper("formatPhoneNumber", function(phoneNumber) {
  phoneNumber = phoneNumber.toString();
  return "(" + phoneNumber.substr(0,3) + ") " + phoneNumber.substr(3,3) + "-" + phoneNumber.substr(6,4);
});
You would use the formatPhoneNumber helper in a template like this:
{{formatPhoneNumber phoneNumber}}

Custom Block Helpers
Custom block helpers are also registered with the Handlebars.registerHelper method. When a helper is used with a block, Handlebars will pass the contents of the block compiled into a function to the helper.

Here's an example block helper that compare the option with a value, letting the contents know whether a value is equal to option. If the option is an equal to a value, helper just returns the 'selected' attribute else return empty string. This helper is useful to add a 'selected' attribute conditionally on any of the option elements.
Handlebars.registerHelper("selected", function(option, value) {
 if (option === value) {
        return 'selected';
    } else {
        return '';
    }
});

You would use the selected helper in a template like this:
<select name="countries" >
 <option  value="{{code}}" {{selected code "46" }>{{country_name}}({{code}})</option>
</select>
If the country code is equal to 46 i.e Sweden, the option will be selected.

Ref: Custom Helpers – Handlebars.js Tutorial

Friday, September 29, 2017

How To Install and Configure Homestead For Laravel 5 and OSX?

Laravel Homestead is an official, pre-packaged Vagrant box that provides you a wonderful development environment without requiring you to install PHP, a web server, and any other server software on your local machine. No more worrying about messing up your operating system! Vagrant boxes are completely disposable. If something goes wrong, you can destroy and re-create the box in minutes!

Homestead runs on any Windows, Mac, or Linux system, and includes the Nginx web server, PHP 7.1, MySQL, PostgreSQL, Redis, Memcached, Node, and all of the other goodies you need to develop amazing Laravel applications.

STEP 1: DOWNLOADING FILES
The first step is getting the required software for Homestead. Before launching your Homestead environment, you must install VirtualBox, (VMWare, or Parallels) as well as Vagrant. I used VirtualBox and as it is free, I am pretty sure most of you guys will be using it too.

STEP 2: INSTALLING VAGRANT HOMESTEAD BOX
Once VirtualBox / VMware and Vagrant have been installed, you should add the laravel/homestead box to your Vagrant installation using the following command in your terminal. It will take a few minutes to download the box, depending on your Internet connection speed:
 vagrant box add laravel/homestead

STEP 3: INSTALLING LARAVEL HOMESTEAD
You may install Homestead by simply cloning the repository. Consider cloning the repository into a Homestead folder within your "home" directory, as the Homestead box will serve as the host to all of your Laravel projects:
 cd ~
 git clone https://github.com/laravel/homestead.git Homestead
Once you have cloned the Homestead repository, run the bash init.sh command from the Homestead directory to create the Homestead.yaml configuration file. The Homestead.yaml file will be placed in the Homestead directory:
 cd Homestead
 bash init.sh

STEP 4: CONFIGURING THE LARAVEL HOMESTEAD
Rest of the configuration is easy. The homstead.yaml is already configured for a default app.

Setting Your Provider
The provider key in your Homestead.yaml file indicates which Vagrant provider should be used: virtualbox, vmware_fusion, vmware_workstation, or parallels. You may set this to the provider you prefer. I recommend virtualbox.
  provider: virtualbox
Configuring Shared Folders/ Folder Mapping
Folder mapping means that your Guest OS and Host OS will share a common folder where you can keep your laravel files. Laravel Homestead configures a default folder in the home directory of the Host OS.The folders property of the Homestead.yaml file lists all of the folders you wish to share with your Homestead environment. As files within these folders are changed, they will be kept in sync between your local machine and the Homestead environment. You may configure as many shared folders as necessary:
folders:
    - map: ~/Code
      to: /home/vagrant/Code
Sites
Sites is a configuration array for Nginx. By default configuration, you will have a “homestead.app” pseudo-domain which will point to a folder inside the “shared folder”. Any php code inside that folder will get executed when you will go to homestead.app inside your browser. You should set it to the “public” folder of your laravel app. Again, you may add as many sites to your Homestead environment as necessary. Homestead can serve as a convenient, virtualized environment for every Laravel project you are working on:

sites:
    - map: homestead.app
      to: /home/vagrant/Code/Laravel/public

If you change the sites property after provisioning the Homestead box, you should re-run vagrant reload --provision to update the Nginx configuration on the virtual machine.
 vagrant reload --provision
Note: It’s this particular step that tends to confuse most Homestead beginners, so pay close attention to the following description. The folders object’s map attribute identifies the location in which your Laravel project will be located. The default value is ~/Code, meaning Homestead expects your project to reside in a directory named Code found in your home directory. You’re free to change this to any location you please. The folders object’s to attribute identifies the location on the virtual machine that will mirror the contents of the directory defined by the map key, thereby making the contents of your local directory available to the virtual machine.
The sites object’s map attribute defines the domain name used to access the Laravel application via the browser. Finally, the sites object’s to attribute defines the Laravel project’s root web directory, which is /public by default.


If this explanation is clear as mud, let’s clarify with an example. Begin by setting the folders object’s map attribute to any path you please, likely somewhere within the directory where you tend to manage your various software projects. For instance, mine homestead.yaml is currently set like this:
ip: "192.168.10.10"
memory: 2048
cpus: 1
provider: virtualbox

authorize: ~/.ssh/id_rsa.pub

keys:
    - ~/.ssh/id_rsa

folders:
    - map: ~/development/projects
      to: /home/vagrant/projects

sites:
    - map: laravel.dev
      to: /home/vagrant/projects/laravel/public

    - map: homestead.app
      to: /home/vagrant/projects/tutorials/laravel-basics/public  

databases:
    - homestead

Here is the screen dump of my Folder Structure


STEP 5: CONFIGURING THE HOST FILE
You must add the "domains" for your Nginx sites to the hosts file on your machine. The hosts file will redirect requests for your Homestead sites into your Homestead machine. On Mac and Linux, this file is located at private/etc/hosts. Open the hosts file with administrative access
  sudo nano /private/etc/hosts
The lines you add to this file will look like the following. You can add it anywhere but for ease, add it at the bottom of the file as below.
192.168.10.10   laravel.dev
192.168.10.10   homestead.app
Make sure the IP address listed is the one set in your Homestead.yaml file.

After adding above lines to the file Press cltr + o, then Enter, then cltr+x
Here is the screenshot of my host file:

STEP 6: RISE AND SHINE HOMESTEAD
Open terminal and navigate to Homestead directory and run the following vagrant up command. Vagrant will boot the virtual machine and automatically configure your shared folders and Nginx sites.
  Anup:~ anup$ cd ~/Homestead
  Anup:Homestead anup$ vagrant up
You will have your Homestead running in no time. Now go to homestead.app in your browser and be ready to get an error. Most probably “No input File Found”. It is because we don’t have laravel app’s “public” folder yet. We will install laravel in the next step.

STEP 7: INSTALL COMPOSER AND LARAVEL
Laravel utilizes Composer to manage its dependencies. So, before using Laravel, make sure you have Composer installed on your machine.
Installing Composer Run this in your terminal to get the latest Composer version:
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
Make composer globally accessible
After running the installer, you can run this to move composer.phar to a directory that is in your path:
mv composer.phar /usr/local/bin/composer
Now just run composer in order to run Composer instead of php composer.phar
Via Laravel Installer
After the Composer is installed successfully, download the Laravel installer using Composer:
 composer global require "laravel/installer"
Make sure to place the $HOME/.composer/vendor/bin directory (or the equivalent directory for your OS) in your $PATH so the laravel executable can be located by your system. Open .bashrc file to add required $PATH as below:
  Anup:~ anup$ nano ~/.bashrc
Add the export PATH="$PATH:$HOME/.config/composer/vendor/bin" as below:

Once installed, the laravel new command will create a fresh Laravel installation in the directory you specify. For instance, laravel new blog will create a directory named blog containing a fresh Laravel installation with all of Laravel's dependencies already installed.

To install Laravel, we need to go the directory we have specified on STEP 4 (i.e. sites section of homestead.yaml) as below
Anup:~ anup$ cd development/projects/tutorials/laravel-basics/
Anup:laravel-basics anup$ laravel new
It will install laravel in the laravel-basics folder. Don't forget to create .env file on root directory(i.e. remove .example extension from .env.example). Otherwise, you will get error.

My Laravel project looks like below:

STEP 8: SSH’ing INTO YOUR MACHINE
Go the the Homestead directory, run vagrant up and vagrant ssh.
 Anup:~ anup$ cd ~/Homestead
 Anup:Homestead anup$ vagrant up

After vagrant is up, then you can ssh into it as below.
 Anup:Homestead anup$ vagrant ssh
 vagrant@homestead:~$ 
Go the respective project as below and run composer install to complete the Laravel installation process.
vagrant@homestead:~$ cd projects/tutorials/laravel-basics/
vagrant@homestead:~/projects/tutorials/laravel-basics$ composer install
vagrant@homestead:~/projects/tutorials/laravel-basics$ php artisan key:generate
Your Homestead virtual machine is up and running! Open a browser and navigate to the URL http://homestead.app and you should see

You may encounter errors and problems while following the above steps but everyone do. Homestead is very easy to install and configure and after a few minutes of playing around the problems, you will be able to fix it. Let me know in the comments, if I am missing anything in the article or if you are stuck with laravel homestead.

Sources :
Laravel Installation
Install Laravel Homestead on Windows Extremely Easily
Installing and Configuring Homestead 2.0 for Laravel 5

Wednesday, September 27, 2017

How to Upgrade to PHP 7 or 7.1 on macOS?

Usually, with a fresh version of macOS Sierra, you get a PHP 5.6 installed.

Download and Install to PHP 7.0 or 7.1
You’ve got two options: brew or curl install. I am showing how to upgrade to PHP version 7.0 or 7.1 using curl method.

Open Terminal and run…
curl -s http://php-osx.liip.ch/install.sh | bash -s 7.0
or for 7.1
curl -s http://php-osx.liip.ch/install.sh | bash -s 7.1

If the output of php -v still doesn't echoes the version 7, simply type following command to update your path, it should do the magic, as stated on php-osx.liip.ch website
export PATH=/usr/local/php5/bin:$PATH

Source: How to upgrade your version of PHP to 7.0 on macOS Sierra

Monday, September 11, 2017

How to Validate and Submit Form Using VueJs and PHP?

Client-side validation using JavaScript enhances user experience by giving feedback immediately to the user rather than having them complete a round-trip through the server. Before we begin, you must understand that this type of data input validation is no substitute for server-side validation. Without server-side validation, you are trusting the user and whatever tools they are using to make sure input is valid. Client-side validation with Vue.js (or any other JavaScript library/framework) should be used in addition to, not instead of it.

I'll also mention that many modern browsers have client-side validation built-in by using HTML attributes such as (but not limited to) required and maxlength="10". However, not all browsers support this and all of them behave differently. Let’s look at how to build our own form validation using Vue.js so it behaves the same in all modern browsers.

Scenario
We want to build a form with 4 inputs:
• Name
• Number between 1 and 10
• Email
• Message

All inputs are required. The number input should only allow numbers between 1 and 10 & email input should have a valid format.

Setup
Start with a basic HTML file with the Bootstrap 3 stylesheet and Vue.js.
<!DOCTYPE html>
<html>
 <head>
    <meta charset="utf-8">
    <title>Form Validation</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"/>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
</body>
</html>
Our form will go in the content area. Just to get a prettier layout, we’ll put it inside a single col, inside a single row, inside a single container. Each of these elements have classes that position them nicely.
<!div class="container">
  <!div class="row justify-content-center">
    <!div class="col-md-6">
      <!form>
       <!!-- form elements go here -->
      <!/form>
    <!/div><!!-- /col -->
  <!/div><!!-- /row -->
<!/div><!!-- /container -->
Now, our 4 input elements and submit button will go inside the form. Bootstrap provides validation classes. Let’s add those as well.
  <div class="form-group">
      <label class="control-label" for="name">Name </label>
      <input id="name" name="name" class="form-control" type="text" v-model="name">
      <span id="helpBlock" class="help-block">This field is required. </span>
    </div>
    
    <div class="form-group">
      <label class="control-label" for="number">Enter a number between 1 and 10 </label>
      <input id="number" name="number" class="form-control" type="text" v-model="number">
      <span id="helpBlock" class="help-block">Make sure this is a number between 1 and 10. </span>
    </div>

    <div class="form-group">
      <label class="control-label" for="name"Email</label>
      <input id="email" name="email" class="form-control" type="text" v-model="email">
      <span id="helpBlock" class="help-block">Email is invalid. </span>
    </div>

    <div class="form-group">
      <label class="control-label" for="message">Enter a Message </label>
      <textarea  name="message" class="form-control" type="text" v-model="message"> </textarea>
      <span id="helpBlock" class="help-block">This field is required. </span>
    </div>                 
    
    <button class="btn btn-primary">Submit </button>

Right now, the feedback elements will always be displayed. Later, we'll make sure they’re only shown if validation fails.

Building the Vue App
With the HTML in place, now we'll jump into main.js and start coding the logic for our form.
var form = new Vue({
  el: '#form',
  data: {
    name: '',
    email: '',
    message: '',
    number: '',
    attemptSubmit: false,
    postStatus: false
  },
  computed: {
    missingName: function () {},
    wrongNumber: function () {},
    missingEmail: function () {},
    missingMessage: function () {}
  },
  methods: {
    isNumeric: function () {},
    isEmail: function () {},
    validateForm: function () {},
    onSubmit () {}
  },
});


In our data object, there are 6 variables:
1. name — Will hold the value of the name input
2. email — Will hold the value of the email input
3. message — Will hold the value of the message input
4. number — Will hold the value of the number input
5. attemptSubmit — A boolean that indicates whether the user has attempted to submit the form. We can use this to hide validation warnings until after the user has tried to submit the form.
6. postStatus - A boolean that indicates whether the form has been submitted. We can use this to hide the form after the submission.

There are also a 4 computed variables here:
1. missingName — Will return true if name is empty
2. wrongNumber — Will return true if number is not between 1 and 10
3. missingEmail — Will return true if email is empty or invalid
4. missingMessage — Will return true if message is empty

Finally, there are a 4 methods:
1. isNumeric — A utility function that checks to see if an input is a number
2. isEmail — A utility function that checks to see if an input has valid email
3. validateForm — The main function that will be called when trying to submit
4. onSubmit - If the validation is passed, that will be called

I mentioned above that there are 4 variables that hold the value of the inputs. We can wire those up with Vue models. Back in the HTML…
  <input id="name" name="name" class="form-control" type="text" v-model="name">
  <input id="number" name="number" class="form-control" type="text" v-model="number">
  <input id="email" name="email" class="form-control" type="text" v-model="email">
  <textarea  name="message" class="form-control" type="text" v-model="message"></textarea>
With our models wired up, we can use the computed variables to determine the status of each input. missingName and missingMessage are easy. Return true if value is empty:
  missingName: function () { return this.name === ''; },
  missingMessage: function () { return this.message === ''; },
wrongNumber is a little more complex, but not bad at all. Return true if the value is not a number or it’s less than 1 or it’s greater than 10. missingEmail return true if the value has not a valid format or null.
 wrongNumber: function () {
  return (
    this.isNumeric(this.number) === false ||
    this.number < 1 ||
    this.number > 10
  )
},

missingEmail: function () {
   return (
     this.isEmail(this.email) === null)
},
Oops, we’re calling isNumeric() and isEmail() but we haven’t coded it, yet. Here’s what it looks like:
isNumeric: function (n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
},
isEmail: ( str ) => {      
   let regexp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/     
   return str.match(regexp);
}
We're actually done with the JavaScript except for the actual validateForm() and onSubmit function. For that one, we just want to tell our app the user attempted to submit the form and prevent it from submitting if missingName, missingEmail, missingMessage or wrongNumber are true. If all the values are validated, we call onSubmit method.
validateForm: function (event) {
   this.attemptSubmit = true;
   if (this.missingName || this.wrongNumber || this.missingMessage || this.missingEmail) {
       event.preventDefault();
   } else {
       this.onSubmit();
   }       
Done with JavaScript. Back in the HTML, we need to fire the validateForm() function when the form is submitted.

  <form id="form" method="post" v-on:submit.prevent="validateForm">


Then, add the (Bootstrap) has-warning class for each input. We only want to add this class if BOTH:
1. The user has attempted to submit the form, and 2. The value is not valid
<div class="form-group" v-bind:class="{ 'has-warning': attemptSubmit && missingName }">
...
<div class="form-group" v-bind:class="{ 'has-warning': attemptSubmit && wrongNumber }">
...
<div class="form-group" v-bind:class="{ 'has-warning': attemptSubmit && missingEmail }">
...
<div class="form-group" v-bind:class="{ 'has-warning': attemptSubmit && missingMessage }">

Finally, we only want the feedback elements to appear under those same circumstances:
 <span id="helpBlock" class="help-block" v-if="attemptSubmit && missingName">This field is required.</span>
.....
 <span id="helpBlock" class="help-block" v-if="attemptSubmit && wrongNumber">Make sure this is a number between 1 and 10.</span>
......
 <span id="helpBlock" class="help-block" v-if="attemptSubmit && missingEmail">Email is invalid.</span>
......
 <span id="helpBlock" class="help-block" v-if="attemptSubmit && missingMessage">This field is required.</span>
That’s it! On load, the form looks like…
If you try to submit with an empty fields, a warning appears.
The nice part is that, the way we’ve coded it, when the user corrects their mistake, the warning goes away immediately.

Form Submission
After the validation is successful, we will submit using PHP. In order to submit the POST values we are going to use. Axios. Axios is a promise-based HTTP client that works both in the browser and in a node.js environment. It basically provides a single API for dealing with XMLHttpRequests and node’s http interface.

Before using axios, you first need to install it. Adding Axios to your project is easy. There are two options:
1. Install Axios with Node Package Manager as follows:
  $ npm install axios
2. The easiest way is to include Axios by using a Content Delivery Network, e.g. by including the following <script> tag in your index.html file:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

Simply import axios or require it as you do with any other dependency in node as below (if you are using nodeJs and webpack only):

import axios from 'axios';

or

var axios = require('axios');

A frequently overlooked but very useful capability Axios provides is the ability to create a base instance that allows you to share a common base URL and configuration across all calls to the instance.

onSubmit () {
    
     if (process.env.NODE_ENV === 'development') {
            axios.defaults.baseURL = 'http://localhost:8888/your-project-name/php'
      }

      axios.post('post.php', {
                'name': this.name,
                'email': this.email,
                'message': this.message,
                'number': this.number               
        }).then(response => {
            if (response.data.error) {
                    console.log('error', response.data.error)
           } else {
                this.postStatus = true
                console.log('success', response.data.message)                   
           }
        }).catch(error => {
              console.log(error.response)
     }); 
}

Create a folder 'php' and create a file 'post.php' under it.
/* php/post.php */

<?php
header('Content-type: application/json');
header('Access-Control-Allow-Headers: Content-Type');
header("Access-Control-Allow-Origin: *");

$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE);

$name = $input['name'];
$email = $input['email'];
$message = $input['message'];
$number = $input['number'];


$result['message'] = '';
$result['error']  = false;

if($name){
  $result['message']  = "Posted Values => ".$name."-".$email."-".$message."-".$number;
  $result['error']  = false;
}
else {
  $result['error']  = 'Form submission failed.';
}


echo json_encode($result);

file_get_contents(php://input) - gets the raw POST data and this is useful if the POSTed data is a JSON encoded structure, which is often the case for an AJAX POST request. The PHP superglobal $_POST, only is supposed to wrap data that is either
1. application/x-www-form-urlencoded (standard content type for simple form-posts) or
2. multipart/form-data-encoded (mostly used for file uploads)

This is because these are the only content types that must be supported by user agents. So the server and PHP traditionally don't expect to receive any other content type (which doesn't mean they couldn't). But if you are working with Ajax a lot, this probably also includes exchanging more complex data with types (string, int, bool) and structures (arrays, objects), so in most cases JSON is the best choice. The content would now be 'application/json' (or at least none of the above mentioned), so PHP's $_POST-wrapper doesn't know how to handle that (yet). The data is still there, you just can't access it through the wrapper. So you need to fetch it yourself in raw format with file_get_contents('php://input') (as long as it's not multipart/form-data-encoded).

After the form is submitted, you will see confirmation message as below.
I have created a component called 'Form.Vue' with above pieces. Here is the complete source code.

//Form.Vue

<template>  
    <div id="app" class="container">
      <div class="row justify-content-center">
        <div class="col-md-6" v-if="!postStatus">
          <form id="form" method="post" v-on:submit.prevent="validateForm">
            <div class="form-group" v-bind:class="{ 'has-warning': attemptSubmit && missingName }">
              <label class="control-label" for="name">Name</label>
              <input id="name" name="name" class="form-control" type="text" v-model="name">
              <span id="helpBlock" class="help-block" v-if="attemptSubmit && missingName">This field is required.</span>
            </div>
            
            <div class="form-group" v-bind:class="{ 'has-warning': attemptSubmit && wrongNumber }">
              <label class="control-label" for="number">Enter a number between 1 and 10</label>
              <input id="number" name="number" class="form-control" type="text" v-model="number">
              <span id="helpBlock" class="help-block" v-if="attemptSubmit && wrongNumber">Make sure this is a number between 1 and 10.</span>
            </div>

             <div class="form-group" v-bind:class="{ 'has-warning': attemptSubmit && missingEmail }">
              <label class="control-label" for="name">Email</label>
              <input id="email" name="email" class="form-control" type="text" v-model="email">
              <span id="helpBlock" class="help-block" v-if="attemptSubmit && missingEmail">Email is invalid.</span>
            </div>

             <div class="form-group" v-bind:class="{ 'has-warning': attemptSubmit && missingMessage }">
              <label class="control-label" for="message">Enter a Message</label>
              <textarea  name="message" class="form-control" type="text" v-model="message"></textarea>
              <span id="helpBlock" class="help-block" v-if="attemptSubmit && missingMessage">This field is required.</span>
            </div>                 
            
            <button class="btn btn-primary">Submit</button>
          </form>
        </div><!-- /col -->

         <div class="col-md-8" v-if="postStatus">

           <h1>The form is submitted successfully.</h1>

         </div> 
      </div><!-- /row -->

    </div><!-- /container -->
</template>

<script>

import axios from 'axios'
  
  export default {   
    data () {
      return {
        name: '',
        email: '',
        message: '',
        number: '',
        attemptSubmit: false,
        postStatus: false
      }
    },
    computed: {
        missingName: function () { return this.name === '' },
        missingMessage: function () { return this.message === '' },
        missingEmail: function () {
          return (
            this.isEmail(this.email) === null)
        },
        wrongNumber: function () {
          return (
            this.isNumeric(this.number) === false ||
            this.number < 1 ||
            this.number > 10
          )
      },
  },
  methods: {
     isNumeric: function (n) {
      return !isNaN(parseFloat(n)) && isFinite(n);
    },
    isEmail: ( str ) => {      
      let regexp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/     
      return str.match(regexp);
    },       
    validateForm: function (event) {
      this.attemptSubmit = true;
      if (this.missingName || this.wrongNumber || this.missingMessage || this.missingEmail) {
          event.preventDefault();
      } else {
         this.onSubmit();
      }       
    },
    onSubmit () {
    
       if (process.env.NODE_ENV === 'development') {
                axios.defaults.baseURL = 'http://localhost:8888/your-project-name/php'
        }

       axios.post('post.php', {
                'name': this.name,
                'email': this.email,
                'message': this.message,
                'number': this.number               
            }).then(response => {
                if (response.data.error) {
                    console.log('error', response.data.error)
                } else {
                    this.postStatus = true
                    console.log('success', response.data.message)                   
                }
            }).catch(error => {
                console.log(error.response)
            }); 
      }
  }   
}
</script>

Source: Form Validation with Vue.js

Wednesday, August 16, 2017

How to Dockerize a Node.js app?

The goal of this example is to show you how to get a Node.js application into a Docker container. In this article we'll show you how to create a Docker image for an application written in Node.js.

Why should I dockerize my application
You might've heard about the whole Docker thing, but that still doesn't answer the question: "why bother?" Well, that's why:

1. You can launch a fully capable development environment on any computer supporting Docker; you don't have to install libraries, dependencies, download packages, mess with config files etc.
2. The working environment of the application remains consistent across the whole workflow. This means the app runs exactly the same for developer, tester, and client, be it on development, staging or production server.

In short, Docker is the counter-measure for the age-old response in the software development: "Strange, it works for me!"

Part 1: Create the Node.js app
In the first part of this guide we will create a simple web application in Node.js, then we will build a Docker image for that application, and lastly we will run the image as a container.

Install Node.js
If you've never worked with Node.js before, kick off with installing the npm manager: nodejs.org/en/download/package-manager

Install NPM and Express Framework
First, create a new directory 'helloworld' where all the files would live and initialize npm.
 $ mkdir helloworld 
 $ cd helloworld
 $ npm init
When asked for the details of the application (name, version, etc.), just confirm the default values with enter.

Npm will create a package.json that will hold the dependencies of the app. Let's add the Express Framework as the first dependency:
 $ npm install express --save
The file should look like this now:
{
  "name": "helloworld",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.15.2"
  }
}
With everything installed, we can create a server.js file that defines a web app using the Express.js framework with a simple HTTP server that will serve our Hello World website:
//Load express module with `require` directive
var express = require('express')
var app = express()

//Define request response in root URL (/)
app.get('/', function (req, res) {
  res.send('Hello World!')
})

//Launch listening server on port 8081
app.listen(8081, function () {
  console.log('app listening on port 8081!')
})
Run the app
The application is ready to launch:
  $ node server.js
Go to http://localhost:8081/ in your browser to view it.

Part 2: Dockerizing Node.js application
Every application requires a specific working environment: pre-installed applications, dependencies, data bases, everything in specific version. Docker containers allow you to create such environments. Contrary to VM, however, the container doesn't hold the whole operating system—just applications, dependencies, and configuration. This makes Docker containers much lighter and faster than regular VM's.

In this part of the article, we'll look at how you can run this app inside a Docker container using the official Docker image.

Install Docker
Docker allows you to package an application with all of its dependencies into a standardized unit, called a container, for software development. A container is a stripped-to-basics version of a Linux operating system. An image is software you load into a container.

Begin with installing Docker for your type of OS: Docker installation

Write Dockerfile
The Docker image is created with instructions written in the Dockerfile. Let's add Dockerfile to the directory with our application. Create an empty file called Dockerfile:
 touch Dockerfile
Open the Dockerfile in your favorite text editor. The first thing we need to do is define from what image we want to build from.
Line 1: Use another Docker image for the template of my image. We shall use the official Node.js image with Node v8.
 FROM node:8.3.0
Line 2: Set working dir in the container to /app. We shall use this directory to store files, run npm, and launch our application:
 # Create app directory
 WORKDIR /app
Line 3-5: Copy application to /app directory and install dependencies. If you add the package.json first and run npm install later, Docker won't have to install the dependencies again if you change the package.json file. Please note that if you are using npm version 5 or later you will also want to copy package-lock.json, which is generated once you run npm install. This results from the way the Docker image is being built (layers and cache), and this is what we should do:
 # Install app dependencies
 COPY package.json /app

 # For npm@5 or later, copy package-lock.json as well
 # COPY package.json package-lock.json /app

 RUN npm install
Note that, rather than copying the entire working directory, we are only copying the package.json file. This allows us to take advantage of cached Docker layers.
To bundle your app's source code inside the Docker image, use the COPY instruction:
 # Bundle app source
 COPY . /app
Your app binds to port 8081 so you'll use the EXPOSE instruction to have it mapped by the docker daemon:
 EXPOSE 8081
Last but not least, define the command to run your app using CMD which defines your runtime. This line describes what should be executed when the Docker image is launching. What we want to do is to run our application:
 CMD node server.js
Summing up, the whole Dockerfile should look like this:
 FROM node:8.3.0

 # Create app directory
 WORKDIR /app

 # Install app dependencies
 COPY package.json /app

 # For npm@5 or later, copy package-lock.json as well
 # COPY package.json package-lock.json /app

 RUN npm install

 # Bundle app source
 COPY . /app

 EXPOSE 8081
 CMD node server.js

.dockerignore file
Create a .dockerignore file in the same directory as your Dockerfile with following content:
 node_modules
 npm-debug.log
This will prevent your local modules and debug logs from being copied onto your Docker image and possibly overwriting modules installed within your image.

Build Docker image
Go to the directory that has your Dockerfile and run the following command to build the Docker image. The -t flag lets you tag your image so it's easier to find later using the docker images command:
 $ docker build -t hello-world .
Run the image
The application has been baked into the image. Dinner time! Execute the following string to launch the container and publish it on the host with the same port 8081:
 $ docker run -p 8081:8081 hello-world
Running your image with -p flag redirects a public port to a private port inside the container.

Print the output of your app
# Get container ID
$ docker ps

# Print app output
$ docker logs 

# Example
  app listening on port 8081!

We hope this tutorial helped you get up and running a simple Node.js application on Docker.

Sources:
Dockerizing a Node.js web app
How to Dockerize a Node.js application