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
Related
Iron-router is preventing my template from rendering a new page because it seems to believe it is already there.
The routes that I am dealing with are these:
Router.route('/', {
name: 'landingpage',
template: 'landingpage',
onBeforeAction: function() {
this.next();
}
});
Router.route('/chapter/:pathSlug/:chapterSlug', {
name: 'chaptershow',
template: 'chaptershow',
//waitOn: function() {
//return [Meteor.subscribe('users'),
//Meteor.subscribe('ChapterCollection')];
//},
onBeforeAction: function() {
Session.set('currentRoute', 'chapter');
this.next();
}
});
Let's say I have two chapters I want to display:
/chapter/voyage/somestories
/chapter/voyage/someotherstories
From the console I can easily go from the landingpage to either of the voyage pages or vice versa with
Router.go('landingpage');
Router.go('/chapter/voyage/somestories');
However, if I am on /chapter/voyage/somestories and try to go to /chapter/voyage/someotherstories using either
Router.go('/chapter/voyage/someotherstories');
Router.go('chaptershow', {pathSlug: 'voyage', chapterSlug: 'someotherstories'});
the URL in the location bar changes to /chapter/voyage/someotherstories but the new context doesn't load.
How do I get my new chapter to render?
If I have in the router map:
this.resource('detail', { path: '/detail/:type' }, function() {
...
});
And I retrive the currentPanth in my Ember Application code:
currentPath: '',
ApplicationController : Ember.Controller.extend({
updateCurrentPath: function() {
App.set('currentPath', this.get('currentPath'));
console.log('currentPath',App.currentPath);
}.observes('currentPath')
}),
When I navigate in my app, I get the route names by console, but when It is "detail" I get "detail.index". How can I get the type?
you only have access to the params in the route, ie. when you are defining your model:
App.Router.map(function() {
this.resource('photo', { path: '/photos/:photo_id' });
});
App.PhotoRoute = Ember.Route.extend({
model: function(params) {
return Ember.$.getJSON('/photos/'+params.photo_id);
}
});
Or you can also use paramsFor, also in the route only.
Depending on what you are trying to acomplish maybe query params suit better
I've set up two routes in Iron-Router: 'home' (a paged list of all post) and 'doc' (a detail view). The home page loads just fine, but the detail view can only be loaded if the home page has been viewed previously. Otherwise it will render empty – and it can't be used as a permalink.
This will always load:
http://localhost:3000/
This will only load if 'home' has been viewed before:
http://localhost:3000/doc/tZFawq8cgf43hZBaJ
the routes:
Router.map(function() {
this.route('home', {
path: '/'
});
this.route('doc', {
path: '/doc/:_id',
data: function() {
return MyPix.findOne({_id: this.params._id});
}
});
});
the doc template:
<template name="doc">
<h1>{{this.name}}</h1>
<img src="{{ this.url store='OriginalRetinaPix' }}" width="{{ this.metadata.width }}" height="{{ this.metadata.height }}" />
</template>
publish/subscribe:
Meteor.publish('MyPix', function(cursor) {
Counts.publish(this, 'numberOfPosts', MyPix.find(), { noReady: true });
return MyPix.find({}, {sort: {uploadedAt: -1}, limit: 4, skip: cursor});
});
if(Meteor.isClient) {
Session.setDefault('docCursor', 0);
console.log('docCursor: ' + Session.get('docCursor'));
Meteor.autorun(function(){
Meteor.subscribe('MyPix', Session.get('docCursor'));
})
}
btw: the project on GitHub
On your "doc" route, you should use the waitOn in order to have the data ready on page load. Add a loading template in the Router.configure as well
I recommend you to upgrade to the new iron:router routes declarations and also add meteorhacks:subs-manager for better cache on the subscriptions.
This is an example that should work in your case
var subs = new SubsManager();
Router.route('/doc/:_id', {
name: 'doc',
template: 'doc',
waitOn: function() {
return subs.subscribe('aPix', this.params._id);
},
data: function() {
return {
apix: MyPix.findOne({
_id: this.params._id
})
};
}
});
and on the server side create a publications.js
Meteor.publish('aPix', function(id) {
check(id, String);
return MyPix.find(id);
});
Use this.
Router.map(function() {
this.route('home', {
path: '/'
});
this.route('doc', {
path: '/doc/:_id',
waitOn: function(){
return Meteor.subscribe('MyPix');
},
data: function() {
return MyPix.findOne({_id: this.params._id});
}
});
});
Also you subscription should look like this.
Meteor.publish('MyPix', function(cursor) {
//Counts.publish(this, 'numberOfPosts', MyPix.find(), { noReady: true });
return MyPix.find({});
});
Also Add, meteor add sacha:spin, because when you have a lot of people, the subscription will be have a little delay.
Add this to each route.
loadingTemplate: "loading"
<template name="loading">
{{> spinner}}
</template>
Router.onBeforeAction("loading");
Just in case you are showing 100+ images on 'home' and someone enter and have a slow connection, he will think that the page load empty, or something.
You only subscribe to a subset of all the documents. If you directly go to /doc/tZFawq8cgf43hZBaJ, the document with the id tZFawq8cgf43hZBaJ may not be part of the subset of documents you receive on the client.
Note: if this answer is correct, you should be able to directly go to /doc/<id> for those documents showing up first on the home page (on the first page, when the session variable docCursor is 0).
I'd like to nest resources in Ember, but to be able to access them with a short URL.
For example: mysite.com/admin will open the route: /routes/profiles/settings/admin
Is it possible to do something like that using Ember?
I'm currently using Ember 1.7 with Ember App Kit.
I tried the following but it doesn't work:
var Router = Ember.Router.extend();
Router.map(function () {
this.resource('profile', function () {
this.resource('profile.settings', { path: '/settings' }, function () {
this.resource('profile.settings.admin', { path: '/admin' });
);
});
Thanks.
Your code doesn't work because your inner most resource is inheriting the /profile path from the outer most resource and /settings from the middle resource. If you want it to be just plain /admin, you'd have to do something like this:
this.resource('profile', { path: '' }, function() {
this.resource('profile.settings', { path: '' }, function() {
this.resource('profile.settings.admin', { path: '/admin' });
});
});
However, this is going to get pretty hairy when you have more routes that each want top-level paths. You might find it easier to just declare a admin route at the top level, then redirect using the redirect hook in the route.
I'm following an ember tutorial-
http://coding.smashingmagazine.com/2013/11/07/an-in-depth-introduction-to-ember-js/
and have edited it to include a new model and route. The original tutorial is a CRUD app for a collection of users. I now want to expand the app to deal with a list of subjects that these users might study. The router.jsfile now looks like this-
App.Router.map(function(){
this.resource('users', function(){
this.resource('user', { path:'/:user_id' }, function(){
this.route('edit');
});
this.route('create');
});
this.resource('subjects', function(){
this.resource('subject', {path: '/:subject_id'}, function(){
this.route('edit');
});
this.route('create');
});
});
(Subjects are a separate route because I want to be able to create separate routes for now)
I've added a subjects.js model which looks like this:
App.Subject = DS.Model.extend({
name : DS.attr(),
});
App.Subject.FIXTURES = [{
id: 1,
name: 'History',
}, {
id: 2,
name: 'Biology',
}];
a subjectsController:
App.SubjectsController = Ember.ArrayController.extend({
sortProperties: ['name'],
sortAscending: true // false = descending
});
a subjectsRoute:
App.SubjectsRoute = Ember.Route.extend({
model: function(){
return this.store.find('subject');
}
});
and a template in my index which looks like this:
<script type = "text/x-handlebars" id = "subjects">
<ul>
{{#each subject in controller}}
<li>{{subject.name}}</li>
{{/each}}
</ul>
</script>
I have added all my dependencies and followed the exact same steps in the tutorial as I did for the users CRUD app described in it, but now when I go to my browser, nothing renders. Can anyone see why?
In the tutorial described for you, there is a missing route to catch wrong paths, and redirect to the users route, maybe you need to include it to show something, since there isn't a index route to show some initial page.
Update your code with the following:
router.js
App.Router.map(function(){
this.resource('users', function(){
this.resource('user', { path:'/:user_id' }, function(){
this.route('edit');
});
this.route('create');
});
this.resource('subjects', function(){
this.resource('subject', {path: '/:subject_id'}, function(){
this.route('edit');
});
this.route('create');
});
// this is our 404 error route - see MissingRoute just bellow
this.route('missing', { path: '/*path' });
});
// this handles wrong routes - you could use it to redirect to a 404 route or like here to redirect to the index page
App.MissingRoute = Em.Route.extend({
redirect: function(){
this.transitionTo('users.index');
}
});