2012-10-23 3 views
7

Ich erstelle eine Router-basierte EmberJS App (stark nach dem excellent router guide modelliert). Allerdings bin ich ziemlich verwirrt darüber, was in einer Ansicht vs in einem Controller gehört.EmberJS Router App: Ansichten vs Controller

Ich bekomme total, dass {{action showFoo}} oft eine Zustandsänderung anzeigt und dass der Router der Zustandsautomat für meine App ist. Aber einige meiner Handlungen fallen nicht in diese Kategorie.

Hier ist ein Beispiel aus meinem tatsächlichen Code (HTML vereinfacht, aber Schnurrbärte intakt). Ich möchte ein Login-Formular haben, das über Ajax funktioniert (d. H. Das HTML-Formular posten nicht direkt zum Server, es teilt meiner Ember-App mit, einen Login über JSON zu versuchen).

<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> 

Die valueBindings sind Felder in meinem loginController aber die logIn Handler ist in meiner Sicht (weil ich nicht verstehen konnte, wie die Vorlage zu sagen, um den Controller zu nennen). Ich fühle mich wie eine seltsame Verteilung & Ich bin mir nicht sicher, was der richtige Ember-Ansatz dazu ist.

Ich glaube nicht, dass der Router die Aktion behandeln sollte, da die Anforderung eines Anmeldeversuchs nicht wirklich eine Statusänderung ist. Der loginController fühlt sich an der richtigen Stelle an versuchen Sie das Login. Nachdem eine Login-Antwort empfangen wurde, könnte dieser Controller die Statusänderung auslösen.

Antwort

3

Ich glaube nicht, dass der Router sollte die Aktion sein Handling, weil ein Anmeldeversuch anfordernden nicht wirklich ein Änderungszustand ist.

Ich denke, das ist genau der Fall: ein Login-Versuch zu einem authenticating Zustand übergehen sollte, in dem zum Beispiel ein weiterer Klick auf „Login“ wird ignoriert.

Also IMHO sollte dies vom Router behandelt werden. Ich bin über so etwas wie dieses zu denken, sehen http://jsfiddle.net/pangratz666/97Uyh/:

Lenker:

<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

Dank, ich mag dieses Modell . Ich fange gerade an, die Idee, den Router effektiv für das State Management zu benutzen, in den Griff zu bekommen. Ich denke an "authentifiziert" vs. "nicht authentifiziert" wie Staaten mit Unterrouten ist jetzt wirklich offensichtlich und ziemlich nett in meinen Gedanken. – Boon

+0

@pangratz - Müssten alle authentifizierten Ansichten unter der Route eingeloggt sein, in Ihrem Beispiel oben z. B. /admin/newView? – Upworks

+0

@Upworks Ja ... – pangratz

1

Sie können den Controller dafür verwenden, die Vorlage, die Sie verwenden, haben Zugriff auf den Controller.

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

Diese Geige ist eine kleine Anwendung, die das tut: fiddle

Dann nach der Anmeldung aufgetreten Sie actioncall an Ihren Router machen können, oder dem Benutzer zeigen, dass nicht einloggen.

1

Ich habe gerade machte es durch eine Änderung erfolgt, um die Codes wie:

{{ action logIn target="controller" }} 
Verwandte Themen