Template.body.helpers returns no value - meteor

As my ROOT_URL differs in Dev and Prod environments I am rtying to use the Meteor.settings functionality to set my href values correctly.
Because links are used all over the application, it seemed a natural candidate for a helper on the body template. It is defined like so:
Template.body.helpers({
rootURL: Meteor.settings.public.root_url
})
and in the template it is used like so:
<li class="{{guessesActive}}">
<a href="{{rootURL}}guesses" class="waves-effect waves-light">Guesses
<span class="sr-only">(current)</span>
</a>
</li>
But the value of Meteor.settings.public.root_url is not appended to the anchor.

I think you just need to add as a registered helper instead of appending to the body. Template.registerHelper('rootURL', function() {...}); Then return the appropriate value. Meteor docs have more on registerHelper.

It turns out I misunderstood the body template. I thought it was meant to be accessible for all. It runs out this is not the case. It is meant to allow using helpers directly in the <body> tag.
To set global helpers, define a global variable called Helpers and assign it an object with the functions and variables you want accessible.
As explained in this post https://stackoverflow.com/a/28837834/763962

Related

Is there an event when whole template is rendered in Vue3?

I have some recursion in the component template and I need add some functionality to the result html. So I need to wait till the whole html of the component and its nested components are available. What is the right time to add this functionality? Functionality means call jQuery plugin on the result html.
The code looks like:
<template>
<div>
<ul>
<li v-for="category in categories"
:key="category.id"
id="menuItem_{{category.id}}"
data-module="{{category.module?.id ? category.module?.id : 0}}"
>
<div>
{{category.name}}
</div>
<CategoriesList v-if="category.all_children?.length" :categories="category.all_children" />
</li>
</ul>
</div>
</template>
I had a similar situation for my previous project. I was using angular and NxJS and I used observables for doing this.
You can create a dynamic array of observables, init it in the main component, add a subscription and then update them when each component is rendered (in the mounted function for example). When all your array is done, you can then call the function / apply your functionality.
Seems like something like exists in Vuejs: https://jasonwatmore.com/post/2019/04/02/vuejs-rxjs-communicating-between-components-with-observable-subject
or https://www.thisdot.co/blog/introduction-to-vuejs-and-rxjs
I could check out the code tonight and send it to you if you are interested.

What's a clean way to have a conditional container in handlebars?

