Uncaught Error: No Iron.Layout found so you can't use yield
Asked Answered
E

2

6

Using Meteor 0.9.3 and iron:router 1.0.0-pre2, this error shows on the console even though iron:layout was installed, see below:

willems-mini:iron willem$ meteor add iron:router@=1.0.0-pre2
added iron:location at version 1.0.0-pre2
added iron:dynamic-template at version 1.0.0-pre2
added iron:router at version 1.0.0-pre2
added iron:layout at version 1.0.0-pre2
added iron:middleware-stack at version 1.0.0-pre2
added iron:url at version 1.0.0-pre2
added iron:controller at version 1.0.0-pre2
added iron:core at version 1.0.0-pre2

iron:router: Routing specifically designed for Meteor

There are no other packages, just the defaults for meteor:

willems-mini:iron willem$ meteor list
autopublish      1.0.0  Publish the entire database to all clients
insecure         1.0.0  Allow all database writes by default
iron:router      1.0.0-pre2  Routing specifically designed for Meteor
meteor-platform  1.1.1  Include a standard set of Meteor packages in your app

I am trying to run a very simple app:

1 javascript file:

Router.route('/', function () {
    this.render('home');
});

if (Meteor.isClient) {
    Template.home.events({
        'click button': function () {
            console.log('click!');
        }
    });
}

and 1 html file:

<head>
    <title>iron router test</title>
</head>

<body>
    {{> defaultLayout}}
</body>


<template name="defaultLayout">
    <header>
        {{> yield "header"}}
    </header>

    <article>
        {{> yield}}
    </article>

    <footer>
        {{> yield "footer"}}
    </footer>
</template>


<template name="home">
    {{#contentFor "header"}}
        <button>click header</button>
    {{/contentFor}}

    <button>click</button>

    {{#contentFor "footer"}}
        <button>click footer</button>
    {{/contentFor}}
</template>
Elkin answered 30/9, 2014 at 12:38 Comment(0)
S
8

This is not how iron:router layouts are supposed to work.

Get rid of your explicit inclusion of the layout in the body :

{{! this is WRONG, remove the body tag altogether }}
<body>
    {{> defaultLayout}}
</body>

The place where your specify the layoutTemplate is in the RouteController :

Router.route('/', function () {
  this.render('home');
},{
 layoutTemplate:"defaultLayout" 
});

Declaring explicitly your RouteControllers is usually a nicer design pattern.

lib/router.js

Router.route("/",{
  // give the route a name so it figures out itself to use :
  // - HomeController
  // - a template name "home"
  name:"home"
});

lib/controllers/lib/default-layout.js

DefaultLayoutController=RouteController.extend({
  layoutTemplate:"defaultLayout"
});

lib/controllers/home.js

HomeController=DefaultLayoutController.extend({
  //
});
Smitty answered 30/9, 2014 at 12:46 Comment(2)
This solved the problem (thanks), however, it leaves me with one other question: I am a bit surprised to find that clicks that originate from the named yield regions ('header' and 'footer') do not end up as events for the 'home' template. I can only see these click events in the event handler of the 'defaultLayout' template. Is there a way to get these events noticed in the 'home' template event handler?Elkin
Just found a way to do this: I used the new iron-router feature to define event handlers on the route controller. This way I can get all 'home' template events in one place.Elkin
P
2

Well, like your error says you're missing an iron layout.

Could look something like this in your lib/router.js or wherever you hold your router code:

Router.configure({
    layoutTemplate: 'layout',
    loadingTemplate: 'loading'
});

And so the respective <template name="layout"> should be there.

Preservative answered 30/9, 2014 at 12:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.