Meteor can't find template defined in package - meteor

I am creating a package that should make a layout template available in the application
package/client/templates/boxesLayout.html
<template name="boxesLayout">
<div class="wrapper">
<h1>Test</h1>
</div>
</template>
package/package.js
Package.onUse(function(api) {
api.versionsFrom('1.0.4.1');
api.addFiles([
'client/templates/boxesLayout.html'
]);
api.addFiles('boxes.js');
});
However, when I try to set the layout in a route like this
InboxController = BaseController.extend({
layoutTemplate: 'boxesLayout',
I get an error saying the layout is not defined, any ideas?

You need to use templating in order for a template to be exposed via a package. Modify your package.js to look something like the following:
Package.onUse(function(api) {
api.versionsFrom('1.0.4.1');
api.use('templating', 'client');
api.addFiles('client/templates/boxesLayout.html', 'client');
api.addFiles('boxes.js', 'client');
});
Note that the example adds your files only to the client, which makes sense for templates.

Related

TypeError: Cannot read property <template name> of undefined when creating package

I am trying to create a package for Meteor, unsuccessfully unfortunately. I'm on Meteor 1.8.1. My goal is to make a template for a button that I can use in my application like this {{> testButton}} (I am just trying it out atm).
package.js
Package.describe({
name: 'button-test',
version: '0.0.1',
summary: '',
git: '',
documentation: 'README.md'
});
Package.onUse(function (api) {
api.use(['ecmascript']);
api.use(['session', 'templating'], ['client', 'server']);
api.mainModule('button-test.js');
});
Package.onTest(function (api) {
api.use('ecmascript');
api.use('tinytest');
api.use('button-test');
api.mainModule('button-test-tests.js');
});
button-test.js
// Variables exported by this module can be imported by other packages and
// applications. See button-test-tests.js for an example of importing.
import './testButton.js';
testButton.js
import { Template } from 'meteor/templating';
Template.testButton.events({
'click #buttonT': () =>
console.log('Clicked the button')
});
testButton.html
<template name="testButton"><button id="buttonT">TEST</button></template>
I have some problems with this;
Running the code like this returns the error TypeError: Cannot read property 'testButton' of undefined. So there is a problem with Template, but I don't know what it is, since I have added it with api.use
When I try to add import ./testButton.html to testButton.js I get the error Error: Cannot find module './testButton.html'
I looked at the source code for accounts-ui-unstyled, but this is written on an older meteor version.
Does anybody have an idea as to what I am doing wrong?
The problem was with the api.mainModule, I solved it by having my Package.onUse like this:
Package.onUse(function (api) {
api.use(['templating', 'blaze'], 'client');
api.use('ecmascript');
api.addFiles(['button-test.js'], 'client');
});
After using the addFiles instead of mainModule, I could import the html and the Template problem disappeared. I have no idea why this works and mainModule does not, but hey, it does.

Meteor can't find template that is defined 4 lines later

This code:
//hello.js
import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import './hello.html';
Template.hello.onCreated(function helloOnCreated() {
// counter starts at 0
this.counter = new ReactiveVar(0);
});
Template.hello.helpers({
counter() {
return Template.instance().counter.get();
},
});
Template.hello.events({
'click button'(event, instance) {
// increment the counter when button is clicked
instance.counter.set(instance.counter.get() + 1);
},
});
<!-- hello.html -->
<body>
<h1>Welcome to Meteor!</h1>
{{> hello}}
{{> info}}
</body>
<template name="hello">
<button>Click Me</button>
<p>You've pressed the button {{counter}} times.</p>
</template>
<template name="info">
<h2>Learn Meteor!</h2>
<ul>
<li>Do the Tutorial</li>
<li>Follow the Guide</li>
<li>Read the Docs</li>
<li>Discussions</li>
</ul>
</template>
Returns this error:
Error: No such template: hello
at lookup.js:189
at Blaze.View.<anonymous> (spacebars-runtime.js:32)
at view.js:199
at Function.Template._withTemplateInstanceFunc (template.js:465)
at view.js:197
at Object.Blaze._withCurrentView (view.js:538)
at viewAutorun (view.js:196)
at Tracker.Computation._compute (tracker.js:311)
at new Tracker.Computation (tracker.js:201)
at Object.Tracker.autorun (tracker.js:576)
To prevent this for getting absurdly long, here is the GitHub repo if needed.
In the tutorial the template comes after the call. But for some reason, it won't on my page. If I move the templates above the call, it works, but not after. I'm not sure what I'm doing wrong.
Here is the directory structure as requested. I've just started this project, and hello is the only page at the moment.
You should also add a comment to the top of each file which merely indicates the working directory.
I assume the first snippet of code is the contents of hello.js and the second snippet to be the content of main.html. I also assume that you are NOT showing us the contents of hello.html.
If all these are true, I can see that you are importing hello.html into hello.js BUT you are ALSO referencing hello.html WITHIN main.html. I assume your error is Meteor being confused as to which is the right reference, and grabbing the wrong one.
Clean code tends to separate Meteor templates into their own directories and files anyways. I'd get rid of them from main.html.
UPDATE:
I think your issue is in your main.js, or rather, your routing file.
For starters, it's bad JS practise to import in the middle of the code. Good practise is:
1) Import all absolute paths
2) Add a spacing
3) Import all relative paths
4) Never import after that
Take a good look # BlazeLayout.render which you have added to your project, but haven't used. Attempting to just brazenly import the JS file is never going to work. You need to pass arguments to the render method, which include the template you desire to render.

