Path works on desktop, but not mobile - meteor

I've a tab bar on a responsive app I'm building:
<template name="tabNav">
<nav class="bar bar-tab">
<a class="tab-item" id="groups-nav" href="{{pathFor 'groupsList'}}">
<span class="icon icon-star-filled"></span>
<span class="tab-label">Groups</span>
</a>
<a class="tab-item active" id="games-nav" href="{{pathFor 'locationSet'}}">
<span class="icon icon-list"></span>
<span class="tab-label">Games</span>
</a>
<!-- more code -->
</template>
The pathFor 'groupsList' works on desktop, but not on mobile. You can try it out here: pp-groups.meteor.com.
This is a prototype only and doesn't use any real data. All of my views code is available here: https://github.com/stewartmccoy/pp-groups/tree/master/groups/client/views
These are my defined routes:
Router.map(function() {
this.route('layout', {
path: '/',
template: 'getLocation',
layoutTemplate: 'getLocation',
yieldTemplates: {
'tabNav': {to: 'footer'}
}
});
this.route('locationSet', {
path: '/locationSet',
template: 'locationSet',
layoutTemplate: 'locationSet'
});
this.route('groupsList', {
path: '/groupsList',
template: 'groupsList',
layoutTemplate: 'groupsList'
});
});
Why doesn't the pathFor work on mobile? (It at least doesn't work in Xcode iOS simulator or on iPhone Mobile Safari or Chrome).

The push.js component is causing the issue. You can still use Rachet with Iron Router by disabling push.js. Per rachet's documention you can disable push by adding a data-ignore tag to your HTML link.
<!-- Use data-ignore="push" to prevent the push.js interception -->
<a href="http://www.google.com" data-ignore="push">Google<a>

