This is part II of the coServ tutorial. Part I explains how to use coServ CLI to create a web app. It also describes how to create a palet to display TODO items. This article will show you how to implement the controller of a palet, so your palet can interact with users. It will also show how to import existing UI components. Importing UI components and reuse them can greatly simplify your app.
To quickly generate the UI we want without spending too much energy to describe them, we use the bootstrap framework to build the UI needed in this tutorial. You may need to check the bootstrap documentation if you’re not familiar with it. However, it should be noted that coServ is not bounded with bootstrap. coServ basically works with all the un-opinionated JS libraries and CSS frameworks.
Implement palet controller
You can add a palet controller by implementing the exports.control() function inside a palet file.
exports.control = function(p) { p.click = function(event) {
let li = $(event.currentTarget)
itemIndex = li.data('index')
li.tab('show') alert( li.text() )
}
}
The function is given a palet instance (p) as the first parameter. In the example code, we add a controller function click() as the event handler when users click on a TODO item. The click() function will find out what is the event target by $(event.currentTarget), and highlight the item with li.tab(‘show’). To see if things are running correctly, we bring up an alert to display the title of the selected TODO item.
With the event handler ready, we need to register this handler to the TODO items. This can be done by calling the on() function of the HTML element which represents a TODO item:
.on('click', 'this.click')
The first argument ‘click’ denotes the event we’re listening to. The second argument ‘this.click’ points to the handler function. Using ‘this’ to indicate the palet controller.
Now let’s zoom out a little bit and see how an event controller is actually registered with a HTML element:
Line 13 says we’ll listen to the ‘click’ event on each TODO item and the event should be directed to the palet controller function click() which is defined in exports.control().
Now reload the page and click on any of the TODO items, you’ll see something like:
Importing existing components
We’ve successfully registered an event handler to a HTML element. The handler popups an alert to display the title of the selected item. It works, but not pretty. Our next step is to use a bootstrap modal dialog to show the details of a TODO item.
Bootstrap is a very useful tool and we love it, but sometimes it’s just a bit tedious to use. Check below to see the HTML code needed just to create a modal dialog skeleton:
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Modal body text goes here.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
Without too many bootstrap components, your HTML code can be easily jammed with layers of <div> tags. What’s more, by mistakenly missing just one <div> tag, your code could fail without any hints. It’s too painful to debug such HTML codes.
coServ is here for the rescue. coServ allows you to define any Bootstrap component as UIC (UI Component). Once you get a UIC to work once, you can use it as many times as you like. No more worries about mistyping one of the many <div> tags. Better yet, the resulting code will be much more readable and maintainable. Let’s see how to invoke UICs in a coServ palet:
The first line tells coServ to import a bootstrap component package from the uic directory in you web app directory. Once the package has been imported, you can create an UIC instance by calling it’s create() function as shown in line 15. Line 15 will create a modal dialog from the bootstrap component package we imported at line 1:
become.create('Modal', 'todoModal', modalData)
The first argument ‘Model’ tells coServ to create a Modal component out of the imported package (a UIC package could have many components available). The second argument assigns ‘todoModal’ as the ID of the created UIC. The third argument is the required input to an UIC. In the sample code shown above, we can see the input data to a Modal dialog is defined as:
let modalData = {
title: 'My TODO Item',
body: xs.e('h5', 'Will display a TODO item here...'),
primaryBtn: 'Confirm',
closeBtn: true
}
Without digging into the definition, let’s just assume the modal UIC will work properly and it will have a title showing ‘My TODO Item’ as we said so. It will also have a primary button showning ‘Confirm’ and a close button being displayed. The body part of a Modal UIC should display the details of a TODO item. In the beginning, it will be default to a header tag (<h5>Will display a TODO item here…</h5>). The xs.e() function is how you create a HTML elemnt in coServ.
With the palet view function modified, we still need to modify the palet controller so it will invoke our newly implemented Modal dialog instead of the alert popup. See the code below:
Compared with controller codes written in the beginning of this tutorial, line 8 is the only code changed. Line 8 says it will bring up the Bootstrap Modal dialog. Everything looks good, right? Wait a minute! Where does_todoModal come from? When is this variable defined?
The _todoModal variable which points to a Modal UIC instance is created in exports.view(). Remember in exports.view(), we create the Modal UIC by this line of code:
bscomp.create('Modal', 'todoModal', modalData)
The second argument indicates the created UIC instance will be assigned an ID as ‘todoModal’. A nice thing about coServ is that it will automatically (and inherently) declare a variable in the palet controller for each UIC instance created in the view function. The variable name will be the UIC ID prepended by ‘_’. With that, developers can easily refer to any UIC instance created in the view() function. The same feature also works for embedded palet. We’ll see how to embed palettes later in this tutorial.
Now let’s reload the ‘/todo/list’ page, and click on any TODO items to see the new feature:
That looks better than an alert, but we still need to show the selected TODO item in the modal dialog. That’s what we’ll do next.
Embedded palets
The plan is to use another palet to display the details of a selected TODO item. The new palet will be ‘/todo/view’ and we’ll embed that palet in the dialog body. Let’s summarize the user story as:
A user click on a TODO item to see its details.
So, let’s create the ‘/todo/view’ palet. You can create a “palets/todo/view.xs” file under the web app theme directory. For this “view” palet, we’ll leverage the Bootstrap horizontal form component to display the detailed information of a TODO item. When you create a web app with the coServ CLI tool, an UIC package containing the Bootstrap horizontal form will be added to your web app and ready to be used. Below is the source code of view.xs:
The above sample code should be self-explanatory. The key is to import the ‘/bs4/components/form’ UIC package and create a horizontal form with this line of code:
bsform.create('Horizontal', 'mbody', {items: formItems} )
The rest is to specify what form control will be used to display each TODO item property, and allow the Bootstrap horizontal form to do the presentation thing. In the example, four properties (title, start time, done time, and done) of a TODO item will be displayed. How those properties should be displayed is defined in the formItems array.
Ok. We’re done with the part II of the tutorial.
If the bootstrap UIC sounds too magical, you can explore its source code to see how it works. The source code will be in the “uic/bs4/components” directory of your web app. We use bootstrap UIC in the tutorial so we can make sure the main points are clearly delivered. Or we may be tangled up with layers of <div> tags in the example code.
Articles of this tutorial: