If the data function returns a falsy value like null, the NotFound template will be rendered in my application. This works fine, but now I want also to render the NotFound template, if the route does not exist.
For instance:
this.route('settingsOverviewPage', {
path: '/settings',
data: function() { return Users.findOne(Meteor.userId()); },
waitOn: function() {
if (Meteor.userId()) {
return Meteor.subscribe('ownUser', Meteor.userId());
}
return null;
}
});
If I use this route: /settings12345 for instance, the browser reloads, but it renders the last route.
Any help would be greatly appreciated.
You have to define a "catch-all" route like this :
this.route("notFound",{
path:"*",
template:"notFoundTemplate"
});
It is important that you define this route as the LAST one, otherwise it will catch valid URLs.
Related
I have in my router.js:
Router.map(function() {
this.route('portfolio', function() {
this.route('company', { path:'/company/:id' });
});
}
And in my routes/portfolio/company.js:
import Ember from 'ember';
export default Ember.Route.extend({
model: function(params) {
var companyId = params.id;
return new Ember.RSVP.hash({
company: Ember.$.ajax({ url: '/api/company/'+companyId, dataType: "json", type: 'GET' })
}).then(function(message) {
return message;
}, function(error) {
console.log( error );
});
}
});
My route and template is loading fine, when I navigate to app/portfolio/company/1, but for some reason when I navigate to that route, Ember wont load the model (no error, but the {{model}} variable does not get populated in template). Only when I refresh the page, Ember loads the model?! I am a bit confused now...
Edit: added missing param and added better description
I think in your template or in controller you are using model like so
model.company replace it with model, and remove extraneous RSVP.hash
because Ember.$.ajax already returns promise which model hooks can handle
so in ES6 (ember-cli supports it) your model hook should look like this
model({ id }) {
return Ember.$.ajax('/api/company/' + id);
}
with above things everything should work, what was happening I think you were passing just model to {{link-to}} while your controller or template expecting model.company so was breaking things
I am working on a site where I have to search in the DB for string that come after the / on the root domain. I can't find anything about it in the documentation.
I am trying to make it work with Iron Router but any other suggestion would work out.
Thanks for the help!
Edit: Basically I just want to pass anything that comes after domain.com/ to a variable.
Here's something i've been doing so maybe it'll lead you down the right path
Route sends URL params to ownedGroupList template
Router.route('/users/:_id/groups', {
name: 'owned.group.list',
template: 'ownedGroupList',
data: function() {
return {params: this.params};
}
});
Template ownedGroupList can access params object using this.data in onCreated, onRendered, and onDestroyed template event handlers
Template.ownedGroupList.onCreated(function(){
this.subscribe("owned-groups", this.data.params._id );
});
Template ownedGroupList can access params through this variable in helper methods
Template.ownedGroupList.helpers({
groups: function() {
return Groups.find({owner: this.params._id });
}
});
Template ownedGroupList can access params through template.data variable in event handlers
Template.ownedGroupList.events({
'click .a-button': function(event, template) {
var group = Groups.findOne({owner: template.data.params._id });
// do something with group
}
});
Here's a simple route that should do the trick
Router.route('/:keyword', {
name: 'keyword',
template: 'keywordTemplate',
data: function() {
return this.params.keyword;
}
});
This will pass the keyword as the data context to your template and then you can do whatever you want with it. Alternatively you can perform the search straight in the router (especially if you're passing the keyword to a subscription so that the search runs on the server). For example:
Router.route('/:keyword', {
name: 'keyword',
template: 'keywordTemplate',
waitOn: function(){
return Meteor.subscribe('keywordSearch',keyword);
},
data: function() {
return MyCollection.find();
}
});
This second pattern will send your keyword to a subscription named keywordSearch that will execute on the server. When that subscription is ready, the route's data function will run and the data context passed to your keywordTemplate will be whatever documents and fields have been made available in MyCollection.
I am using Meteor with iron-router and I'm trying to redirect the user back to the login-page if he is no logged in. But on some routes the onBeforeAction is not called. And as I discovered this has something to do with the data which is returned by the data function on the route.
If data returns null/undefined the onBeforeAction is not called and it displays the layout without the data.
If data returns i.e. an empty object it is calling the onBeforeAction and redirecting to the login-page.
1) Is this the right behaviour or is there something wrong with my route definition?
2) Is it possible that the onBeforeAction function is called before the page is rendered? Because it always show the layout/view for a short moment which is not that nice.
So, I have this route:
this.route('dashboardPortfolio', {
path: ['/dashboard/portfolio'],
layoutTemplate: 'dashboardLayout',
yieldTemplates: {
'header': {to: 'header'},
'dashboardHeader': {to: 'dashboardHeader'},
'footerMain' : {to: 'footer'}
},
notFoundTemplate: 'notFound',
loadingTemplate: 'dashboardLoading',
waitOn: function() {
return Meteor.subscribe("portfolio-edit");
},
data: function() {
var portfolio = Portfolio.findOne({user: Meteor.userId()});
if(portfolio) return portfolio;
else return {};
// return Portfolio.findOne({user: Meteor.userId()});
}
});
and my onBeforeAction:
var OnBeforeActions;
OnBeforeActions = {
loginRequired: function(route, asd, pause) {
if (!Meteor.userId()) {
this.layout('login');
this.render('login');
} else {
this.next();
}
}
};
Router.onBeforeAction(OnBeforeActions.loginRequired, {
except: ['register', 'login', 'about', 'portfolio']
});
Try replacing "except" by "only" in the next line:
except: ['register', 'login', 'about', 'portfolio']
Good luck!
In Meteor, using iron-router, I'm trying to implement a route mapping which has a dynamic segment and a fallback route if the dynamic segment does not match any items in a collection. For example, say I have a URL like so:
http://foobar.com/harold
I would like to first check if harold matches any IDs in a Posts collection. If there is a match then it should take me to a postPage template.
If there are no matches, then the router should render harold matches any items.
I've searched through all the iron-router documentation, but can't seem to figure out the right approach. I wonder if there is something like this.next() which cancels the current route mapping and goes to the next route mapping. Here's my attempt to try to do it:
Router.map(function () {
this.route('postPage', {
// matches: '/MFLS6aKqqRZ2JGz9q'
// matches: '/81zBqGE85aAfjk1js'
path: '/:postId',
before: function () {
//check if segment matches a post ID
post = Posts.findOne(this.params.postId);
if (!post) {
//If no matches, then go to next route
//Something like this.next()?
}
},
data: function() {
return Posts.findOne(this.params.postId);
}
});
this.route('profilePage', {
// matches: '/harold'
// matches: '/brendan'
path: '/:username',
data: function() {
return Profiles.findOne(this.params.username);
}
});
});
What you're describing is really just one route: /:input where input can be anything. As #David Weldon mentioned, this isn't a good idea; it basically subverts the point of using a router, and causes a lot of extra code and database queries to run every time the URL changes.
That said, if you really want to do it that way, you just need to collapse all your code into one route:
Router.map(function () {
this.route('theOneRouteToRuleThemAll', {
path: '/:input',
data: function() {
if (Profiles.findOne({username: this.params.input}) != null)
return Profiles.findOne({username: this.params.input});
else if (Posts.findOne({postId: this.params.input} != null)
return Posts.findOne({postId: this.params.input};
else
return null; // No user or post found; could handle with notFoundTemplate
}
});
});
My routes looks like this:
App.Router.map(function () {
this.resource('index', { path: '/' }, function() {
this.resource('label', { path: '/label' }, function() {
this.route('notes', { path: '/:label_id' });
});
this.route('manage', { path: '/manage' });
});
});
Users should only visit label.notes and manage routes. I'm trying to find solution how to implement redirection from index for example to label.notes. One of methods described in documentation is:
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('label.notes', 0);
}
});
Here is jsbin with full example http://jsbin.com/UnasOse/1/edit
This works if user navigates by clicking links, but if manage opened by url, or page updated user will be redirected to notes.
So, how to implement redirection only then user opens root url (index)?
Using the your current router mapping, you have the routes index.manage and label.notes.
When the page is refreshed in the index.manage, first it will transition to the parent route, in that case the index, and after to manage. But in you index you have the redirect, so the manage isn't processed.
Just remove of your mapping the resource('index') and update your manage route to reflect the new configuration, so link-to index.manage will become manage, and data-template-name=index/manage to manage etc.
The updated route mapping is the following:
App.Router.map(function () {
// this.route('index', { path: '/' }); generated by ember
this.resource('label', { path: '/label' }, function() {
this.route('notes', { path: '/:label_id' });
});
this.route('manage', { path: '/manage' });
});
You can keep your IndexRoute, because ember create by default a this.route('index', { path: '/' }). So your IndexRoute will execute just when the user go to http://yoursite.com/
You can see that sample in action in this jsbin http://jsbin.com/ucanam/1024/edit