<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[vue - JBay Solutions - The Dev Blog]]></title><description><![CDATA[JBay Solutions Development Blog on Java, Android, Play2 and others]]></description><link>http://blog.jbaysolutions.com/</link><generator>Ghost 0.7</generator><lastBuildDate>Wed, 16 Oct 2024 01:15:04 GMT</lastBuildDate><atom:link href="http://blog.jbaysolutions.com/tag/vue/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Vue.js quick start guide]]></title><description><![CDATA[<h1 id="vuejsv10xquickstartguide">Vue.js (v1.0.x) quick start guide</h1>

<p><em><strong>NOTE</strong>: We plan to update this guide to Vue 2.0 when the final release is out</em></p>

<p>Like most software companies which create web applications, we develop frontends with HTML and Javascript. <br>
Having mostly used jQuery on our applications, we felt there</p>]]></description><link>http://blog.jbaysolutions.com/2016/09/16/vue-js-quick-start-guide/</link><guid isPermaLink="false">9141f0f7-10e0-43a8-8c0b-e45fd1fa69c0</guid><category><![CDATA[javascript]]></category><category><![CDATA[vue]]></category><category><![CDATA[vue.js]]></category><category><![CDATA[frontend]]></category><dc:creator><![CDATA[Gustavo Santos]]></dc:creator><pubDate>Fri, 16 Sep 2016 13:29:18 GMT</pubDate><media:content url="https://vuejs.org/images/logo.png" medium="image"/><content:encoded><![CDATA[<h1 id="vuejsv10xquickstartguide">Vue.js (v1.0.x) quick start guide</h1>

<img src="https://vuejs.org/images/logo.png" alt="Vue.js quick start guide"><p><em><strong>NOTE</strong>: We plan to update this guide to Vue 2.0 when the final release is out</em></p>

<p>Like most software companies which create web applications, we develop frontends with HTML and Javascript. <br>
Having mostly used jQuery on our applications, we felt there had to be an easier and less verbose way develop web frontends.   </p>

<p>The problem is...there literally hundreds of javascript libraries/frameworks out there, with new showing up every day!</p>

<p>After lots of searching and reading, we settled on <a href="http://vuejs.org/">Vue.js</a>. Although its relatively recent Vue.js seemed like a great choice. </p>

<p>Since the core library is only a view layer and doesn't force you to build a complete SPA (single page application), it means we could just start using it some components on our existing web applications.  </p>

<h2 id="documentation">Documentation</h2>

<p>Vue provides a very good <a href="https://vuejs.org/guide/index.html">official documentation</a>, which we recommend you start with.</p>

<h2 id="oursetup">Our Setup</h2>

<p>On our apps, the most basic setup always includes Vue, <a href="https://github.com/vuejs/vue-resource/">vue-resource</a> for http requests, and <a href="https://github.com/vuejs/vue-validator">vue-validator</a> for form validation </p>

<p>Since we are not using webpack or any other module bundler, we just import the js files using a script tag.</p>

<pre><code class="language-markup">    &lt;script src="javascripts/vue/vue.js"&gt;&lt;/script&gt;
    &lt;script src="javascripts/vue/vue-resource.js"&gt;&lt;/script&gt;
    &lt;script src="javascripts/vue/vue-validator.js"&gt;&lt;/script&gt;
</code></pre>

<h3 id="debuganddevtools">Debug and Devtools</h3>

<p>When on the developing environment, we enable these <a href="http://vuejs.org/api/#Global-Config">Vue global configs</a>:</p>

<pre><code class="language-javascript">     Vue.config.debug = true;
     Vue.config.devtools = true;
</code></pre>

<p>This will enable stack traces and allow using the <a href="https://github.com/vuejs/vue-devtools">vue-devtools</a> browser extension.  </p>

<h3 id="pageexample">Page example</h3>

<p>On each page, we create a div template, like explained in the Vue guide:</p>

