Simulation Development

Data

Data is used to manipulate slides, widgets and score an exam. There are several ways to handle data.

Data Types

There are two types of data you will create within Hammer, slide properties and model properties.

Slide Properties

Slide properties are properties local to the slide the are in. They are not accessible outside of the slide. They are also not persistent. When a slide no longer exists, the values set to properties also cease to exist. Properties can be bound, updated and removed at anytime while the slide is in existence. A slide property syntax looks like this:

my_property
Model Properties

Model properties are properties global. They are accessible outside of the slide. They are persistent and can be stored and restored. A model property syntax looks like this:

path/to/my/file::my_property
Comparison Chart - Slide vs Model Properties
Slide Properties Model Properties
Local done
Global done
Bindable done done
Session Persistence done
State Store / Restore * done
* Requires compatible Hammer package

When should I use Slide vs. Model properties?

If you need the data to persist, meaning you need to restore the state, use models. If you only need a property to exist for a slide while its in display, use a Slide property. If the change in one slide will affect how another slide displays its content, use a model.

Data Binding

Data binding establishes a connecting to a property and a UI element. It is similar to an event listener, but rather than dispatching an event, it updates the display. We use {{ }} curly braces to bind to data. This is how AngularJS creates the binds. Hammer extends this behavior to support its own format.

Example Binding To A Property

The following example will bind a label to a slide's property.

<h:label>{{my_property}}</h:label>
Example Binding To A Model

Behind-the-scenes: If you try the following:

<div>{{my_property}}</div>

You will see the following on the screen:

{%my_property%}

That is because Hammer converts the {{ }} to {% %} to prevent conflicts and unnecessary parsing by Angular when the items are not running. Most bound properties will be encapsulated in h:label.

Setting default values in properties

To set default values you need to create a h:properties tag in h:virtual. Inside h:properties you can create any number of properties. Properties support nesting as well.

<h:properties>
    <my_property>Hello, world!</my_property>
    <example>
        <of>
            <nesting>Hello, world</nesting>
        </of>
    </example>
</h:properties>

The parser will automatically convert strings, booleans and numbers to their proper type. A property that is defined without a value is set as undefined.

Properties CAN CONTAIN ${string} tags but CANNOT CONTAIN {{binding}} properties or <%= expression %> tags.

Arrays

There are two ways you can define arrays. If you already have more than one item you would like to define in the array you can create a property like so:

<h:properties>
    <my_list>1</my_property>
    <my_list>2</my_property>
    <my_list>3</my_property>
</h:properties>

You can optionally use [] square brackets as a shortcut. Any type you place in the [] will be converted. The values must be well-formed JSON objects.

<h:properties>
    <my_list>[1,2,3]</my_list>
</h:properties>

Here is another example containing many different object types:

<h:properties>
    <my_list>["Test", 1, true, false, {"message": "Hello, world"}]</my_list>
</h:properties>
JSON Objects

Like arrays you can declare an object using {} curly braces. The values must be well-formed JSON objects.

<h:properties>
     <my_obj>{"message": "Hello, world"}</my_obj>
 </h:properties>

Modifying properties

There are a variety of actions Hammer provides to modify data. We are only going to focus on one method. Refer to the Actions to learn other ways. To update a property we can use the h:set action in a h:function, like so:

<h:function name="update">
   <h:set property="path.to.my.property">Goodbye</h:set>
</h:function>

Use dot syntax to reference nested properties.

Model properties

Models work like properties, except you create them in an external file. Typically, you will create your models is the models directory. Models are loaded automatically as they are referenced in code. The reference indicates the path to the model and the property.

Referencing a model
path/to/my/file::my_property

The url is relative to sandbox/index.html. If the model path does not exist, it will indicate this in the console but will not prevent the exam from running. It will assume you wanted to create a virtual model.

Note: Virtual models will still be persisted in the production environment.

Declaring a model

Open sandbox/models/app.xml. There you will see an example of a model. You will notice the namespace declaration:

<root xmlns="http://certiport.com/hammer/sdk/model"></root>

Hammer uses this information to know that is file represents a strings XML file. The xmlns is required by Hammer. It it is not declared will throw an error if it is missing.

timer Exercise: Data Binding

In this exercise, we will bind a text input with a label.

Launch in your browser http://localhost:8080/sandbox/#/tutorials/data/data_start. It should open a page with "Data Binding Tutorial" displayed.

Open sandbox/slides/tutorials/data/binding_start.html in seed-exam in your editor.

We are going to add two widgets, an h:text and a h:label, both bound to the same property using {{ }} curly braces. In doing so they will be "bound" to each other and by modifying the content in the text input, the h:label will reflect the change.

Add the following lines to binding_start.html:

<h:text class="input" value="{{name}}"></h:text>
<h:label>Hello, {{name}}!</h:label>

In your browser, refresh your page. As you type in the input you will see the label update.

timer Exercise: Defining default properties

In the previous, we bound to a property that was not declared. A value did not exist until we actually typed in the input box. Our label's initial display looked like this

Hello,!

Let's now add a default property so the label. Create a default property using the h:properties tag, by inserting the following code:

<h:virtual>
    <h:properties>
        <name>John</name>
    </h:properties>
</h:virtual>

Your initial display will now look like this:

Hello, John!