2014-05-02 82 views
20

我正在努力將用戶重定向到登錄頁面(如果他沒有登錄)(Windows 7上的Meteor v0.8.0)。使用鐵路路由器重定向未登錄的用戶...再次

在stackoverflow上有幾個類似的問題,但沒有答案似乎適用於我。

都不行#1:渲染()

the documentation

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()功能了。如前所述here,代碼應該是:

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模板將顯示在layoutTemplate{{>yield}}中。這通常不是您想要的登錄頁面。登錄頁面聽起來像自然的方式Router.go()或this.redirect()

定義路線:

都不行#2。然後,你可以這樣做:

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模板之前短暫地閃爍被展示。

你有沒有同樣的問題?

回答

9

好的,所以看起來路線上的渲染功能只能將模板渲染到當前佈局中。要將模板渲染到不同的佈局中,您必須致電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')

+1

它的作品,感謝凱利!我所要做的就是'Router.onBeforeAction(function(){if(!Meteor.userId())this.setLayout(「login」); \t}},{except:['login']});''看起來沒有必要調用'pause()' – steph643

+0

很高興幫忙!同樣,搞清楚這實際上有助於我學習鐵路路由器工作方式的新知識。 –

+1

'setLayout(undefined)'保持登錄佈局,所以我不得不創建一個空白模板,只是產生,並將您的最後一行改爲'this.setLayout(this.lookupLayoutTemplate()||'blank');' – Loren

0

你只需要從onBeforeAction()

onBeforeAction: function() { 

    if (_.include(['login'], this.route.name)){ 
    return; 
    } 

    if (!Meteor.userId()) { 

    return this.render('login'); 

    } 
} 

返回render()的結果還要注意,我改變Meteor.user()Meteor.userId()。這可以防止每次當前用戶文檔變得重新運行掛鉤。

+0

對不起,但這不起作用。如您所暗示的,省略對「暫停()」的調用時,「登錄」模板將不會呈現。當給你的建議增加「pause()」時,結果與上面的**「不工作#1」**相同。 – steph643

+0

我已經添加了一個檢查,以便鉤子不會爲登錄路徑運行..除此之外,我不知道可能會導致這種情況..我在我的所有項目中都使用此代碼,並且它工作得很好。 –

+0

可以肯定的是,即使從具有一個路徑的路由中調用,您是否確認提議的代碼可讓您獲得「登錄」表單而無需使用任何layoutTemplate? – steph643

0

在流星0.8.3對我的作品:

Router.onBeforeAction(function() { 
    if (_.include(['formLogin'], this.route.name)){ 
    return; 
    } 

    if (!Meteor.userId()) { 
    this.redirect('formLogin'); 
    return; 
    } 

}); 
3

它看起來這與等待waitOn中的訂閱有關。

下解決了佈局呈現問題對我來說:

Router.onBeforeAction(function() { 
    if (!Meteor.user() && this.ready()) 
     return this.redirect('/login'); 
}, {except: ['login']}); 
+8

應該指出,需要'else {this.next()}'。 –

20

你可以把if或除非在佈局模板模板幫手。

{{#unless currentUser}} 
    {{> loginPage}} 
{{else}} 
    {{> yield}} 
{{/unless}} 
+4

最優雅的解決方案,因爲它簡化了使用鐵路路由器時的複雜性,如果更新了「Meteor.user」,則無需重新路由。 – chuckus

+0

解決方案中的問題是,如果在LogIn頁面上存在指向其他模板/路由的鏈接(如註冊,恢復密碼等),則它們將不起作用,因爲'{{#unless currentUser}}'會避免任何其他路線運行。 – Ruben

相關問題