When there is a link present, we want something like this HTML:
<img src="{{src}}"></img>
When there is no link present, we want something like this HTML:
<img src="{{src}}"></img>
Is there a clean way to do this? I consider the following solution bad, because it's dangerous to have to separately remember to open and close the <a> tag:
{{#if url}}<a href="{{url}}" title="{{title}}" target="_blank">{{/if}}
<img src="{{src}}">
{{#if url}}</a>{{/if}}
I considered using a block helper, but can't think of how to do so without adding more complexity. Maybe something like:
{{#linkWrap url}}<img src="{{src}}">{{/linkWrap}}
But then it's hard to see how we set the title and target and everything gets awkward.
I think you are on the right track, but I would recommend using a Handlebars Partial Block instead of a Block Helper. This will allow to pass one piece of template (the block) to another piece of template by which it will be wrapped (the partial).
Handlebars provides us with {{> #partial-block }} as a way to render a block of template within a partial. We can use this to create our "linkWrap" partial:
{{#if link}}
<a href="{{link.url}}" target="{{link.target}}" title="{{link.title}}">
{{> #partial-block}}
</a>
{{else}}
{{> #partial-block}}
{{/if}}
This gives us a clean and simple partial that will allow us to wrap any section of our template with a link as long as we have a link object to pass to our partial. Note that I have opted to use an object to represent the link so that I can pass a single parameter to the partial instead of passing the url, title, etc. properties individually.
For anywhere we wish to render a link around some markup in our template, we can do so in the following way:
{{#> linkWrap link=link}}
<img src="{{image.src}}">
{{/linkWrap}}
If the link object is null or undefined, the img element will be rendered without a parent anchor element.
I have created a supplementary fiddle for reference.

Different ways of using router links?

Im still learning Angular and I come across an example of using links for routes that I had not seen. Going through the docs on Angular.io, Im using to seeing and using this format:
https://angular.io/tutorial/toh-pt5
template: `
<h1>{{title}}</h1>
<a routerLink="/heroes">Heroes</a>
<router-outlet></router-outlet>
`
Then, I was reading an article here:
http://blog.ng-book.com/basic-routing-in-angular-2/
<a>Navigation:</a>
<ul>
<li><a [router-link]="['home']">Home</a></li>
<li><a [router-link]="['login']">Login</a></li>
<li><a [router-link]="['dashboard']">Dashboard</a></li>
</ul>
What is the difference?
First example you provided, the data is passed as a raw value, therefore it can be set as a static value
Second example, it can be bound to a variable from the component, not necessarily, it's just a different way which offers more flexibility of what you can do with the router.
They would both deliver you the same result if you simply type in a raw value, but if you need a value from the component, for example, retrieve a value from the database, the second one would be more ideal.

Iron router sublayouts - getting data context on yield

Consider the following templates:
layout
pageLayoutStandard
aboutUs
'layout' is my top-level template, which I specify using:
Router.configure({
layoutTemplate: 'layout',
});
Inside layout.html I have the following:
<main id="site-main" role="main">
{{>Template.dynamic template=page.pageLayoutTemplate }}
</main>
I pass some data in from the route: a page object which has a property 'pageLayoutTemplate', having the value 'pageLayoutStandard'.
Inside 'pageLayoutStandard' template, I have:
{{> yield }}
If I visit the '/about-us' route, I render the 'aboutUs' template into 'pageLayoutStandard' - no worries.
And now to my problem...
In my 'aboutUs' template, I expect the 'data' property of the instance to contain the data I passed down from iron-router. However, I find that my the data property contains a 'Template' object; specifically, it contains 'pageLayoutStandard'.
So it looks like 'yield' doesn't like living in a sub-layout - it wants to live at the top level layout for it to get the data from the route. This I validated by moving my yield to the top level layout - the 'aboutUs' template then gets the right data.
Is there any way I can get 'yield' to get the correct data context when it exists in a sublayout?
One solution is to access the data using
Router.current().data()
I my self am fairly new to Iron-Router, but I believe it may be a similar issue that I cam across in another way. There are also several ambiguities in your question, such as where and how are you specifically defining the data context.
Basically I discovered that {{> yield}} creates it's own <body> tags. This also means that things like Template.body.events(); don't propagate into this new Iron-router <body>. This is a known "bug" with Iron-Router.
There is a workaround that has been developed to solve that particular issue, but I'm not sure it's relevant to your case, or at least may not solve the problem since you are not looking to propagate the main body template.
In the end it may be that your routing logic is somewhat inverted, as you mentioned, with the intended usage of Iron-Router.
I believe a better way to perform what you want would be to have:
<main id="site-main" role="main">
{{> yield}}
</main>
With something like this in your router definition
Router.map(function (){
this.route("/about-us", {
template: "pageLayoutStandard"
}
});
You should then be able to set your data context and rendering as per usual.

css tabs that do not require div changes for the active tab

I'm looking to get ideas on how to not change at all the code used to create css tabs (so that I can place it into an include file to avoid duplicating the code across all files that use it), but my current implementation doesn't allow this because I need to select the active tab using id="selectedTab".
The only implementation I found so far that solves this is the following one:
http://unraveled.com/publications/css_tabs/
It requires assigning a class to each tab and uses the body id to determine the active tab.
Is this the only way or is there any other alternatives?
My current code looks like this (the id=noajax" is used to avoid using ajax to load certain pages):
<div class="productTabsBlock2">
<a id="selectedTab" href="/link1" >OVERVIEW</a>
SCREENSHOTS
<a id="noajax" href="/link3" >SPEED TESTS</a>
<a href="/link4" >AWARDS</a>
</div>
EDIT: asp is available as server side and is already used on these pages.
If you're looking for a non-JS solution, then the body class/id provide the easiest way to do what you want.
If you have access to JS library, you can easily add "selected" class to any of the <a> element and modify its appearance.
Just in case you haven't notice, you can use more than one class definition in an element. For example, <a class="noajax selected" /> is valid and both CSS selectors .noajax and .selected will be applied to the element.
An include file for what? If it's a server side programming language like PHP, you can pass a parameter for the selected tab through various methods.
you could use jQuery to add the `selectedTab' id (or class) like so
$('.productTabsBlock2 a').mouseover(function () {
$(this).addClass('selectedTab');
});

Resources