Meteor: templates included in markdown do not call onRendered hook - meteor

I use markdown in a template, and include another template in markdown, as follows:
<template name="hello">
{{#markdown}}
{{> subtemplate}}
{{/markdown}}
</template>
<template name="subtemplate">
<p>Something to show</p>
</template>
Then in javascript, I have:
Template.subtemplate.onRendered(
function() {
console.log("Visited");
return;
}
)
On the page, I do see "Something to show". However, the onRendered hook is not called, as I don't see "Visited" in the console.
If I move the subtemplate outside markdown:
<template name="hello">
{{#markdown}}
{{/markdown}}
{{> subtemplate}}
</template>
I do see the "Visited" in the console.
So, anyway to trigger onRendered hook inside markdown?

Unfortunately there's currently no way to put a template inside markdown helper and have it work interactively. It also applies to event handlers not only onRendered hooks.
The reason this is happening is that what markdown effectively does is it transfer all it's contents to text, then it passes it through a markdown parser and finally renderers the resulting text. The consequence is that the structure of your views get lost in the process.
In fact, the helper was not designed to handle a lot of html content inside of it. Instead you should probably pass only single chunks of text to the markdown helper and try to avoid putting templates inside if they contain some additional logic apart from rendering stuff, e.g. event handlers.

Related

need to display Loader Div on before pagerender in meteor/blaze/Flowrouter

i have started using meteor/blaze/FlowRouter recently and stuck on one issue
i need to display my custom loader div which will be shown whenever page template is in transition mode like loading content or requesting data from api or search users data etc
is there any way do to it in one place ? ... i don't want to add html content of loader in every page and handle it by function calling as it will be repetition of code
You can use percolate:momentum package from atmosphere.
First, install momentum:
meteor add percolate:momentum
Then, create a layout template:
<template name="appBody">
{{#momentum plugin="fade"}}
{{#if Template.subscriptionsReady}}
{{> Template.dynamic template=main}}
{{else}}
{{> AppLoading}}
{{/if}}
{{/momentum}}
</template>
If your subscriptions is ready, then Blaze will render template {main} specified in router. Otherwise, will render your AppLoading Template.
And you need to create the AppLoading template too:
<template name="AppLoading">
<!-- Your Loading div here -->
</template>

Meteor - sergeyt:typeahead - Not injecting when inside an {{#each}}

I have several instances of sergeyt:typeahead working in my webapp. However today I am building a table out of data from query. One of the columns needs to allow for possibly selecting from a collection or if the user wants to enter their own value.
This has worked for me in other parts. Now it appears that when using an {{#each}} statement in the html and when the typeahead is inside the {{#each}} that it does not receive the injecting.
I believe this may be due to the fact that inject is typically done on the rendered which is run before the {{#each}} has run and created the dom elements. And if that is the case how would I go about then placing the inject on these newly generated elements?
You should be able to create a sub template for each stop:
<template name='myApp'>
{{#each stops}}
{{> stop}}
{{/each}}
</template>
<template name="stop">
<input class="form-control typeahead" ...>
</template>
This way you can call typeahead.inject on each instance after it is rendered.
Template.stop.onRendered(function() {
Meteor.typeahead.inject();
});

How to get the data object from a certain template instance in Chrome Console in Meteor?

<template name="orderForm">
{{> photographyServicesForm}}
{{> videographyServicesForm}}
{{> onlineProductsForm}}
</template>
If I go to the orderForm page is there a way to get the data inside of the orderForm Blaze template instance when I'm in Chrome Console? I know how to get it inside the orderForm callbacks, events, helpers, and inside the HTML, but I want to be able to easily check up on it and even update it from the Chrome Console.
I also know that there are four different template instances when I go to this orderForm. Obviously Template.orderForm doesn't work because it's not the current template instance.
EDIT
Here's the answer:
<template name="orderForm">
<div id="orderForm">
{{> photographyServicesForm}}
{{> videographyServicesForm}}
{{> onlineProductsForm}}
</div>
</template>
Blaze.getData($('#orderForm')[0])
It should be noted that the same data available on the orderForm template is also available to its child templates - photographyServicesForm, videographyServicesForm, onlineProductsForm
You want to check out Blaze.getData and Blaze.getView.
With Blaze.getData you can simply do this:
Blaze.getData(document.querySelector('.someelement'))
This works pretty well, but you have to have an element inside the template-instance you can query for.

Template.body vs Template.myTemplate

I am currently going through the Meteor tutorial (https://www.meteor.com/try), and have come across something about Templates that puzzles me.
In the tutorial, a simple "Todo List" application gets created. In this app, the following HTML is placed into the simple-todos.html file:
<!-- simple-todos.html -->
<head>
<title>Todo List</title>
</head>
<body>
<div class="container">
<header>
<h1>Todo List</h1>
</header>
<ul>
{{#each tasks}}
{{> task}}
{{/each}}
</ul>
</div>
</body>
<template name="task">
<li>{{text}}</li>
</template>
Then, the following JavaScript is placed into the simple-todos.js file:
// simple-todos.js
Tasks = new Mongo.Collection("tasks");
if (Meteor.isClient) {
// This code only runs on the client
Template.body.helpers({
tasks: function () {
return Tasks.find({});
}
});
}
At this point, the example works exactly as intended. However, as I poke around in the documentation, as well as look at other examples on the web, I have noticed slightly different syntax: using Template.myTemplate instead of Template.body.
So, out of curiosity, I altered my JavaScript file to read:
Template.task.helpers({ ...
instead of:
Template.body.helpers({ ...
However, when I run the application now, the client does not display the data from the collection. I don't get any errors about undefined types, like I do if I misspell the template name in the JavaScript, so it seems that it is resolving the template correctly. But why isn't it getting used or rendered?
And to go a little further: when is it appropriate to use Template.myTemplate and when is it appropriate to use Template.body?
The helpers code only works for the template it's attached too.
So, code that works for Template.task will only apply to templates named "task".
Template.body is like the one-off that exists because it would be weird if it didn't. It's a way for you to specifically target the <body>, even though technically, there's no template named "body".
So, what is going on:
Parent template = body
Child template = task
Your logic says:
In the parent template, for each task that we find, render an instance of the child template "task".
If you change your helper from body to task, you won't get any output at all, unless you mimic the pattern that's already happening:
<template name="task">
{{#each tasks}}
do something
{{/each}}
</template>
That's because <body> is the parent template, and you should treat it as such:
<template="body>stuff that normally goes in an HTML body here</template>
When you remove the helpers for the body, then no data gets displayed at all because helpers pass data into the template. And with no helper for the template i.e. the body, you get no data.

Isolating template regions in meteor for easier DOM navigation

It is very useful to use template.find to locate DOM elements inside a specific template instance. But what happens when the template iterates {{#each}} over some tags without using a sub-template?
<template name="top">
{{#each items}}
<img src="{{src}}">
Click me
{{/each}}
</template>
Tempalte.events(
'click a': (event, template) ->
template.find('img') # This doesn't do the trick
# Is there a better way?
)
Is there a way to easily access the img element associated with the click event?
I know I can use event.target or create another template an use it inside the {{#each}} block. I wonder if there is a better/shorter way to do it.
You could add an #index to the img to make it possible to select it (using js or CSS). How to get index in Handlebars each helper?

Resources