2012-10-23 66 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" }} 
相关问题