iron:router doesn't work after updating meteor

I recently updated my meteor project and whenever i try to run my project i got this :
Router.route('/', function () {
this.render('Home', {
data: function () { return Items.findOne({_id: this.params._id}); }
});
});
this is my route that should direct the user to "main" template
Router.route('/', {
template: 'main'
});
i used to get similar problem when i first added iron:router package, and the reason was because i haven't implemented it. I believe the way i should implement it is different after the update. please correct me if am wrong
Your router file needs to be included above or in a folder above your client and server folders. It's just there, if router is not contained above client and server than meteor does not digest it properly for the function it serves.
Short answer:
Put router.js where-ever it is that you start your meteor application.
(as opposed to .\client or .\server)
How you configure main template:
Router.configure({
layoutTemplate:'yourMainTemplateName' //main template should have {{> yield}} inside HTML which tells iron:router where to render templates per route
});
Route configuration:
Router.route('/', function () {
this.render('homeTemplateName');
});
Update your question with your new codes if it doesn't work.

Template helpers in Telescope Package when using Telescope.modules.add

I have been able to insert this template titled lightBox using Telescope.modules.add
The file structure seems to be working fine except I cannot make a template helper to interact with the template thats inserted using Telescope.modules.add function. The following code produces a client side error of "Uncaught TypeError: Cannot read property 'helpers' of undefined". Without this helper method the template is visible and does exist in the browser view.
lightBox.js
if (Meteor.isClient) {
Telescope.modules.add("top", {
template: "lightBox",
order: 0
});
Template.layout.events({
'click .post-content': function (e) {
Session.set('lightBoxPageViewCounter', 1 );
}
});
Template.lightBox.helpers({
lightBoxOn: function() {
return true;
}
});
}
Package.js
Package.describe({
name: "admithub:admithub-lightbox",
summary: "popup lightbox for admit hub forum to college email leads",
version: "0.0.1"
});
Package.onUse(function(api) {
api.use([
'accounts-base',
'stylus',
'telescope:core#0.24.0',
'aldeed:simple-schema',
'aldeed:collection2',
'aldeed:autoform'
]);
api.addFiles('lib/client/lightBox.js', 'client');
api.addFiles('lib/client/lightbox.html', 'client');
api.addFiles('lib/client/lightbox.styl', 'client');
});
Template is named lightBox and exists in the same package within the same directory. I have worked around this by using a global helper methods but this is an inefficient fix.
Your package load order is wrong, you must load the template declaration (html) before the template helpers declaration (js), you just need to swap your api.addFiles calls.
api.addFiles('lib/client/lightbox.html', 'client');
api.addFiles('lib/client/lightBox.js', 'client');

Pass data to a dynamic template

With meteor updates up to 0.8 my old code stopped working.
Handlebars.registerHelper('getTemplate', function(id, context) {
return Template[id](context);
});
<template name="main">
....
{{{getTemplate templateName context}}}
....
</template>
//somewhere in other template
Template.main.context = {name:value};
This way I was able to render a custom template with custom data. Now I can't find the way to pass context to the dynamic template. With blaze both templateName and context is undefined. Any advice?
Meteor >= 0.8.2
You can use the UI.dynamic helper render a template with a context which are both specified dynamically. For more details, check out this issue.
Meteor < 0.8.2
Both of these issues are addressed on this page in the meteor wiki.
Handlebars.registerHelper is now UI.registerHelper as seen here.
Examples of how to dynamically render templates are shown here.
update
Actually, given the requirements, a solution doesn't seem very obvious to me. If you are willing to use session variables to set the template name and context, AND only have one dynamic template in your main template. You could do something like this:
<body>
{{> main}}
</body>
<template name="main">
{{> getTemplate context}}
</template>
<template name="dogs">
<p>There are {{animals}} dogs!</p>
</template>
<template name="cats">
<p>There are {{animals}} cats!</p>
</template>
Session.setDefault('templateName', 'dogs');
Session.setDefault('templateContext', {animals: 10});
Template.main.getTemplate = function() {
return Template[Session.get('templateName')];
};
Template.main.context = function() {
return Session.get('templateContext');
};
This was brought up on the meteor-core list and #dgreensp, MDG core dev working on Blaze, opened Ticket #2007 - How to render a template to HTML with data so they definitely know about this and I'd expect a fix to land soon after 0.8.0.
He also included the following workaround:
var toHTMLWithData = function (kind, data) {
return UI.toHTML(kind.extend({data: function () { return data; }}));
};
The github ticket has further discussion and alternate code snippets that you may find useful.

Resources