Routing issue:
Removing the ratchet package fixed it for me. Looks like ratchet uses it's own way of linking between templates which is incompatible with iron-router. Removing ratchet removes the UI elements, but the routing works on mobile: http://pp-groups-fixed.meteor.com. You could use a strictly UI library, like bootstrap to make the UI elements, or maybe even just the ratchet's UI components. If you want to fully use ratchet, you will most likely have to forgo IronRouter.
Other things to fix:
Layout Templates
When using meteor and iron-router, a layout template is a template with common elements, with a {{> yield}} placed where you want the regular templates to show up.
You actually only have one real layout template in your code, in groups.html there is a layout template named layout, and it is unused.
In your code, regular templates are being misused as layout templates, because they don't have {{> yield}} in them. Also, the tabNav template is being placed using iron-router, yet you have already included it in each template with {{> tabNav}}.
So, you can simply get rid of the layout template code in your iron router, and your app will still function:
Router.map(function() {
this.route('layout', {
path: '/',
template: 'getLocation',
// layoutTemplate: 'getLocation',
// yieldTemplates: {
// 'tabNav': {to: 'footer'}
// }
});
this.route('locationSet', {
path: '/locationSet',
template: 'locationSet',
// layoutTemplate: 'locationSet'
});
this.route('groupsList', {
path: '/groupsList',
template: 'groupsList',
// layoutTemplate: 'groupsList'
});
});
A better way is to take out all the common code, the header, general structure of the page, tab bar, and put it in a layout template. Add a {{> yield}} where you want the page template to render. Refer to this layout template in your router as layoutTemplate.
Another sidenote, iron-router automatically looks for the template with the same name as the route, if no template is defined. So if you are writing this.route('groupsList', ... you don't need to write template: 'groupsList' as well.
Data
Your past-game.js file should be named get-location.js. Yes, the name itself doesn't matter, but that is getLocation's complimentary code, not postGame's. Same with scheduled-games.js and locationSet. Look at the Template.templateName.helpers to see how the code corresponds.
Of course, ideally this data should be in a collection. For now, instead of creating the data as arrays with var, you could create a seperate file with your data as global variables. Simply define as PastGames = [...], then use the template helpers to return the data you need.

Related

How to route html pages on clicks in meteor?

I am a newbie in Meteor. I am developing an app having a login page that must redirect to certain pages as per the login id.There are certain click events which opens up html pages.I have the hard code data in the pages to check the flow now.I have the html pages as well designed, but I am not able to link them for click events and login. Please help.
Here is one way to do it:
In your HTML file, something like this:
<head>
<title>Duckbilled Platypus</title>
</head>
<template name='layout'>
{{> banner}}
{{> yield}}
</template>
<template name="banner">
<h1 class="chocolatefont">Platypi of the World Unite! (Duckbilled, that is)</h1>
<hr/>
</template>
<template name="main">
<div id="templateMain" name="templateMain">
<h2>RAVES</h2>
<p>No Raves yet</p>
<h2>RANTS</h2>
<p>No Rants yet</p>
<h2>RANDOM</h2>
The Legend of NFN Oscar
<br/><br/>
NFN Oscar's donut
<br/><br/>
Alliteration Station ("Ben's Bizarre Bazaar")
<br/><br/>
Boomeranging Telescopic and Kaleidoscopic Phrase Mazes
<br/><br/>
Acrostics
<br/><br/>
Homonym Homie
</div>
</template>
...and then add whichever templates you want for the pages you want to route to; in my case, it's one for each "href" referenced in the anchor tags (nfnoscar, nfnoscarsdout. etc.)
The "yield" (which means, "insert here whatever the router says corresponds to the URL") requires Iron:Router, which you say you already have.
In your JS file, something like this:
Router.configure({
layoutTemplate: 'layout'
});
Router.route('/', {
name: 'main',
template: 'main'
});
Router.route('/nfnoscar', {
name: 'nfnoscar',
template: 'nfnoscar'
});
Router.route('/nfnoscarsdonut', {
name: 'nfnoscarsdonut',
template: 'nfnoscarsdonut'
});
Router.route('/alliterationstation', {
name: 'alliterationstation',
template: 'alliterationstation'
});
Router.route('/btakpm', {
name: 'btakpm',
template: 'btakpm'
});
Router.route('/homonyms', {
name: 'homonyms',
template: 'homonyms'
});
Router.route('/acrostics', {
name: 'acrostics',
template: 'acrostics'
});
Now, whichever link is clicked, the corresponding page is loaded by means of the "yield" and the Iron Router routing.
You can see this particular app and how it works when you click the links, etc., at my "sandbox" Meteorsite here.

Meteor: make layout.html WaitOn a subscription?

I'm trying to make a chat (Template.chatlist) feature that sticks to the bottom of the page (similar to the chat function on Facebook, where the chat box is persistent while the page in the background changes as the user browses to other parts of the site). So I put the chat box in a handlebars template on the layout page (so it's not rendering from the {{>yield}} template). The problem is, it's not waiting on the subscriptions before it loads (there is no route to the layout.html, so I couldn't set a waitOn on it in the router), so it's not able to pull information from my users collection.
I need to know, how can I make the layout.html page wait to load after the subscriptions are properly finished? Of course, I can put the chat template inside every page's yield template to have it wait properly, but is there a way where I don't have to do it this way?
<main class="main container" id="central">
{{> yield}}
{{> chatlist}}
</main>
This is sort of what the layout.html looks like right now. The chatlist template is not waiting on any data subscriptions because it's not in the yield section (and thus not controlled by the router)
I also did Template.chatlist.helpers and registered the user data into a helper, but for some reason when I tested it by console logging Users.count the console returns with zero.
Use a region:
<template name="layout">
<aside>
{{> yield region='aside'}}
</aside>
<div>
{{> yield}}
</div>
<footer>
{{> yield region='footer'}}
</footer>
</template>
Router.map(function () {
this.route('home', {
path: '/',
template: 'myHomeTemplate',
layoutTemplate: 'layout',
yieldTemplates: {
'myAsideTemplate': {to: 'aside'},
'myFooter': {to: 'footer'}
},
waitOn: function() {
// ...
}
});
});
See the Iron Router docs.

How can I use two Iron Router controllers in one layout in Meteor 0.8.0?

