Prevent Iron Router Not Found template showing when using angular-meteor - meteor

I have a Meteor application and I'm using a combination of angular-meteor and Iron Router routing.
Angular-meteor client side routing is used for all browser side routing and Iron Router is used for all server side routing. I'm implementing an OAuth2 server in Meteor so I need to be able to hit a URL without using the client side code.
The setup works great, but with one consequence: the Iron Router 'not found' template always shows on the client, because I have no client side routes for Iron Router:
I've also tried adding a blank Iron Router route to the client side code:
Router.route('(.*)', function(){
//Do nothing
});
or
Router.route('(.*)', function(){
//Do nothing
this.ready();
});
But that results in all my angular-meteor templates being duplicated on the client:
I've also tried setting the Iron Router configuration to use a different not-found template I've written in Blaze, and using angular-with-blaze:
> meteor add angular-with-blaze
client & server code:
Router.configure({
notFoundTemplate: "ironrouternotfound"
});
ironrouternotfound_blaze.html:
<template name="ironrouternotfound">
IR Not Found
</template>
ironrouternotfound.html
<blaze-template name="ironrouternotfound"></blaze-template>
But that results in the following text being injected into the bottom on the HTML DOM:
Couldn't find a template named "ironrouternotfound" or "ironrouternotfound". Are you sure you defined it?
This message is injected by IronRouter and it doesn't have an ID on the div or any CSS classes so I can't hide it using JS or CSS. (Well, I might be able to hack a JS to remove the last div on the page, but that could be dangerous)
Any one managed to remove the Iron Router not-found view in this situation?

My temporary CSS hack is:
div[style="margin: 0 auto; color: red;"] {
display: none;
}

This works for me. First declare a blank HTML template in a client folder like this:
<template name="noRoutesTemplate"></template>
Next in a common folder (eg. 'lib') add iron router's noRoutesTemplate to the configuration.
import { Router } from 'meteor/iron:router';
Router.configure({
noRoutesTemplate: 'noRoutesTemplate',
});
See this reference link

Related

Iron-Router dynamic templates in layout like in Flow-Router

How can i render dynamic templates via layout in Iron Router?
For example in Flow-Router in layout i can define some dynamic templates:
newsRoutes.route('/',{
action:function(){
BlazeLayout.render("layout",{top:"digest",left:"post_list",right:"chat"});
}
});
And then i can define another route with another parameters:
adminRoutes.route('/',{
action:function(){
BlazeLayout.render("admin_layout",{top:"admin_user_list"});
}
});
And Flow-Router will not render nothing in left and right positions.And it is good for me.
But with named {{>yield}} regions in Iron:Router i can't do that. Because Iron:Router save {{>yield}} regions from route to route, and it can be only rewriten by redefined regions. How can i prevent rendering {{>yield}} regions if it not defined in current route?

Meteor + Iron Router unable to scroll up

I have tried using command like scrollTo(0) and packages like okgrow:router-autoscroll. I have read through many pages online. I am completely unable to make it so that when I load a new template via route (Iron Router) it automatically scrolls to the top.
Edit: I have tried all of the following to no avail:
$(window).scrollTop()
$('body, html').scrollTop()
$('body').scrollTop()
$(document).scrollTop()
window.scrollTo(x, y)
For those of you with the same issue. I ended up solving this with problem in all browsers with the following code:
Template.templateName.onRendered(function(){
$('.wrapper-header')[0].scrollIntoView();
});
This should work in all browsers as it did for me, and remove the necessity for flowrouter and Iron Router autoscroll addons.
Hope this helps!

Meteor: Images and text do not load after moving to Iron:Router

