Skip to content

Exploring components

Stuk edited this page Mar 8, 2013 · 13 revisions
  1. Quick Start
  2. Exploring Components
  3. Hello Montage

Components make up the view portion of a Montage application.

While Montage itself includes a variety of pre-built user interface components, a custom Montage application employs the same component mechanism to help build and organize its interface.

Montage components are modular and encapsulated; the structure (HTML), appearance (CSS) and behavior (JavaScript) that power the component are all contained in the same directory. These directories end with a .reel extension, just like a regular file, to indicate that it is an isolated unit.

This modularity means that wherever a component is used, the same HTML will dictate how is is structured, the same CSS will dictate how it looks, and the same JavaScript will dictate how it behaves. Since a component is self-contained, it's easy to work on, rename, or even remove a single component without having to find bits and pieces of it scattered across different directories.

Inside the directory from the Quick Start guide run the minit command to create a new component

$ minit create:component --name name-tag
name-tag.reel created.
$ cd ui/name-tag.reel/
$ ls 
name-tag.css   name-tag.html  name-tag.js

The first thing to notice is that we put all our components in the ui directory. This convention allows you to use any Montage package and easily locate the components it provides.

Let's step through the files, and some of the notable features in each of them.

HTML

<link rel="stylesheet" type="text/css" href="name-tag.css">

The CSS is included, just as you would normally.

<script type="text/montage-serialization">
{
    "owner": {
        "properties": {
            "element": {"#": "name-tag"}
        }
    }
}
</script>

The serialization is where most of the action occurs in a Montage template. We will explore it further in a later tutorial, but here are a few things to note:

  • the type is set to text/montage-serialization
  • the serialization is just JSON, with some enforced semantics
  • owner is a special label in the serialization that refers to the current component. It's the equivalent of this in Javascript.
  • within the serialization you can use {"#": "montage-id"} to refer to elements in the body
  • although not shown here, you can also use {"@": "label"} to refer to another object by its label in the serialization
<body>
    <div data-montage-id="name-tag" class="NameTag">
    </div>
</body>

While each template is a complete and valid document, only one element serves as the root element of the component being described. The serialization identifies the element with the data-montage-id of name-tag as this component's root element using the {"#": "name-tag"} reference.

This means that when we use a NameTag component in a Montage application the only portion of its template that will be rendered is the name-tag element. This also explains why we do not use the document unique HTML id attribute to identify the element. (why data-montage-id?).

CSS

.NameTag {

}

The CSS starts off blank, ready for you to style. Notice that the class name is a CamelCased version of the reel name. This is part of our CSS naming convention that allows us to scope each component's CSS so that it doesn't "leak out" and accidentally style other components.

Javascript

var Montage = require("montage").Montage,
    Component = require("montage/ui/component").Component;

Montage uses the CommonJS module system, just like Node.js, through Mr.

exports.NameTag = Montage.create(Component, {

});

The file exports a single object with a CamelCased version of the reel name, which inherits from Component. Montage.create() is a special version of Ecmascript 5's Object.create() that has some extensions that we'll explore later.

In use the NameTag Component will be rendered in a document using its element from its included template, styled using its included CSS, and given instructions on how to act from its included JavaScript.

#All Together Now

No component is an island; they are assembled to present the User Interface of your Montage application.

With your name tag component in hand say Hello to Montage


Why data-montage-id? The id attribute seems like an ideal candidate for identifying an element, however there are some issues. We don't use id because our components are reusable, and so when they are inserted into a document multiple times there would be multiple elements with the same id, which is invalid HTML5. Why not remove the id when inserting? Although you should always use classes to style your document, we don't want to prevent ids being used for styling, either for performance or legacy reasons. This means we can't use the id attribute. Instead we use a custom data- attribute, data-montage-id. When the Shadow DOM gets more mature and is implemented it might be possible to revert back to using id, as each template will be isolated in the document.