Перенаправление не зарегистрированных пользователей с железным маршрутизатором... Снова
Я борюсь с общей необходимостью перенаправлять пользователя на страницу входа в систему, если он не вошел в систему (Meteor v0.8.0 в Windows 7).
Есть несколько похожих вопросов о stackoverflow, но ответ не работает для меня.
Не будет работать # 1: render()
Из документация:
onBeforeAction: function () {
if (!Meteor.user()) {
// render the login template but keep the url in the browser the same
this.render('login');
// stop the rest of the before hooks and the action function
this.stop();
}
},
Два вопроса здесь:
1- Документация устарела. Функция this.stop()
больше отсутствует. Как указано здесь, код должен быть:
onBeforeAction: function (pause) {
if (!Meteor.user()) {
// render the login template but keep the url in the browser the same
this.render('login');
// stop the rest of the before hooks and the action function
pause();
}
},
2- Это работает, только если маршрут не имеет значения layoutTemplate
. Если он имеет один, шаблон login
отображается в {{>yield}}
layoutTemplate
. Обычно это не то, что вы хотите для страницы входа.
Не будет работать # 2: Router.go() или this.redirect()
Определение маршрута для страницы входа звучит как естественный путь. Затем вы можете:
Router.onBeforeAction(function(pause) {
if (!Meteor.user()) {
pause();
Router.go('\login');
}
}, {except: ['login']});
Или:
Router.onBeforeAction(function() {
if (!Meteor.user())
this.redirect('\login');
}, {except: ['login']});
Но, как ни странно, по-прежнему существует проблема, если исходный маршрут (перед перенаправлением) имеет layoutTemplate
: шаблон /login
отображается внутри {{yield}}
. Что опять же не то, что вы обычно хотите (и определенно не то, что вы ожидаете, так как шаблон /login
не имеет layoutTemplate
).
Я нашел способ частично решить эту проблему:
Router.onBeforeAction(function() {
if (!Meteor.user()) {
var that = this;
setTimeout(function() { that.redirect('\login'); }, 0);
}
}, {except: ['login']});
Теперь все в порядке: шаблон /login
отображается как чистая страница... За исключением того, что layoutTemplate
исходного маршрута кратковременно мигает до отображения шаблона /login
.
У вас есть эта же проблема?
Ответы
Ответ 1
Итак, кажется, что функция рендеринга на маршруте только отображает шаблон в текущий макет. Чтобы отобразить шаблон в другом макете, вы должны вызвать this.setLayout('templateName')
. Кажется, что одно предупреждение - вам нужно будет установить макет после входа в систему.
onBeforeAction: function(pause) {
var routeName = this.route.name;
if (_.include(['login'], routeName))
return;
if (! Meteor.userId()) {
this.setLayout("newLayout");
this.render('login');
//if you have named yields it the login form
this.render('loginForm', {to:"formRegion"});
//and finally call the pause() to prevent further actions from running
pause();
}else{
this.setLayout(this.lookupLayoutTemplate());
}
}
Вы также можете просто визуализировать шаблон входа в качестве макета, если вам нужен шаблон входа в систему, вызывая this.setLayout('login')
Ответ 2
Вы можете поместить в шаблон макета if или if template.
{{#unless currentUser}}
{{> loginPage}}
{{else}}
{{> yield}}
{{/unless}}
Ответ 3
Похоже, что это связано с ожиданием подписок в waitOn.
Ниже перечислены проблемы с отображением макета для меня:
Router.onBeforeAction(function() {
if (!Meteor.user() && this.ready())
return this.redirect('/login');
}, {except: ['login']});
Ответ 4
Вам просто нужно вернуть результат render()
из onBeforeAction()
onBeforeAction: function () {
if (_.include(['login'], this.route.name)){
return;
}
if (!Meteor.userId()) {
return this.render('login');
}
}
Также обратите внимание, что я изменил Meteor.user()
на Meteor.userId()
. Это препятствует повторному запуску крючка каждый раз, когда текущий документ пользователя работает.
Ответ 5
В Meteor 0.8.3 для меня работает:
Router.onBeforeAction(function () {
if (_.include(['formLogin'], this.route.name)){
return;
}
if (!Meteor.userId()) {
this.redirect('formLogin');
return;
}
});