1
votes

I was following this Ember tutorial and this quickly got a lot more complicated. This was the tutorial that I was following.

I am lost as to what is going on. When is the index.hbs getting loaded and why? Here is my code starting with the router.js:

import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

Router.map(function() {
  this.route('todos', { path: '/'}, function() {
    this.route('complete');
    this.route('incomplete');
  });
});

export default Router;

So it looks like our home url will load the todos.js route right? This is my code:

import Ember from 'ember';

export default Ember.Route.extend({
  model() {
    let todos = [
      {
        title: 'Learn Ember',
        complete: false,
      },
      {
        title: 'Solve World Hunger',
        complete: false,
      }
    ];
    return todos;
  }
});

So this todos.js route is my model right?

I assume ember also loads the todos.hbs template by default? Is that right? Or does it load the app/templates/todos/index.hbs? Which one does it load?

This is my app/templates/todos.hbs code:

<input type="text" id="new-todo" placeholder="What needs to be done?" />
{{#todo-list todos=model}}
    {{outlet}}
{{/todo-list}}

This is my app/templates/todos/index.hbs code:

<ul id="todo-list">
    {{#each model as |todo|}}
         <!-- this loads the component todo-item and passes in a todo as todo -->
        {{todo-item todo=todo}}
    {{/each}}
</ul>

The tutorial doesn't really explain what is going on here. If the index.hbs gets loaded, does it then load the todo-item component template? If so, this is my app/templates/components/todo-item.hbs:

<input type="checkbox" class="toggle" checked="{{if todo.complete 'checked'}}">  
<label class="{{if todo.complete 'completed'}}">{{todo.title}}</label><button class="destroy"></button>

In the event that the app/templates/todos.hbs gets loaded...What is going on in the app/templates/todos.hbs? Are we passing in the model (somehow accessible in the template?) as todos to the todo-list component? Here is the app/templates/components/todo-list.hbs

<section id="main">
    {{yield}}

    <input type="checkbox" id="toggle-all">
</section>

<footer id="footer">
    <span id="todo-count">
        <strong>2</strong> todos left
    </span>
    <ul id="filters">
        <li>
            <a href="all" class="selected">All</a>
        </li>
        <li>
            <a href="active">Active</a>
        </li>
        <li>
            <a href="completed">Completed</a>
        </li>
    </ul>

    <button id="clear-completed">
        Clear completed (1)
    </button>
</footer>
1
You have a lot of questions here. I think several of them can be answered by the Ember routing guide, specifically the section on defining routes.GJK

1 Answers

2
votes

Welcome to the wonderful world of Emberjs! first of all, I recommend you to visit the official page of Emberjs. Can you see the sidebar menu? well, be ready to spend some time reading it if you want to understand how Emberjs works. I strongly recommend you to read at least Router, Template, Component and Controller sections to begin with.

Let's see some of the snippets you have provided:

Router.map(function() {
  this.route('todos', { path: '/'}, function() {
    this.route('complete');
    this.route('incomplete');
  });
});

This is where you define your routes. Here what you have is the main route called 'todos' but used as the root page (starting at /). After it, there are two more routes: /complete and /incomplete.

model() {
    let todos = [
      {
        title: 'Learn Ember',
        complete: false,
      },
      {
        title: 'Solve World Hunger',
        complete: false,
      }
    ];
    return todos;
  }

Here you are defining a model in one route (I assume is the route of todos). Pretty straight, isn't it? if you were using Ember Data for example. you would ask the server for the model here and the route would wait until receive the response.

The reason why you have an index template and a todos template is simple: todos.hbs will contain the {{outlet}} in which every page will be rendered. Imagine it as a wrapper. Whatever comes after / will be wrapped by this todos.hbs, even the index.hbs. You have more info here, in the guides (reason why I recommend you to read it first).

Let's move to another snippet:

{{#todo-list todos=model}}
    {{outlet}}
{{/todo-list}}

Here you are using a component to wrap whatever is rendered in the {{outlet}}. You haven't pasted it here, but it should contain in its template at least a {{yield}} to specify where the {{outlet}} will be rendered. That info about {{yield}} can be found here.

Let's move to the next part:

ul id="todo-list">
    {{#each model as |todo|}}
         <!-- this loads the component todo-item and passes in a todo as todo -->
        {{todo-item todo=todo}}
    {{/each}}
</ul>

This {{#each}} handlebar, expressed in a block way (that's why it uses the # at the beginning and the / at the end), is a loop that allows you work with each item of your model, defined as todo. What you are doing here is to provide the component todo-item with one item of the model. If your model has 3 todos, todo-item will be rendered 3 times, one for each of them.

Again, I recommend you to follow that tutorial having the emberjs guides opened and whenever you have a doubt, check the guides until you understand the concept and then, move to the next step.