-
Notifications
You must be signed in to change notification settings - Fork 7
Documentation
If you're new to Iugo - the best place to get started is the tutorials page.
The Iugo
constructor is used to create an object which represents the supplied model except with listeners attached to handle updates to the model.
new Iugo(model, view, viewcontroller);
The Iugo
constructor accepts three arguments (but is commonly only called with the first):
model:
- Any Javascript Object representing the data model
- Required!
- Values which are not null will act as default values
For example:
var model = {
id: 817,
user: {
name: "chris",
dateOfBirth: "31st March 1984",
address: {
street: "1 Sesame Street",
city: "London"
}
},
friends: [
"Bob",
"Bill",
"Ben",
"Betty"
],
interests: {
books: [
{
title: "20 thousand leagues under the sea",
author: "Jules Verne",
isbn: 92341
}
]
}
};
View:
- An element from the DOM
- Will act as a scope for any view-controller actions
- If omitted,
document.body
will act as the view
To limit the scope of the Iugo
object to an element with the id "view" you would use:
var view = document.getElementById('view');
Viewcontroller:
- An associative array of functions
- For each top level member of the model, if an equivalent key exists, a function from the viewcontroller is executed when that part of the model is updated
- The viewcontroller methods are passed a single argument, which is the new value assigned to the model's member
- Plugins provide "default view-controllers" which handle actions such as binding the model to the DOM.
This view controller would log a message each time the "key" object was updated:
var viewcontoller = {
key: function(value) {
console.log("The key has been updated to " + value);
}
};
There are two parts HTML binding. Firstly applying a class to an element of the form class="bindto-member"
. This will attach the content of model.member
to that node in the DOM. In the case where model.member
is a primitive type, you're done. If, however, model.member
is an Object
or an Array
there are some additional steps.
<div class="bindto-id"></div>
will become
<div class="bindto-id>817</div>
To bind a value from an Object
you can apply the attribute data-bind_key="path.to.value"
to either the element in question or any children of that element. For each element with the attribute, model.member.path.to.value
will be set as the innerHTML
.
<div class="bindto-user">
<span data-bind_key="name"></span>
</div>
will become
<div class="bindto-user">
<span data-bind_key="name">Chris</span>
</div>
To bind the values from an Array
to the DOM there is an additional attribute: data-bind_each
. This must be applied to a child of the element with the bindto-member
class. iugo will copy this node for each entry in the array, then process the new node as normal.
<ul class="bindto-friends">
<li data-bind_each></li>
</ul>
will become
<ul class="bindto-friends">
<li data-bind_each>Bob</li>
<li data-iugo_cloned>Bill</li>
<li data-iugo_cloned>Ben</li>
<li data-iugo_cloned>Betty</li>
</ul>
data-bind_key="path"
attributes can be used on any element in the DOM tree under a node which has been bound with a bindto-member
class. For example:
<div class="bindto-user" data-bind_key="address.city"></div>
<div class="bindto-interests">
<ul data-bind_key="books">
<li data-bind_each>
<span data-bind_key="title"></span>
</li>
</ul>
</div>
As well as binding the whole innerHTML
of a node, one can use an inline variable to inject values from the model into a page. Variables can be used both in the text of a document and in attributes of HTML tags.
The syntax has two variants, a simple flavour which is relative to it's closest bound parent and a namespaced flavour which lets one access any part of the model.
The simple flavour of variables is written as follows:
${relative.path}
This syntax addresses data relative to a bound node. So:
<div class="bindto-user">${name} lives in ${address.city}</div>
becomes:
<div class="bindto-user"><span data-bind_key="name">Chris</span> lives in <span data-bind_key="address.city">London</span></div>
Similarly, these variables can be placed inside attribute values:
<div class="bindto-user"><img src="/images/users/${name}" alt="${name}"></img></div>
becomes:
<div class="bindto-user"><img src="/images/users/Chris" alt="Chris"></img></div>
NB. iugo maintains an index of where attributes have been bound, so if you update the model - changing name
to "Sam", for example - the attributes are updated to match.
There may be times when you need to access data from multiple areas in the model - so cannot rely upon relative paths. For example, if you wanted to create a link to the URL /Chris/wishlist/add?isbn=92341
, you would not be able to use the simple flavour or variables. For this use-case, one can access data using a namespace, where the namespace refers to a top level member of the model and the address is relative to that. For example:
<ul class="bindto-interests" data-bind_key="books">
<li data-bind_each>
<a href="/${user:name}/wishlist/add?isbn=${isbn}"></a>
</li>
</ul>
Consider the following example:
<ul class="bindto-friends">
<li data-bind_each />
<ul>
In that case, the name of each friend
is bound to the innerHTML
of the li
. If you need a more complex DOM structure you will need to reference the current level of the model within the loop - i.e. a variable which points to the friend's name. That variable is addressed using a dot: ${.}
.
<ul class="bindto-friends">
<li data-bind_each>
<a href="http://example.com/friend/${.}">See ${.}'s page</a>
</li>
<ul>
There are some cases, primarily when referencing a URL, that bound attributes can cause issues. Consider the img
tag example:
<div class="bindto-user"><img src="/images/users/${name}" alt="${name}"></img></div>
While this works effectively, the user may notice an exception in their browser's console if the browser tries to retrieve an image from "/images/users/${name}", getting a 404, before iugo has made the substitution. The browser will still pick up the correct image a fraction of a second later but developers don't like errors, do we?
So, for the benefit of a cleaning up those 404s, there is an alternative method of binding attributes. Any attribute which starts with the prefix data-iugo_alias-
will bind to the attribute as if the prefix were dropped. So,
<div class="bindto-user"><img data-iugo_alias-src="/images/users/${name}" alt="${name}"></img></div>
Would still bind "/images/users/Chris" to the scr
attribute but the browser would never see the unprocessed template in the src tag. Perfect!