2012-10-23 67 views
7

我創建了一個基於路由器的EmberJS應用程序(強烈建模在excellent router guide上)。然而,我對於視圖和控制器中屬於什麼的東西相當混亂。EmberJS路由器應用程序:視圖vs控制器

我完全知道{{action showFoo}}通常表示狀態發生變化,並且路由器是我的應用的狀態機。但是我的一些行爲不屬於這一類。

下面是我的實際代碼(html簡化,但鬍鬚完整)的一個例子。我想要一個通過ajax工作的登錄表單(即,html表單不會直接發佈到服務器,它會告訴我的ember應用程序嘗試通過json登錄)。

<form> 
    Email Name: {{view Ember.TextField valueBinding="email"}} 
    Password: {{view Ember.TextField valueBinding="password"}} 
    <button type="submit" {{ action logIn target="this" }}>Sign in</button> 
</form> 

的valueBindings在我的LoginController領域,但是登錄處理程序,在我看來(因爲我無法弄清楚如何告訴模板調用控制器)。我覺得這是一個奇怪的分佈&我不知道什麼是正確的Ember方法是這樣的。

我不認爲路由器應該處理這個動作,因爲請求登錄嘗試並不是一個真正的狀態變化。 loginController感覺像嘗試登錄的正確位置。收到登錄響應後,該控制器可能會觸發狀態更改。

回答

3

我不認爲,路由器應處理行動,因爲請求的登錄嘗試是不是一個真正的狀態改變。

我認爲這是正是的情況:在嘗試登錄應過渡到authenticating狀態,其中,例如,到「登錄」被忽略的另一個點擊。

所以恕我直言,這應該由路由器處理。我想這樣的事情,看到http://jsfiddle.net/pangratz666/97Uyh/

把手

<script type="text/x-handlebars" > 
    {{outlet}} 
</script> 

<script type="text/x-handlebars" data-template-name="login" > 
    <p class="info">{{message}}</p> 
    Login to view the admin area <br/> 
    Email: {{view Ember.TextField valueBinding="email" }} <br/> 
    Password: {{view Ember.TextField valueBinding="password" }} <br/> 
    <button {{action login}} >Login</button> 
</script> 

<script type="text/x-handlebars" data-template-name="authenticating" > 
    Communicating with server ... 
</script> 

<script type="text/x-handlebars" data-template-name="admin" > 
    Hello admin! 
</script> 

的JavaScript

App = Ember.Application.create(); 

App.ApplicationController = Ember.Controller.extend({ 
    login: function() { 
     // reset message 
     this.set('message', null); 

     // get data from login form 
     var loginProps = this.getProperties('email', 'password'); 

     // simulate communication with server 
     Ember.run.later(this, function() { 
      if (loginProps.password === 'admin') { 
       this.set('isAuthenticated', true); 
       this.get('target').send('isAuthenticated'); 
      } else { 
       this.set('message', 'Invalid username or password'); 
       this.set('isAuthenticated', false); 
       this.get('target').send('isNotAuthenticated'); 
      } 
     }, 1000); 

     // inform target that authentication is in progress   
     this.get('target').send('authenticationInProgress'); 
    }, 
    logout: function() { 
     this.set('isAuthenticated', false); 
    } 
}); 
App.ApplicationView = Ember.View.extend({ 
    templateName: 'application' 
}); 

App.LoginView = Ember.View.extend({ 
    templateName: 'login' 
}); 
App.AdminView = Ember.View.extend({ 
    templateName: 'admin' 
}); 
App.AuthenticatingView = Ember.View.extend({ 
    templateName: 'authenticating' 
}); 

App.Router = Ember.Router.extend({ 
    root: Ember.Route.extend({ 
     index: Ember.Route.extend({ 
      route: '/', 
      loggedOut: Ember.Route.extend({ 
       route: '/', 
       connectOutlets: function(router) { 
        router.get('applicationController').connectOutlet('login'); 
       }, 
       login: function(router) { 
        router.get('applicationController').login(); 
       }, 
       authenticationInProgress: function(router) { 
        router.transitionTo('authenticating'); 
       } 
      }), 
      authenticating: Ember.State.extend({ 
       enter: function(router) { 
        router.get('applicationController').connectOutlet('authenticating'); 
       }, 
       isAuthenticated: function(router) { 
        router.transitionTo('loggedIn'); 
       }, 
       isNotAuthenticated: function(router) { 
        router.transitionTo('loggedOut'); 
       } 
      }), 
      loggedIn: Ember.Route.extend({ 
       route: '/admin', 
       connectOutlets: function(router) { 
        if (!router.get('applicationController.isAuthenticated')) { 
         router.transitionTo('loggedOut'); 
        } 
        router.get('applicationController').connectOutlet('admin'); 
       }, 
       logout: function(router) { 
        router.get('applicationController').logout(); 
       } 
      }) 
     }) 
    }) 
});​ 
+0

謝謝,我很喜歡這種模式。我剛剛開始認識到有效地使用路由器進行狀態管理的想法 - 思考「已認證」與「未認證」的關係,因爲具有子路由的國家現在非常明顯,而且在我看來非常好。 – Boon

+0

@pangratz - 是否所有的認證視圖需要嵌套在你的例子中的loggedIn路由下方eg/admin/newView? – Upworks

+0

@Upworks是的... – pangratz

1

您可以使用此控制器,您使用的模板可以訪問控制器。

<script type="text/x-handlebars" data-template-name="loginTemplate"> 
    {{#if controller.login}} 
    Logged in! 
    {{else}} 
    Login failed 
    {{/if}} 
</script> 

這撥弄顯示了一個小的應用程序,這這是否:fiddle

登錄已發生之後之後就可以做出actioncall到路由器,或顯示登錄失敗的用戶。

1

我剛纔提出它的變化完成的代碼爲:

{{ action logIn target="controller" }} 
相關問題