<pre><code class="language-markup">    &lt;div id="app"&gt;
        {{ message }}
    &lt;/div&gt;
</code></pre>

<p>And on the js script loaded for that page:</p>

<pre><code class="language-javascript">    new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue.js!'
      }
    })
</code></pre>

<p>It's highly recommended to give a different id to each template, it's pretty common for builds to concat and uglify multiple js files into one. <br>
If you have multiple templates with the same id, there will be conflicts when binding Vue instances to the templates.</p>

<h3 id="vcloak">v-cloak</h3>

<p>We highly recommend including the <a href="http://vuejs.org/api/#v-cloak">v-cloak</a> directive in every template. This way, uncompiled bindinds will not be diplayed while the page loads:</p>

<p>Just include this rule on your css:</p>

<pre><code class="language-css">    [v-cloak] {
      display: none;
    }
</code></pre>

<p>Using the same page as before:</p>

<pre><code class="language-markup">    &lt;div id="app" v-cloak&gt;
        {{ message }}
    &lt;/div&gt;
</code></pre>

<p>You can check the working sample <a href="https://jbaysolutions.github.io/vue-quick-start-samples/vue-sample-page.html">here</a> </p>

<h2 id="vueresource">vue-resource</h2>

<p><a href="https://github.com/vuejs/vue-resource">vue-resource</a> is a plugin for Vue that provides for making web requests and handle responses using a XMLHttpRequest or JSONP. </p>

<p>We use it extensively when using Vue, mostly for HTTP GET and POST requests. There are other methods and options available, for more details check the official vue-resource docs.</p>

<h3 id="get">GET</h3>

<p>This is a basic example of a GET request where we use the Github API to retrieve a list of JBay Solutions organization projects.</p>

<p>You can check the working sample <a href="https://jbaysolutions.github.io/vue-quick-start-samples/vue-resource-example.html#get">here</a> </p>

<pre><code class="language-javascript">     var url = "https://api.github.com/orgs/jbaysolutions/repos";

     // GET request
     this.$http.get(url).then(function (response) {
         this.loading = false;
         // success callback, response.data will contain the data in JSON format

         // get status
         response.status;
         // get status text
         response.statusText;

     }, function (response) {
         // error callback
     });
</code></pre>

<h3 id="post">POST</h3>

<p>This is a basic example of a POST request where we use the jsonplaceholder.typicode.com fake server to send some data.</p>

<p>You can check the working sample <a href="https://jbaysolutions.github.io/vue-quick-start-samples/vue-resource-example.html#post">here</a> </p>

<pre><code class="language-javascript">    var url = "http://jsonplaceholder.typicode.com/posts";

    var data = {
        title: "a title",
        body: "a body",
        userId: 1
    };

    // POST request
    this.$http.post(url, data).then(function (response) {
        // success callback

        // get status
        response.status;
        // get status text
        response.statusText;

    }, function (response) {
        // error callback
    });
</code></pre>

<p>You can also use POST to send forms or upload files using FormData. Details <a href="https://github.com/vuejs/vue-resource/blob/master/docs/recipes.md#forms">here</a></p>

<h2 id="vuevalidator">vue-validator</h2>

<p><a href="https://github.com/vuejs/vue-validator">vue-validator</a> is form validation component for Vue.js.
It comes with a few built in validators:</p>

<ul>
<li>required: whether the value has been specified</li>
<li>pattern: whether the pattern of the regular expression</li>
<li>minlength: whether the length of specified value is less than or equal minimum length</li>
<li>maxlength: whether the length of specified value is less more or equal maximum length</li>
<li>min: whether the specified numerical value is less than or equal minimum</li>
<li>max: whether the specified numerical value is more than or equal maximum</li>
</ul>

<p>Adicional validators can be declared globally or locally on each Vue instance. A global email validator is one we use on most apps:</p>

