Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagejs
// injected refs
var $log, $scope, wss, ks;

// constants
var dataReq = 'sampleCustomDataRequest',
    dataResp = 'sampleCustomDataResponse';

The dataReqNote that the request and response event strings follow the convention of using the view ID as a prefix. This guarantees that our event names will be distinct from those of any other view.

Defining the Controller 

We'll skip over the helper functions for the moment and focus on the controller:

Code Block
languagejs
angular.module('ovSampleCustom', [])
    .controller('OvSampleCustomCtrl', 
    [ '$log', '$scope', 'WebSocketService', 'KeyService',
 
    function (_$log_, _$scope_, _wss_, _ks_) { 
        ...
    }]);

The first line here gets a reference to the registers our "ovSampleCustom" module with angular, (the empty array states that our module is not dependent on any other module). Again, this is note the naming convention in play; the module name should start with "ov" (lowercase) followed by the identifier for our view, in continuing camel-case.

The controller() function is invoked on the returned module reference to define our controller. The first argument – "OvSampleCustomCtrl" – is the name of our controller, as registered with angular. Once again, the naming convention is to start with "Ov" (uppercase 'O') followed by the identifier for our view (continuing camel-case), followed by "Ctrl". The second argument is an array...

All the elements of the array (except the last) are the names of services to be injected into our controller function at run time. Angular uses these to bind the actual services to the specified parameters of the controller function (the last item in the array).

...

Inside our controller function, we start by saving injected references inside our closure, so that they are available to other functions. We also initialize our state:

Code Block
languagejs
$log = _$log_;
$scope = _$scope_;
wss = _wss_;
ks = _ks_;

;

 

We also initialize our state; our map of event handlers, and the initial cached "data" from the server.

Code Block
languagejs
var handlers = {};
$scope.data = {};

...

Next, we need to tell the WebSocketService which callback function to invoke when a "sampleCustomDataResponse" event arrives from the server:

Code Block
languagejs
// data response handler
handlers[dataResp] = respDataCb;
wss.bindHandlers(handlers);

The callback function (one of the helper methods we skipped earlier) has the job of setting our scope variable data to be the payload of the event, (which is passed in as the first parameter to the function), and then prodding angular to re-process:, (so, for example, the {{ }} substitutions get updated with the new data):

Code Blockcode
languagejs
function respDataCb(data) {
    $scope.data = data;
    $scope.$apply();
}

...

The map entries use well-known logical keys to identify the keystroke (in this example 'space' for the space-bar), with a value being a two-element array defining ; the first element is a callback function reference, and the second element is the text to display in the Quick Help panel, for the corresponding key.

The _helpFormat key is a special value that is used by the Quick Help Service to lay out the definition of bound keystrokes; each sub-array in the main array is a "column" in the panel; the entries in each sub-array define the order in which the keys are listed.

...

The getData() function tells the WebSocketService to send the data request event to the server:

Code Block
languagejs
function getData() {
    wss.sendEvent(dataReq);
}

Since no second parameter is provided for the sendEvent() call, the web socket service defaults to sending an empty payload along with the event.

 

Remember the ng-click attribute in the "button" div in our HTML snippet? Well, here we set the function reference on our scope, to bind to that element's click handler:

...

Code Block
languagecss
linenumberstrue
collapsetrue
/* css for sample app view */

#ov-sample-custom {
    padding: 20px;
}
.light #ov-sample-custom {
    color: navy;
}
.dark #ov-sample-custom {
    color: #88f;
}

#ov-sample-custom .button-panel {
    margin: 10px;
    width: 200px;
}

.light #ov-sample-custom .button-panel {
    background-color: #ccf;
}
.dark #ov-sample-custom .button-panel {
    background-color: #444;
}

#ov-sample-custom .my-button {
    cursor: pointer;
    padding: 4px;
    text-align: center;
}

.light #ov-sample-custom .my-button {
    color: white;
    background-color: #99d;
}
.dark #ov-sample-custom .my-button {
    color: black;
    background-color: #aaa;
}

#ov-sample-custom .number {
    font-size: 140%;
    text-align: right;
}

#ov-sample-custom .quote {
    margin: 10px 20px;
    font-style: italic;
} 

It This should be fairly self-explanatory. However, note the use of the .light and .dark classes to change color selections based on each of the GUI's themes.

...

The final piece to the puzzle are the two "glue" files used to patch references to our client-side source into index.html. These files are located in the ~src/main/resources directory. They must be named css.html

...

and js.html respectively, so the framework can find them.

css.html

This is a short snippet that is injected into index.html. It contains exactly one line:

...

Code Block
languagexml
 <script src="app/view/sampleCustom/sampleCustom.js"></script>

 

Summary

Obviously, this sample page doesn't do anything particularly useful, but it should serve as a template of how to stitch things together to create your own custom views. Just remember to follow the naming convention – generally, using your view ID as a prefix to DOM elements, event names, and other "public" identifiers.

Have fun creating your own views!