Skip to content

Commit

Permalink
Test and document evaluated tag attributes.
Browse files Browse the repository at this point in the history
Closes #113.
  • Loading branch information
flatheadmill committed Jun 24, 2013
1 parent 9a3192d commit 242db87
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 0 deletions.
113 changes: 113 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,119 @@ serialize to older HTML flavors for older browsers.
On the browser, when we generate Stencil XML, we simply import it into the
existing DOM using `Document.adoptNode`.

## Tag Libraries

Using the same language as used in templates, Stencil supports the creation of
tag libraries. With tag libraries you can doe more to hide the complexity of a
template. You can create tags that name collections in application domain.

## Creating Evaluated Tag Properties

Sometimes you will want to specify an evaluated property in your tags. We have a
tricky trick for your tag defintion that will give you want you want. When you
want the user to provide you with a statement that you can use in an `each` or
`value` directive, do a double evaluation in your tag library.

Here is a minimal example, we're going to create an alias for the `value`
directive named `say` that has an evaluated called `stuff`. As you can see, we
use an evaluated attribute for the `select` attribute of the `value` directive
in the tag. The evaulated select attribute will use the `stuff` attribute passed
to the tag.

```xml
<s:include xmlns:s="stencil">
<s:tag name="say">
<s:value s:select="$attribute.stuff"/>
</s:tag>
</s:include>
```

When the template author is ready to say stuff, he invokes the `say` tag with an
ordinary `stuff` attribute, he doesn't have to know that it's evaluated.

The attribute `stuff` has a value of `"1 + 1"`. That is not evaluated. It is
passed into the tag as `$attributes.stuff`. Inside the tag, `$attributes.stuff`
has a string value of `"1 + 1"`. The evaluated `select` attribute of value
evaluates `$attributes.stuff` and creates a `select` attribute for the `value`
directive with a string value of `"1 + 1"`.

```xml
<html xmlns:s="stencil" xmlns:t="inc:_tags.xml">
<body>
<p><t:say stuff="1 + 1"/></p>
</body>
<html>
```

The `value` attribute will then evaluate the `select` attribute, unaware and
unconcerned that it was once an evaluated attribute. It's not a static attribute
as far as the `value` attribute is concerned. It evaluates the JavaScript
statement `1 + 1` and gets `2`.

Here is the output.

```html
<html>
<body>
<p>2</p>
</body>
<html>
```

You'd probably want to use `select` as your attribute, instead of `stuff`
because it follows convention and requires less explanation. We use `stuff` in
the example above to make it easier to pick out the working parts.

Here's a slightly more complicated, every-so-slightly more realistic example.
Here we put our select attribute into an evaluated select attribute of an `each`
directive. We're creating a `loopy` tag.

```xml
<s:include xmlns:s="stencil">
<s:tag name="loopy">
<s:each s:select="$attribute.select" as="item">
<s:tag name="item" select="item"/>
</s:each>
</s:tag>
</s:include>
```

Here's how we use it with the object `{ numbers: [ 1, 2, 3 ] }`. As you can see,
we pass in the string `"numbers"` in a select attribute. It does not get
evaluated. It is passed into the tag as the property `$attributes.select`. The
value of `$attributes.select` will be the string `"numbers"`.

When we use an evaluated `select` attibute with the `each` directive, it
evaluates to the value of `$attibute.select` with is `"numbers"`. That creates a
select value for the `each` directive that is `"numbers"`. That is evaluated by
the `each` directive to obtain the numbers array.

```xml
<html xmlns:s="stencil" xmlns:t="inc:_tags.xml">
<body>
<ul>
<t:loopy select="numbers">
<li><t:item/></li>
</t:loopy>
</ul>
</body>
<html>
```

Which gives us the html.

```html
<html>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</body>
</html>
```

## Remember

* It's not a query tool. It's a templating tool.
Expand Down
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
compiled = functions[source];
if (!compiled) {
parameters.push.apply(parameters, Object.keys(context));
console.log(parameters, source);
functions[source] = compiled = {
parameters: parameters,
expression: Function.apply(Function, parameters.concat([ "return " + source ]))
Expand Down
9 changes: 9 additions & 0 deletions t/tags/fixtures/_evaluated.stencil
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<s:include xmlns:s="stencil">
<s:tag name="loop">
<ul>
<s:each s:select="$attributes.select" s:into="$attributes.as">
<li><s:value s:select="$attributes.display"/></li>
</s:each>
</ul>
</s:tag>
</s:include>
5 changes: 5 additions & 0 deletions t/tags/fixtures/evaluated.stencil
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html xmlns:s="stencil" xmlns:e="inc:_evaluated.stencil">
<body>
<e:loop select="items" as="item" display="item.value"/>
</body>
</html>
8 changes: 8 additions & 0 deletions t/tags/fixtures/evaluated.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<html>
<body>
<ul>
<li>1</li>
<li>2</li>
</ul>
</body>
</html>

0 comments on commit 242db87

Please sign in to comment.