<pre><code class="language-javascript">    Vue.validator('email', function (val) {
        return /^(([^&lt;&gt;()[\]\\.,;:\s@\"]+(\.[^&lt;&gt;()[\]\\.,;:\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,}))$/.test(val);
    });
</code></pre>

<p>Local validators can be declared inside the validators object on a Vue instance.</p>

<p>The sample below uses both cases, a global email validator and a locally declared validator to check if both passwords match. For more details about custom validatores check the docs <a href="http://vuejs.github.io/vue-validator/en/custom.html">here</a></p>

<p>You can check the working sample <a href="https://jbaysolutions.github.io/vue-quick-start-samples/vue-validator-example.html">here</a> </p>

<p>Since we mostly use Bootstrap for our apps layout, the sample below has is built with conditions to display errors using help blocks.</p>

<pre><code class="language-markup">    &lt;validator name="sampleValidator"&gt;
        &lt;form v-on:submit.prevent="saveUser" novalidate&gt;
            &lt;div class="form-group" v-bind:class="{ 'has-error': $sampleValidator.firstName.invalid &amp;&amp; $sampleValidator.firstName.touched}"&gt;
                &lt;label for="firstName" class="control-label"&gt;First Name *&lt;/label&gt;
                &lt;input class="form-control" type="text" name="firstName" placeholder="" v-model="user.firstName" v-validate:first-name="{ required: true, maxlength: 50 }"/&gt;
                &lt;span class="help-block" v-show="$sampleValidator.firstName.touched &amp;&amp; $sampleValidator.firstName.required"&gt;This field is required.&lt;/span&gt;
                &lt;span class="help-block" v-show="$sampleValidator.firstName.touched &amp;&amp; $sampleValidator.firstName.maxlength"&gt;The max size is 50.&lt;/span&gt;
            &lt;/div&gt;

            &lt;div class="form-group" v-bind:class="{ 'has-error': $sampleValidator.lastName.invalid &amp;&amp; $sampleValidator.lastName.touched}"&gt;
                &lt;label for="lastName" class="control-label"&gt;Last Name *&lt;/label&gt;
                &lt;input class="form-control" type="text" name="lastName" placeholder="" v-model="user.lastName" v-validate:last-name="{ required: true, maxlength: 100 }"/&gt;
                &lt;span class="help-block" v-show="$sampleValidator.lastName.touched &amp;&amp; $sampleValidator.lastName.required"&gt;This field is required.&lt;/span&gt;
                &lt;span class="help-block" v-show="$sampleValidator.lastName.touched &amp;&amp; $sampleValidator.lastName.maxlength"&gt;The max size is 100.&lt;/span&gt;
            &lt;/div&gt;

            &lt;div class="form-group" v-bind:class="{ 'has-error': $sampleValidator.country.invalid &amp;&amp; $sampleValidator.country.touched}"&gt;
                &lt;label for="country" class="control-label"&gt;Country Code&lt;/label&gt;
                &lt;input class="form-control" type="text" name="country" placeholder="" v-model="user.country" v-validate:country="{ maxlength: 3 }"/&gt;
                &lt;span class="help-block" v-show="$sampleValidator.country.touched &amp;&amp; $sampleValidator.country.required"&gt;This field is required.&lt;/span&gt;
                &lt;span class="help-block" v-show="$sampleValidator.country.touched &amp;&amp; $sampleValidator.country.maxlength"&gt;The max size is 3.&lt;/span&gt;
            &lt;/div&gt;

            &lt;div class="form-group" v-bind:class="{ 'has-error': $sampleValidator.mail.invalid &amp;&amp; $sampleValidator.mail.touched}"&gt;
                &lt;label for="email" class="control-label"&gt;Email *&lt;/label&gt;
                &lt;input class="form-control" type="email" name="email" v-model="user.email" v-validate:mail="{ required: true, email: true }"/&gt;
                &lt;span class="help-block" v-show="$sampleValidator.mail.touched &amp;&amp; $sampleValidator.mail.required"&gt;This field is required.&lt;/span&gt;
                &lt;span class="help-block" v-show="$sampleValidator.mail.touched &amp;&amp; $sampleValidator.mail.email &amp;&amp; !$sampleValidator.mail.required"&gt;The email address is not valid.&lt;/span&gt;
            &lt;/div&gt;

            &lt;div class="form-group" v-bind:class="{ 'has-error': $sampleValidator.password.invalid &amp;&amp; $sampleValidator.password.touched}"&gt;
                &lt;label for="password" class="control-label" &gt;Password *:&lt;/label&gt;
                &lt;input type="password" class="form-control" name="password" v-model="user.password" v-validate:password="{ required: true, minlength: 6, maxlength: 10 }"&gt;
                &lt;span class="help-block" v-show="$sampleValidator.password.touched &amp;&amp; $sampleValidator.password.required"&gt;This field is required.&lt;/span&gt;
                &lt;span class="help-block" v-show="$sampleValidator.password.touched &amp;&amp; $sampleValidator.password.minlength &amp;&amp; !$sampleValidator.password.required"&gt;Please enter at least 6 characters.&lt;/span&gt;
                &lt;span class="help-block" v-show="$sampleValidator.password.touched &amp;&amp; $sampleValidator.password.maxlength"&gt;The max size is 255.&lt;/span&gt;
            &lt;/div&gt;

            &lt;div class="form-group" v-bind:class="{ 'has-error': $sampleValidator.confirmPassword.invalid &amp;&amp; $sampleValidator.confirmPassword.touched}"&gt;
                &lt;label for="confirmPassword" class="control-label" &gt;Confirm password *:&lt;/label&gt;
                &lt;input type="password" class="form-control" name="confirmPassword" v-model="confirmPassword" v-validate:confirm-password="{ required: true, passwordValidator: { rule: user.password }}"&gt;
                &lt;span class="help-block" v-show="$sampleValidator.confirmPassword.touched &amp;&amp; $sampleValidator.confirmPassword.required"&gt;This field is required.&lt;/span&gt;
                &lt;span class="help-block" v-show="$sampleValidator.confirmPassword.touched &amp;&amp; $sampleValidator.confirmPassword.passwordValidator &amp;&amp; !$sampleValidator.confirmPassword.required"&gt;The passwords don't match.&lt;/span&gt;
            &lt;/div&gt;

            &lt;button class="btn btn-primary" type="submit"&gt;Add&lt;/button&gt;
        &lt;/form&gt;
    &lt;/validator&gt;
</code></pre>

<p>When the form is submited, we only save the user if the form is valid:</p>

<pre><code class="language-javascript">    saveUser: function () {
        this.$validate(true);
        if (this.$sampleValidator.valid) {
            // save the user
        }
    },
</code></pre>

<!--## File upload?-->

<h2 id="ourcustomcomponents">Our custom components</h2>

<p>Below are the components we most commonly use on our apps: </p>

<h3 id="datepicker">Datepicker</h3>

<p>This datepicker component is a wrapper for <a href="https://eternicode.github.io/bootstrap-datepicker/">bootstrap-datepicker</a>. <br>
The lib js and css files need to be included in your html.</p>

<pre><code class="language-markup">    &lt;script src="js/bootstrap-datepicker.js" type="text/javascript"&gt;&lt;/script&gt;
    &lt;link rel="stylesheet" media="screen" href="css/bootstrap-datepicker3.css")"&gt;
</code></pre>

<p>Below is the full component source: </p>

<pre><code class="language-javascript">    var datepickerComponent = Vue.extend({
        template: '&lt;div class="input-group date" v-el:inputgroup&gt;' +
        '   &lt;input type="text" class="form-control" v-model="value"&gt;' +
        '   &lt;span class="input-group-addon"&gt;&lt;i class="glyphicon glyphicon-calendar"&gt;&lt;/i&gt;&lt;/span&gt;' +
        '&lt;/div&gt;',
        props: {
            value: ''
        },
        data: function () {
            return {};
        },
        watch: {
            value: function () {
                this.datepicker.datepicker("update", this.value);
            },
        },
        ready: function () {
            this.datepicker = $(this.$els.inputgroup).datepicker({
                format: 'yyyy-mm-dd',
                autoclose: true
            });
        }
    });

    Vue.component('datepicker', datepickerComponent);
</code></pre>

<p>And to use it:</p>

<pre><code class="language-markup">    &lt;datepicker :value.sync="myDate"/&gt;
</code></pre>

<h3 id="bootstrapselect">bootstrap-select</h3>

<p>This select component is a wrapper for <a href="https://silviomoreto.github.io/bootstrap-select/">bootstrap-select</a></p>

<p>The lib js and css files need to be included in your html.</p>

<pre><code class="language-markup">    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.11.2/js/bootstrap-select.min.js"&gt;&lt;/script&gt;
    &lt;link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.11.2/css/bootstrap-select.min.css"&gt;
</code></pre>

<p>Below is the full component source:</p>

<pre><code class="language-javascript">    var bSelectComponent = Vue.extend({
        //v-el:select
        template: '&lt;select v-el:select&gt;' +
        '   &lt;option v-for="item in items" value="{{item.value}}"&gt;{{item.text}}&lt;/option&gt;' +
        '&lt;/select&gt;',
        props: {
            value: "",
            items: [],
        },
        data: function () {
            return {};
        },
        watch: {
            items: function () {
                var select = $(this.$els.select);
                select.selectpicker("refresh");
                select.selectpicker("val", this.value);
            },
            value: function () {
                var select = $(this.$els.select);
                if (this.value !== select.selectpicker("val")) {
                    select.selectpicker("val", this.value);
                }
            }
        },
        ready: function () {
            var select = $(this.$els.select);
            select.selectpicker();
            select.selectpicker("val", this.value);
            var self = this;
            select.on("changed.bs.select", function () {
                self.value = select.selectpicker("val");
            });
        }
    });
    Vue.component('b-select', bSelectComponent);
</code></pre>

<p>And to use it:</p>

<pre><code class="language-markup">    &lt;b-select :value.sync="myValue" :items="itemList"/&gt;
</code></pre>

<p>Where itemList is an array of objects:</p>

<pre><code class="language-javascript">[
    {
        "text": "Item 1",
        "value": "1"
    },
    {
        "text": "Item 2",
        "value": "2"
    },
    {
        "text": "Item 3",
        "value": "3"
    },

]
</code></pre>

<p>To enable any of the js component options, like live search, you can use it like this:      </p>

<pre><code class="language-markup">    &lt;b-select :value.sync="myValue" :items="itemList" data-live-search="true"/&gt;
</code></pre>

<h3 id="vuegridlayout">vue-grid-layout</h3>

<p>A draggable and resizable grid layout, for Vue.js.</p>

<p>We developed this component to be used primarily in our SaaS app <a href="https://www.draxed.com/?utm_source=blog&amp;utm_medium=web&amp;utm_campaign=vue-grid-layout">Draxed</a>.</p>

<p>Read all about it <a href="https://github.com/jbaysolutions/vue-grid-layout">HERE</a>.</p>

<h3 id="vuebootstraptable">vue-bootstrap-table</h3>

<p>A sortable and searchable table, as a Vue component, using bootstrap styling.</p>

<p>We developed this component to be used primarily in our SaaS app <a href="https://www.draxed.com/?utm_source=blog&amp;utm_medium=web&amp;utm_campaign=vue-bootstrap-table">Draxed</a>.</p>

<p>Read all about it <a href="https://github.com/jbaysolutions/vue-bootstrap-table">HERE</a>.</p>]]></content:encoded></item></channel></rss>