< Previous Article Next Article >

Vue.js Apps

Vue is a progressive client-side framework for building user interfaces. It is designed to be incrementally adoptable. The core library is focused on the view layer only, and is easy to pick up and integrate with other libraries or existing projects.

Hello World in Vue

<html>
  <head> 
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      {{ message }}
    </div>
    <script src="public/app.js"></script>
  </body>
</html>
// app.js file
var app = new Vue({ 
  el: '#app',
  data: {
    message: 'Hello World!'
  }
});

Vue Template Syntax

Vue's mustache syntax ({{ }}) allows you to place data into HTML content. As the data changes, the content is updated automatically.

<div id="app">
  {{ message }}
</div>

In addition, Vue provides a number of special directives prefixed with v-.

v-bind and v-model

Another way to provide dynamic content is to add the v-bind directive to an HTML attribute.

<input type="text" v-bind:value="initialValue" />

Because of v-bind, initialValue above is now a dynamic JavaScript property. Vue also allows you to simply use :value as a shortcut for v-bind:value.

If we want an input value to update our data automatically (e.g. two-way binding on an input field), we can use the v-model directive.

<input type="text" v-model="value" />

v-if

v-if is used to add conditional logic to your HTML content.

<span v-if="visible">Some Text</span>

Once the visible property is set to false, the <span> is removed from the DOM.

v-for

Loops and repeating content are created using v-for. For example:

<div id="app">
  <ol>
    <li v-for="todo in todos">
      {{ todo.text }}
    </li>
  </ol>
</div>
var app = new Vue({
  el: '#app',
  data: {
    todos: [
      { text: 'Learn JavaScript' },
      { text: 'Learn Vue' },
      { text: 'Build something awesome' }
    ]
  }
})

v-on

v-on can be used to attach event listeners that invoke Vue methods.

<div id="app">
  <p>{{ counter }}</p>
  <button v-on:click="increment">Increment Counter</button>
</div>
var app = new Vue({
  el: '#app',
  data: {
    counter: 0
  },
  methods: {
    increment: function () {
      this.counter++;
    }
  }
})

You can also use @click as a shortcut for v-on:click.

Vue Components

In Vue, you can define custom components like this:

Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: `
    <button v-on:click="count++">You clicked me {{ count }} times.</button>
  `
})

Components are reusable:

<div id="app">
  <p> First counter: <button-counter></button-counter> </p>
  <p> Second counter: <button-counter></button-counter> </p>
</div>

Interacting with the Server and the Database

Unlike a stateful application, where the flow is controlled by server-side code, Vue controls the flow of the application exclusively from client-side code.

In order to access the database, you must call out to the server via an AJAX request, which is a background request initiated by the browser to the server.

There are several techniques for initiating an AJAX request. Some of these techniques may require additional libraries like jQuery. However, in most recent browsers, a promise-based API called fetch() is now available, which allows you to make AJAX requests without any special library.

var app = new Vue({ 
  el: '#app',
  mounted() {
    this.message = "Loading Products...";
    fetch("getProducts")
    .then(response => response.json())
    .then(data => {
      this.list = data;
      this.message = null;
    })
    .catch(error => {
      this.message = error;
    })
  },
  data: {
    message: null,
    list: []
  }
});
<div id="app">
  <h1>Product List</h1>
  <p v-if="message" class="message">{{message}}</p>
  <ul v-else>
    <li v-for="item in list">{{item.productName}} - ${{item.buyPrice}}</li>
  </ul>
</div>
// Server-side code to access the database
function getProducts(request, response) {
  var products = pjs.query("SELECT productName, buyPrice FROM products");
  response.send(products);
}
exports.default = getProducts;

For a complete example, visit https://noderun.com/alex/vue-product-list/ or launch it here: https://noderun.com/run/alex/vue-product-list/.

Using Vue with Rich Displays

Rich Displays greatly simplify Vue development because you can create your components visually in a point-and-click manner.

With Rich Displays, you can create a component using widgets in the Visual Designer, and then use the <rich-display> Vue component tag to reference it. A Rich Display component can be as simple as one or two widgets, or as complex as an entire screen.

Here is a simple Customer Grid being created in the Rich Display Visual Designer:

Screenshot

Once the design is saved, we can write a wrapper component called <customers> that fetches data into the grid.

Vue.component('customers', {
  data() {
    return {
      customerGrid: [],
      key: 0
    }
  },
  mounted() {
    fetch("getCustomers")
    .then(response => response.json())
    .then(data => {
      this.customerGrid = data;
      this.key++;
    })
  },
  template: `
    <rich-display path="public/app.json"
                  screen="customers"
                  :key="this.key"
                  :data="{ customerGrid: this.customerGrid }">
    </rich-display>
  `
});

<customers> embeds <rich-display> and passes the necessary props: path, screen, key and data. The data and key props are dynamic JavaScript values.

Now, let's add a Customer panel in the Visual Designer.

Screenshot

We'll then add the <customer-panel> wrapper component to load data into the panel.

Vue.component('customer-panel', {
  data() {
    return {
      customerPanelData: {},
      key: 0
    }
  },
  created() {
    setTimeout(() => { app.getCustomer = this.getCustomer }, 0);
  },
  methods: {
    getCustomer(custNum) {
      fetch("getCustomer?custNum=" + custNum)
      .then(response => response.json())
      .then(data => {
        this.customerPanelData = data;
        this.key++;
      })
    }
  },
  template: `
    <rich-display path="public/app.json"
                  screen="customerPanel"
                  :key="this.key"
                  :data="this.customerPanelData">
    </rich-display>
  `
});

We now have a full customer inquiry application.

Screenshot

If we ever need to add columns to the grid or additional database fields to the panel, we can do this easily in the Visual Designer without having to touch a line of code.

For the complete example, visit https://noderun.com/alex/using-visual-designer-with-vue/, or try the app by visiting https://noderun.com/run/alex/using-visual-designer-with-vue/.

Using Vue on NodeRun

An easy way to get started with Vue on NodeRun is to select one of the Vue templates presented when you're creating a new space.

Screenshot

You can also fork other Vue spaces you find on the NodeRun community site.

The templates and spaces provide the basic configuration for a Vue application, which includes a starting HTML file that loads the Vue library. By default, NodeRun spaces use the in-browser version of Vue during development. However, when you're ready to deploy a production application, it is advised that you precompile your Vue code using the Vue CLI (Command Line Interface).

Learning Vue

This document outlines Vue at a very high level. If you're new to Vue, you will likely want to find other resources to practice and gain a much deeper understanding of what Vue is capable of. You can start by referencing the offical Vue.js site (https://vuejs.org) and then proceed to find other online tutorials.

You can use NodeRun.com and its IDE as your playground for learning and experimenting with Vue in a full-stack environment. The Visual Designer available in the NodeRun IDE can help you build practical Vue components faster.

Questions?

Have questions about this topic? Ask for help on our NodeRun Discussion Forum.

< Previous Article Next Article >