My site works fine when the data is in a template, but once I try to route to it using iron:router, a background image and most remaining content no longer appear. (Some of the content still appears with working css, JS components so I know that those files are being read. Also, when inspecting the element, all the text, images are still visible in the code, but not the website.
This works fine (index.html):
<body>
{{>home}}
</body>
This adds another {{>home}} section, but the new section is having issues rendering as explained above (router.js):
Router.map(function() {
this.route('home', {path: '/'});
});
Are you on the latest iron:router? I had a similar problem, and inquired about it in this pull request:
https://github.com/iron-meteor/iron-router/issues/1051
Latest response indicates this should be fixed now!
You've followed the wrong tutorial :( There are plenty of tutorials and articles out there explaining to define routes like you did.
However, the Iron Router project page explains how to define routes differently.
For more information on routes, have a look at this article about Iron Router as well.
Fixed: problem was not with iron:router but rather that not all elements were loaded into the page yet. Document.ready() works fine when I directly called template.
Issue is that when iron:router loads the template, the new page elements are being loaded after the JS files were already called (JS that animates the images/text in).
Solution: use rendered instead of document ready:
Template.MyTemplate.rendered = function(){
}

Where does Meteor.subscribe() belong?

I just noticed that my subscription code "Meteor.subscribe('my-publications')" at the top of my JS file affects ALL my templates, not just the template that the JS file is created for.
This was unexpected because all the demos did it this way.
Where is the subscription code suppose to be in if I want it to affect one template only? Inside Template.name.created()?
Don't assume the only data in minimongo is what is relevant to your template. Be specific when selecting your data for the template.
You have several options as far as subscriptions go, the most common by far is adding a subscription to the waitOn section of your routes definitions. Using waitOn will result in the subscription being unsubscribed when the route is no longer in use.
Router.map(function() {
this.route('route', {
waitOn: function(){ return Meteor.subscribe("yourSub"; }
});
});
You can also subscribe per template. A package I've created for this purpose can be added via
meteor add elevatedevdesign:template-subscriptions
This pattern will also be coming soon as a part of blaze, but with some slight differences in how you call it. This will automatically unsubscribe when the template is no longer active. It also allow's subs-manager to be subscribed to on template destruction.

Need to include a helper html page in my meteor project

I have a helper.html page that I need to include in my Meteor app to assist with using an api. Looks like this.
<head>
<script type="text/javascript" src="https://www.example.com/api-helper.js"> </script>
</head>
<body>
</body>
Right now I just have it in the root directory of my app. As it is now, here are the problems: the other api script which I have included in main.html, can't find the helper.html. Second, I get this error in the console: Error: Oh no! No route found for path: "/helper.html?. So my question is how do I properly include this helper html page into my Meteor project? Help greatly appreciated.
Thanks
Just put your html file into a folder called public in the root folder.
Error: Oh no! No route found for path: "/helper.html"
This is an error from iron:router, it's complaining that it can't find any route for path "helper.html".
I suppose you get this error message when typing directly http://localhost:3000/helper.html in your browser address bar, which is WRONG because this is not how iron:router is supposed to work.
iron:router manages pure client-side routing using HTML5 push state API contrary to classic server-side routing involved when requesting "/helper.html" to Apache or nginx means the server is going to send you an actual HTML response page displayed by the browser.
In Meteor "single-page apps", the server does not send any HTML responses to the client, it only sends data. It means that the routing takes place entirely in the client, the URL in the address bar gets parsed and iron:router provides utilities to respond accordingly, which usually involves rendering a different template based on which path (route) you hit.
I hope you really understand the difference in nature between these two approaches because this is very important to be aware of when developing with Meteor.
As far as your problem is concerned, I'll take DISQUS integration as an example which seems to be a similar issue.
DISQUS integration on standard PHP solutions is straightforward, you just need to copy-paste this so-called universal embed code :
<div id="disqus_thread"></div>
<script type="text/javascript">
/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
var disqus_shortname = '<example>'; // Required - Replace example with your forum shortname
/* * * DON'T EDIT BELOW THIS LINE * * */
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript>Please enable JavaScript to view the comments powered by Disqus.</noscript>
blog comments powered by <span class="logo-disqus">Disqus</span>
This is fine because once a page gets sent to the client in a traditional website, javascript code gets executed once and we are done : if the user click on another page on the website, the all process of generating the HTML response, sending it to the client and executing JS code will be started from scratch.
However we can't just copy-paste this code inside a Meteor template, because Meteor webapps are "single-page apps", no page reloading process should ever happen in these type of websites.
When we navigate to another page in a Meteor app, the javascript context stays the same and we don't want the DISQUS script to reexecute. What we need to do instead is loading the script only once in the rendered callback of our template.
So we come up with the following Meteor template logic to integrate DISQUS comments loading :
<template name="disqus">
<div id="disqus_thread"></div>
<a href="http://disqus.com" class="dsq-brlink">
blog comments powered by <span class="logo-disqus">Disqus</span>
</a>
</template>
Template.disqus.rendered=function(){
// assumes we get identifier and title as data context
var identifier=this.data.identifier;
var title=this.data.title;
// we need a way to tell if the script has already been loaded or if it's
// the first time, we can check for the existence of the DISQUS variable on
// the global window object to make the difference
if(window.DISQUS){
// DISQUS API has our back, see this resource
// https://help.disqus.com/customer/portal/articles/472107-using-disqus-on-ajax-sites
window.DISQUS.reset({
reload:true,
config:function(){
this.page.identifier=identifier;
this.page.title=title;
}
});
}
else{
// first initialization
window.disqus_shortname = "disqus-shortname";
window.disqus_identifier = identifier;
window.disqus_title = title;
window.disqus_developer = 1;
// load the script via JS instead of embedding it in the HTML
var script = $("<script>",{
type:"text/javascript",
async:true,
src:"//" + disqus_shortname + ".disqus.com/embed.js"
});
$("head").append(script);
}
};
This example demonstrates the way to go when you need to embed API code (google-analytics, DISQUS, etc...) in a Meteor website.

Resources