I would like to define a default error page in meteor. That is if application is crashing or other error occurs the user should be redirected to a "friendly" page that says something like : system is unavailable , please contact etc etc.
Is there any way to accomplish this or something similar ?
Thank you
You have to use BackboneJS(Backbone Router) for routing. With this code the session variable 'page_type' let's you know if you are on a wrong url.
var BackboneRouter = Backbone.Router.extend({
routes: {
"/": "default",
":error": "list"
},
default: function () {
Session.set("page_type", "default");
},
error: function () {
Session.set("page_type", "error");
}
});
Router = new BackboneRouter;
Meteor.startup(function () {
Backbone.history.start({pushState: true});
});
Now you can use the 'page_type' to tell the template engine which template to load.
Template.tmp.route = function () {
if (Session.get("page_type") == "default") {
return true;
} else {
return false;
}
<template name="tmp">
{{#if route}}
{{> default}}
{{else}}
{{> error}}
{{/if}}
</template>
Related
I'm utilizing useraccounts:unstyled, accounts-base, accounts-password and trying to implement a password resetting feature.
I have my route defined as such:
FlowRouter.route('/reset-password/:token', {
name: 'reset-password',
onBeforeAction: function()
Accounts._resetPasswordToken = this.params.token;
this.next();
},
action(params){
Accounts._resetPasswordToken = params.token;
mount(MainLayout, {
content: (<ForgotPassword />)
});
}
});
My template defined as such:
<template name="ForgotPasswordModal">
{{#if $not currentUser}}
<div class="forgot-modal {{$.Session.get 'nav-toggle'}}" id="{{checkState}}">
<i class="fa fa-close resetPwd"></i>
{{> atForm}}
</div>
{{/if}}
</template>
And my helper functions defined as:
if (Meteor.isClient) {
Template.ForgotPasswordModal.onCreated(function(){
if(Accounts._resetPasswordToken){
Session.set('resetPasswordToken', Accounts._resetPasswordToken);
}else{
console.log("else");
}
});
Template.ForgotPasswordModal.helpers({
checkState() {
return (AccountsTemplates.getState() == 'resetPwd') ? 'forgot-modal' : '';
}
});
Template.ForgotPasswordModal.events({
"submit .at-btn": (event)=>{
event.preventDefault();
console.log(event);
password = document.getElementById('reset-password-new-password').value;
console.log("password", password);
if(password){
Accounts.resetPassword(Session.get('resetPasswordToken'), password, (error)=>{
if(error){
console.log("error: ", error);
}else{
console.log("success");
Session.set('resetPasswordToken', null);
}
});
}
}
});
}
Upon clicking submit I get Error: Match error: Expected string, got null (unknown).
Although if I load the route up (with a valid token) and run Session.get('resetPasswordToken') the token is returned validly.
I was getting this for a few days, couldn't figure it out... then after some rearrangement it finally worked.
And you don't have to use Meteor's default route & form for resetting the password.
You're close #Sleep Deprived Bulbasaur, your route should look like this:
FlowRouter.route('/reset-password/:token', {
name: 'reset-password',
action(params){
Session.set('_resetPasswordToken', params.token);
mount(MainLayout, {
content: (<ForgotPassword />)
});
}
});
I did not need the onBeforeAction, Accounts._resetPasswordToken, or this.next(), and it works just fine and logs you in automatically.
Your template should have something like this:
if (!validateForm(password,passwordAgain)) {
console.log('Your passwords dont match');
} else if (!isValidPassword(password, passwordAgain)) {
console.log('You do not have valid passwords');
} else {
let token = Session.get('_resetPasswordToken');
Accounts.resetPassword(token, password, function(err) {
check(token, String);
if (err) {
console.log('We are sorry but something went wrong.');
} else {
console.log('Your password has been changed. Welcome back!');
}
});
}
Please try using this way:
FlowRouter.route('/#/reset-password/:token');
This is default route for reset Password.
I currently use meteor for a microproject of mine to get a bit usage experience with it. Shortly after setting up I ran into some trouble getting Data i recieve from an API call to a third party site to the client into the template. I checked the usual places for answers and found some information but nothing seems to get it working for me.
So I have a simple API Call to the Steam Web Api:
Meteor.methods({
getPlayerStats: function() {
return HTTP.get("http://api.steampowered.com/ISteamUserStats/GetUserStatsForGame/v0002/?appid=730&key=XXXXXXXXXXXXXXX&steamid=XXXXXXXX");
}
});
(Api key and steam id removed for anonymity purpose, but the call indeed returns a valid response)
So I use Iron Router for template rendering.
Router.route('/profile/:steamid', {
name:'profile',
template: 'profile',
data: function() {
Meteor.call('getPlayerStats', function(err, res) {
if(err) {
return {err: err, stat: null};
} else {
var redata = JSON.parse(res.content);
var stats = redata.playerstats.stats;
console.log({err: null, stats: stats});
return {err: null, stats: stats};
}
});
}
});
So as you can see i return an object in the data method containing either err or a parsed version of the result i get from the api call. The console.log actually returns everything as intended in the client browser, that is an object like this:
{err: null, stats: [{name: "xx", value: "XY"},...]}
And now the part that actually gets me wondering, the template:
<template name="profile">
<p>{{err}}</p>
<ul>
{{#each stats}}
<li>{{name}} - {{value}}</li>
{{/each}}
</ul>
</template>
Which fails to render anything, not the err (which is null and therefor not very important) but neither the stats array.
Anyone has any idea where I went wrong on this one?
You cannot return data from asynchronous call. Instead, You can do it in the template's created function by using ReactiveVar or Session Variable like this
Template.profile.created = function () {
// or Template.profile.onCreated(function () {
var template = this;
template.externalData = new ReactiveVar(null);
Meteor.call('getPlayerStats', function(err, res) {
if(err) {
template.externalData.set({err: err, stat: null});
} else {
var redata = JSON.parse(res.content);
var stats = redata.playerstats.stats;
console.log({err: null, stats: stats});
template.externalData.set({err: null, stat: stats});
}
});
};
// }); //comment the above line and use this, if you used onCreated instead of created.
Then in your helpers,
Template.profile.helpers({
externalData: function () {
var template = Template.instance();
return template.externalData.get();
}
});
Then in your template html,
<template name="profile">
{{#if externalData}}
{{#if externalData.err}}
<p>There is an error. {{externalData.err}}</p>
{{else}}
<ul>
{{#each externalData.stats}}
<li>{{name}} - {{value}}</li>
{{/each}}
</ul>
{{/if}}
{{/if}}
</template>
I am trying to render a template on a given page but I get the following error:
Couldn't find a template named "adPage" or "adPage". Are you sure you defined it?
myapp/lib/router.js
This is how I defined the route:
Router.route("/dashboard/adpage/:_id", {
// name:"adPage",
template:"adPage",
data:function(){
return Ads.findOne({_id: this.params._id});
},
onBeforeAction : function()
{
if(Meteor.userId())
{
//user is loggedin continue the route
this.next();
}
else {
console.log("user not loggin, redirect to login page");
this.render('login');
}
},
onAfterAction: function(){
document.title = 'Annonce';
},
waitOn:function(){
return Meteor.subscribe("adDetails",this.params._id);
}
});
myapp/client/main.html
<template name="main">
...
{{> yield}}
...
</template>
myapp/client/adPage/adPage.html
<template name="adPage">
{{title}}
...
</template>
myapp/client/adPage/adPage.js
Template.adPage.onCreated(function() {
console.log("on created");
});
If I move the adPage template to my main.html file, I no longer have the error (I can see the title) but the onCreated is not called.
I tried to put everything in the same client folder and renaming adPage.js to _adPage.js and everything worked as expected.
So I suspect something wrong with the load order but can't figure out what...
Thanks !
If you are using an adblocker. Try to disable it. Its probably because of the filename
Template.recent.created = function () {
this.autorun(function () {
this.subscriptions = [
this.subscribe('users'),
this.subscribe('posts'),
this.subscribe('comments')
];
}.bind(this));
};
Template.recent.rendered = function () {
this.autorun(function () {
var allReady = _.every(this.subscriptions, function (subscription) {
return subscription.ready();
});
...
Is this the correct way to subscribe to more than one DB source in a template? When I render this template again while it's still loading, then it seems to go into infinite loading state.
Related doc: https://www.discovermeteor.com/blog/template-level-subscriptions/
There is no need to wrap your subscriptions in a Tracker.autorun. In fact, each sub has a onReady callback that you can use:
this.subscribe('subName', {onReady: function() {
//Do something when ready
}});
But besides that, there is a subscriptionsReady() function that returns true when all your template subs are ready (see the doc):
So your code become:
Template.recent.onCreated(function () {
this.subscriptions = [
this.subscribe('users'),
this.subscribe('posts'),
this.subscribe('comments')
];
if(this.subscriptionsReady()) {
//do something when all subs are ready
}
});
And in your template you can also check if all template's subs are ready:
<template name="templateName">
{{#if Template.subscriptionsReady}}
Everything is ready!
{{else}}
Loading...
{{/if}}
</template>
if user login show logintemplate in meteor otherwise show index template.I want when user login show the after login page it is ok .But i am asking when we are give at web url afterlogin template like(/admin) it will open i want when ever we give /admin show the home page not showing admin page.plz suggest me.
Maybe you are looking this.
With JSCode.
Router.route('/', function () {
if(Meteor.userId(){
this.render('loginTemplate');
}else{
this.render('login')
}
});
Using Spacebars.
{{#if currentUser}}
{{> loginTemplate}}
{{else}}
{{> login}}
{{/if}}
Using onBeforeAction
First The function
var requireLogin = function() {
if (! Meteor.user()) {
if (Meteor.loggingIn()) {
this.render(this.loadingTemplate);
} else {
this.render('accessDenied');
}
} else {
this.next();
}
}
Second onBeforeAction
Router.onBeforeAction(requireLogin, {only: 'loginTemplate'}); // this will only been applied to the `loginTemplate`.