//

EMBER & HANDLEBARS

Before getting into handlebars, let's look at how routing works in Ember.js. Router is solely responsible for all URLs in Ember.

Linking to Routes

Router is solely responsible for all URLs in Ember. Let's inspect the app.js and index.html files.

app.js

App.router.map(function() {
    this.route('about');
});

index.html

<a href="#">Home</a>
<a href="#/about">About</a>

It is considered a bad practice to do this. We don't hard code URL paths. Instead, we ask the routes for their path.

The Handlebars link-to helper

Use the route name to look up the path

{{#link-to 'index'}}Homepage{{/link-to}}
{{#link-to 'about'}}about{{/link-to}}

The link-to will determine the path based on the route name. The code above will generate the following HTML:

<a href="#/" class="ember-view" id="ember2">Homepage</a>
<a href="#/about" class="ember-view" id="ember3">About</a>

Extra Attributes

How to add a custom class to our link.

{{#link-to 'index' class='nav-brand'}Home{{/link-to}}

The above code will be rendered from template into

<a href="#/" class="ember-view" id="ember2">Homepage</a>

tagName option

How to change the HTML element

{{#link-to 'index' tagName='li'}Home{{/link-to}}
{{#link-to 'about' tagName='li'}
About{{/link-to}}

The above code will be rendered from template into

<li class="ember-view" id="ember1">Home
<li class="ember-view" id="ember2">About

Notice how href disappeared and now it is a list instead of a link. But the click still works as Ember adds click handlers.

Template Variables

You can use properties in your template, like the productsCount below

<script type='text/handlebars' data-template-name='index'>
    There are {{productsCount}} products        
</script>

How do you set a property for use in a template?

Ember Controller

Ember COntroller provides properties for the template. Ember Controller is where a template looks to find a property value. It decorates your applications data for the template and contains information that is not saved to a server.

Asking the Controller:

<script type='text/x-handlebars' data-template-name='index'>
    There are {{productsCount}} products
</script>

Above code looks for a controller named IndexController, and the property inside it.

App.IndexController = Ember.Controller.extend({
    productsCount: 5
});

Every Route has a Default Controller

Consider the code below:

App.Router.map(function() {
    this.route('about');
});

Behind the scenes, Ember creates this About controller.

App.AboutController = Ember.Controller.extend({ });

If we want to declare properties that get rendered inside a template, then we can declare this Controller.

Binding with Metamorph

<script type='text/x-handlebars' data-template-name='index'>
    There are {{productsCount}} products
</script>

This will render as below:

There are
    <script id="metamorph-2-start" type="text/x-placeholder"></script>
    5
    <script id="metamorph-2-end" type="text/x-placeholder"></script>
    products

Ember needs to wrap properties so it can potentially update it later. (AKA. Binding)

How to Bind Attributes

<script type='text/x-handlebars' data-template-name='index'>
    There are {{productsCount}} products
    <img {{bind-attr src='logo'}} alt='Logo' />
</script>

In the rendered html, Ember meta data is still added to enable binding. (data-nindattr-1)

<img src="/images/logo.png" data-bindattr-1="1">

Dynamic Content

How do we fetch the current time?

<script type='text/x-handlebars' data-template-name='index'>
    Rendered on {{time}}
</script>

We need to create a property that calls this function:

(new Date()).toDateString()

This is more then just a value, we need to execute some code to get the value.

Controller Functions

We need to tell Ember this is a property and to call it

App.IndexController = Ember.Controller.extend({
    productsCount: 6,
    logo: '/images/logo.png',
    time: function() {
        return;
    }
});

Controller Functions as Properties

<script type='text/x-handlebaaprps.'js data-template-name='index'>
Rendered on {{time}}
</script>

time will be called, and that value used as a property

App.IndexController = Ember.Controller.extend({
    productsCount: 6,
    logo: '/images/logo.png',
    time: function() {
        return
    }
});

Linking to Routes

Router is solely responsible for all URLs in Ember.

app.js

App.router.map(function() {
    this.route('about');
});

index.html

<a href="#">Home</a>
<a href="#/about">About</a>

It is considered a bad practice to do this. We don't hard code URL paths. Instead, we ask the routes for their path.

The Handlebars link-to helper

Use the route name to look up the path

{{#link-to 'index'}}Homepage{{/link-to}}
{{#link-to 'about'}}about{{/link-to}}

The link-to will determine the path based on the route name. The code above will generate the following HTML:

<a href="#/" class="ember-view" id="ember2">Homepage</a>
<a href="#/about" class="ember-view" id="ember3">About</a>

Extra Attributes

How to add a custom class to our link.

{{#link-to 'index' class='nav-brand'}Home{{/link-to}}

The above code will be rendered from template into

<a href="#/" class="ember-view" id="ember2">Homepage</a>

tagName option

How to change the HTML element

`html {{#link-to 'index' tagName='li'}Home{{/link-to}} {{#link-to 'about' tagName='li'} About{{/link-to}}


The above code will be rendered from template into

```html
<li class="ember-view" id="ember1">Home
<li class="ember-view" id="ember2">About

Notice how href disappeared and now it is a list instead of a link. But the click still works as Ember adds click handlers.

Template Variables

You can use properties in your template, like the productsCount below

<script type='text/handlebars' data-template-name='index'>
    There are {{productsCount}} products        
</script>

How do you set a property for use in a template?

Ember Controller

Ember COntroller provides properties for the template. Ember Controller is where a template looks to find a property value. It decorates your applications data for the template and contains information that is not saved to a server.

Asking the Controller:

<script type='text/x-handlebars' data-template-name='index'>
    There are {{productsCount}} products
</script>

Above code looks for a controller named IndexController, and the property inside it.

App.IndexController = Ember.Controller.extend({
    productsCount: 5
});

Every Route has a Default Controller

Consider the code below:

App.Router.map(function() {
    this.route('about');
});

Behind the scenes, Ember creates this About controller.

App.AboutController = Ember.Controller.extend({ });

If we want to declare properties that get rendered inside a template, then we can declare this Controller.

Binding with Metamorph

<script type='text/x-handlebars' data-template-name='index'>
    There are {{productsCount}} products
</script>

This will render as below:

There are
    <script id="metamorph-2-start" type="text/x-placeholder"></script>
    5
    <script id="metamorph-2-end" type="text/x-placeholder"></script>
    products

Ember needs to wrap properties so it can potentially update it later. (AKA. Binding)

How to Bind Attributes

<script type='text/x-handlebars' data-template-name='index'>
    There are {{productsCount}} products
    <img {{bind-attr src='logo'}} alt='Logo' />
</script>

In the rendered html, Ember meta data is still added to enable binding. (data-nindattr-1)

<img src="/images/logo.png" data-bindattr-1="1">

Dynamic Content

How do we fetch the current time?

<script type='text/x-handlebars' data-template-name='index'>
    Rendered on {{time}}
</script>

We need to create a property that calls this function:

(new Date()).toDateString()

This is more then just a value, we need to execute some code to get the value.

Controller Functions

We need to tell Ember this is a property and to call it

App.IndexController = Ember.Controller.extend({
    productsCount: 6,
    logo: '/images/logo.png',
    time: function() {
        return;
    }
});

Controller Functions as Properties

<script type='text/x-handlebaaprps.'js data-template-name='index'>
    Rendered on {{time}}
</script>

time will be called, and that value used as a property

App.IndexController = Ember.Controller.extend({
    productsCount: 6,
    logo: '/images/logo.png',
    time: function() {
        return
    }
});