In my Meteor app, I have two yield blocks: one for my global navbar and the other for my main content:
<template name="layout">
<div>
{{> yield region='navRegion'}}
</div>
<div>
{{> yield}}
</div>
</template>
How can I add an Iron Router Controller into my routes so that I can pass data into my global navbar (since it doesn't have a route)? Is it possible to run the two controllers at the same time? Or do I have to rely on helpers for the global nav?
Let's say the template that you were trying to render in the main {{> yield}} was named home. The following would work.
Router.configure({
layoutTemplate: 'layout'
});
Router.map(function () {
this.route('home', {
path: '/',
template: 'home',
yieldTemplates: {
'navRegion': {
to: 'navRegion'
}
}
});
});
Here's the answer from #cmather, which he answered on my other post:
How do I activate an Iron Router route without changing the path?
There is a one-to-one between a route and a route controller. You'll
only ever have one controller running at a time, based on the route
you're on. If you want to set a global value from a controller, and it
doesn't make sense to do it in the global data context, you can always
set a session value. For example: Session.set('currentId',
this.params._id) - #cmather

Rerun Helper Functions on Route Change for Active Links

I've been playing around with Meteor + Iron Router for a multi-page app I'm working on and I'm getting stuck on helper functions for named yields. Specifically, I've been trying to get the active class for my navbar tabs to update on each route change.
Below is the relevant code for my project:
router.js
Router.configure({
layoutTemplate: 'mothership',
yieldTemplates: {
'header' : {to: 'header'},
'footer': {to: 'footer'}
},
});
Router.map(function () {
// Home page
this.route('home', {
path: '/',
template: 'home',
});
this.route('about', {
path: '/about',
template: 'about',
});
this.route('emails', {
path: '/emails',
template: 'emails',
});
this.route('people', {
path: '/people',
template: 'people',
});
});
mothership.html
<template name="mothership">
Skip to content
<div id="wrap">
<!-- header -->
<div>{{yield 'header'}}</div>
<div id="content">{{yield}}</div>
</div>
<div id="push"></div>
<div id="footer">
{{yield 'footer'}}
</div>
</template>
header.html
...bootstrap stuff...
<a class="navbar-brand" href="{{pathFor 'home'}}">Mailchacho</a>
<li class="{{activeRoute 'about'}}">About</li>
<li class="{{activeRoute 'emails'}}">Sent Emails</li>
<li class="{{activeRoute 'people'}}">People</li>
...bootstrap stuff...
header.js
Handlebars.registerHelper('activeRoute', function(name) {
var active = location.pathname === Router.path(name);
return (active) ? 'active' : '';
});
// I know I can use Template.headers.helpers... to do this as well, I just found the registerHelper to be cleaner.
When I load a page from scratch, the proper active class is assigned, but when a route is changed on-page, the active class doesn't update. Using breakpoints, I can see the 'activeRoute' function isn't called on a change.
What's interesting is if I add a data dictionary to router.js, it does update. My guess is having the data dictionary indicates that something has changed between routes, forcing a refresh. What I'd like to do is have this refresh occur without needing to pass a data dictionary.
Since Iron Router is still fairly new, I haven't been able to able to find much online. The closest I've found is this issue on github (https://github.com/EventedMind/iron-router/issues/103), but the last comment was never resolved, which seems to be similar to mine.
With the above in mind, is there any way I can signal for a helper function to be rerun on a route change without passing a dummy data dictionary? I was thinking that something like Deps.autorun might be needed, but that doesn't feel right. I'm still pretty new to Meteor & Iron Router so any help here would be appreciated. Thanks!
Yours is a common problem so Mike Fitzgerald has built a package just for this purpose:
https://atmosphere.meteor.com/package/iron-router-active
The given example is like:
<nav>
<ul>
<li class="{{ isActive 'dashboard' }}">...</li>
<li class="{{ isActive 'dashboard|root' }}">...</li>
<li class="{{ isActive 'users' 'on' }}">...</li>
<li class="{{ isActivePath 'products' }}">...</li>
</ul>
</nav>
andd works through handlebars helpers which are called isActive, isActivePath, isNotActive and isNotActivePath.
I use meteor add zimme:active-route now. It works with iron:router, kadira:flow-router and meteorhacks:flow-router.
Just two examples: Output active class:
<li class="{{isActiveRoute 'home'}}">...</li>
Custom class:
<li class="{{isActiveRoute 'home' class='is-selected'}}">...</li>
https://atmospherejs.com/zimme/active-route

meteor: How to use Font Awesome with Handlebars?

First off, I placed this in the HEAD section of my template:
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
I decided I wanted to use the music symbol and inserted it like so:
<div id="close_player"></div>` where the symbol is given by ` fa-music ()
However, when my page loads for some reason I see only fi instead of the Font Awesome symbol I'm supposed to be seeing. The source displays the following:
<div id="close_player"></div>
What is going on, and how do I resolve this?
As Cuberto suggested add the package using mrt,
Then you can do something like this, consider you have iron router and you got 2 icons in every page at your app, and they change according to the route:
<template name='myHomeTemplate'>
<i class={{iconOne}}></i>
<i class={{iconTwo}}></i>
</template>
Then in your router logic you can do
this.route('home', {
path: '/',
template: 'myHomeTemplate',
layoutTemplate: 'layout',
yieldTemplates: {
'myAsideTemplate': {to: 'aside'},
'myFooter': {to: 'footer'}
},
data: {
iconOne: 'fa fa-music',
iconTwo:'fa fa-camera'
}
});
First of all, don't put CSS links in your head. Just add the meteorite package - mrt add font-awesome. This will automatically add the CSS link when you run the app, and it will concatenate and minify it with all your other CSS in deployment. Then, just use the icons the font awesome way:
<i class="fa fa-music"></i>

Resources