Creating your own web-page based Vue.js + Element UI + UB Server #

In this charter we will create a web-page using Vue.js.

Vue.js and Element UI #

Vue.js (pronounced /vjuː/, like view) is a progressive framework for building UI.
Unlike other popular frameworks, to get started, all you have to do is to drop a single script tag into the HTML file:

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

Now you can start writing Vue code.

Element UI is a Vue based component library for developers, designers and product managers. This library has many components, from simple buttons and input fields to carousels and collapses. Also, present bootstrap-like grid layout system.
To use library import JavaScript and CSS files in your page. JS file must be imported after Vue.

<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/element-ui/lib/umd/locale/en.js"></script>

Creating a web-page using Vue.js #

To create a web-page with Vue.js we need to produce steps same as in JQuery lesson:

  • Create a www subdirectory in the project folder and index.html in it
  • Add the "inetPub" property to the "httpServer" section in ubConfig.json

Also, create app.js and add a link to it after closing body tag:

...
</body>
<script src="app.js"></script>
...

And the last preparation step - add links to lodash and UB modules:

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script src="/clientRequire/@unitybase/ub-pub/dist/ub-pub.min.js"></script>

In this point the index.html should look something like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>

    <!-- import CSS -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- import JavaScript -->

    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <script src="https://unpkg.com/element-ui/lib/umd/locale/en.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
    <script src="/clientRequire/@unitybase/ub-pub/dist/ub-pub.min.js"></script>


</head>
<body>
    
</body>
<script src="app.js"></script>
</html>

Development of the Vue app #

The simplest Vue app #

To build the simplest Vue app add:

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

in body section of index.html and

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

to the app.js file.

Try to visit http://localhost:8881 to see what the code above produces.

Extending the page view using the Element UI #

We will use element components(tags that start with el) to declare all needed parts of page.
Put it inside div block with app id.

  • Header menu Header menu

    <el-menu default-active="1" 
              mode="horizontal"
              background-color="#545c64"
              text-color="#fff"
              active-text-color="#ffd04b">
    
            <el-menu-item index="0">
              <a href="https://unitybase.info/" target="_blank">
                  <img alt="Brand" src="https://unitybase.info/img/logo.svg" height="40px"></a>
            </el-menu-item>
    
            <el-menu-item index="1">Home</el-menu-item>
    
            <el-menu-item index="2">
              <a href="https://git-pub.intecracy.com/unitybase/samples/tree/master/courses/tutorial-v5" target="_blank">Tutorials</a>
            </el-menu-item>
    
            <el-menu-item index="3" v-if="!isLogIn">
                <el-button @click="logInFormVisible = true" type="primary">Log in</el-button>
            </el-menu-item>
    
            <el-menu-item index="3" v-else>
                <el-button @click="logout" type="primary">Log out</el-button>
            </el-menu-item>
    
        </el-menu>
    

    v-if directive used to dynamically show or hide element based on condition (user logged or not)

  • Log in dialog

    login

    <el-dialog title="Log in to City Portal"
               :visible.sync="logInFormVisible">
        <el-dialog
                width="30%"
                title="Failed to log in"
                :visible.sync="failedToLogInDialogVisible"
                append-to-body>
        </el-dialog>
        <el-form size="medium">
            <el-form-item label="Login">
                <el-input v-model="form.login" placeholder="Login"></el-input>
            </el-form-item>
            <el-form-item label="Password">
                <el-input type="password" v-model="form.pass" placeholder="Password"
                          @keyup.enter.native="login"></el-input>
            </el-form-item>
            <el-button :loading="isLoading" type="primary" @click="login">Continue</el-button>
        </el-form>
     </el-dialog>
    

    Dialog visible if variable logInFormVisible is true. Also, we declare sub dialog to show it after wrong login credentials.

  • Header

    <el-row type="flex" class="row-bg" justify="center">
        <el-col>
            <div style="display: flex;justify-content: center">
                <h1>{{isLogIn?"Requests":"Welcome to CITY PORTAL!"}}</h1>
            </div>
        </el-col>
    </el-row>
    
  • Table

    Table

    <el-table
            v-show="isLogIn"
            :data="tableData">
        <el-table-column
                prop="ID"
                label="ID">
        </el-table-column>
        <el-table-column
                prop="reqDate"
                label="Request Date">
        </el-table-column>
        <el-table-column
                prop="applicantPhone"
                label="Applicant Phone">
        </el-table-column>
        <el-table-column
                prop="applicantInfo"
                label="Applicant Info">
        </el-table-column>
        <el-table-column
                prop="status"
                label="Status">
        </el-table-column>
        <el-table-column
                prop="reqText"
                label="Request Text">
        </el-table-column>
        <el-table-column
                prop="answer"
                label="Answer">
        </el-table-column>
    </el-table>
    

    :data="tableData" is bind to array of data. If data update, table update automatically.

Extending the page functionality #

Add the following code to app.js:

// if you reload page after login, this variable is true
const wasLogInBeforeReload = localStorage.getItem(location.origin + '/:storedSession') !== null;

const REQ_ENTITY = 'req_reqList';
const REQ_ATTRS = ['ID', 'reqDate', 'applicantPhone', 'applicantInfo', 'status', 'reqText', 'answer'];

//english localisation to element library
ELEMENT.locale(ELEMENT.lang.en);

let Main = {
    data() {
        return {
            form: {
                login: "",
                pass: ""
            },
            logInFormVisible: false,
            failedToLogInDialogVisible: false,
            isLogIn: wasLogInBeforeReload,
            isLoading: false,
            tableData: []
        }
    },
    methods: {
        login: function () {
            this.isLoading = true;
            UB.connect({
                host: window.location.origin,
                allowSessionPersistent: true,
                onCredentialRequired: function (conn, isRepeat) {
                    if (isRepeat) {
                        return Promise.reject(new UB.UBAbortError('invalid password or username'))
                    } else {
                        return Promise.resolve({authSchema: 'UB', login: this.form.login, password: this.form.pass})
                    }
                }.bind(this),
                onAuthorizationFail: function (reason) {
                    this.isLoading = false;
                    this.failedToLogInDialogVisible = true;
                    UB.showErrorWindow(reason);
                }.bind(this),
            }).then(function (conn) {
                this.isLoading = false;
                this.isLogIn = true;
                this.logInFormVisible = false;
                window.$conn = conn;
                this.getRequests()
            }.bind(this))
        },
        logout: function () {
            if (window.$conn) window.$conn
                .logout()
                .then(function () {
                    this.isLogIn = false;
                    this.logInFormVisible = true;
                }.bind(this))
        },
        getRequests: function () {
            window.$conn.Repository(REQ_ENTITY).attrs(REQ_ATTRS).select()
                .then(function (data) {
                    this.tableData = data.map(req => {
                        req.reqDate = req.reqDate.toLocaleDateString('ru-RU');
                        return req;
                    });
                }.bind(this))
        }
    },
    //this part execute after page load
    mounted: function () {
        //auto login and show requests after reload logged page
        if (wasLogInBeforeReload) {
            UB.connect({
                host: window.location.origin,
                allowSessionPersistent: true,
                onAuthorizationFail: function (reason) {
                    UB.showErrorWindow(reason)
                }
            }).then(function (conn) {
                window.$conn = conn;
                this.getRequests();
            }.bind(this))
        }
    }
};
let Ctor = Vue.extend(Main);
new Ctor().$mount('#app');

Now project is available at http://localhost:8881.