1

I am trying to accomplish something like this, in an ember view:

{{#if loggedIn}}
   <p> I'm Logged In! </p>
{{else}}
   {{view App.LoginView contentBinding="App.UserInfo"}}
{{/if}}

This doesn't work out of the box because the context for LoginView ought to be loginController, and *that controller's content" ought the be App.UserInfo.

This discussion has some related notes, and suggests outlets:

Instantiate a controller class using the {{view}} helper?

Outlets provide a clean solution to this - for example, I could do:

{{#if loggedIn}}
   <p> I'm Logged In! </p>
{{else}}
   {{outlet login}}
{{/if}}

and then have the router connect the controller for this view (call it homeController) to the login outlet with LoginView and some context.

However, using outlets, if the loggedIn property changes, the outlet isn't reconnected/redrawn, so if I log in and then log out again I get a blank page.

Is there a nice way to either bind the appropriate controller and controller content using the view helper, or set up the outlet in a way that makes it redraw appropriately if the loggedIn property changes?

Community
  • 1
  • 1
mg2
  • 83
  • 8
  • 1
    Is there a reason you can't use `controllerBinding`? `{{view App.LoginView controllerBinding="App.router.loginController" }}` – tuxedo25 Dec 19 '12 at 22:30
  • That gets me part of the way there but the contentBinding still falls short - I want the contentBinding to be the content of the controller - which I get from connectOutlet, but not from controllerBinding. I guess I could add a contentBinding at the controller automatically binding it to the view... – mg2 Dec 19 '12 at 23:34
  • 2
    Yeah, or try setting a 'contentBinding' property on LoginView itself: something like `contentBinding: 'controller.content'` – tuxedo25 Dec 19 '12 at 23:46
  • Unfortunately neither of these seem to work either. The trouble with setting contentBinding on the view and hoping it propogates to the controller is that my {{view}} helper overrides the contentBinding setting so it's no longer bound to the controller. And the trouble with putting the contentBinding in the controller is that if you say something like contentBinding: "App.LoginView.content", you're binding to the class, not the actual view instance in question. – mg2 Dec 20 '12 at 04:00
  • It feels like there should be an easy way to do this - just because, the context for the view is always the controller, and the outlet mechanism handles it so well - it sets up a view instance and if you give it content it (naturally) sets that to the controller's content so you have access to it in the view. The view helper ought to have a similar construct somehow, no? – mg2 Dec 20 '12 at 04:01
  • 1
    What is wrong with your outlet approach? You could use {{#if loggedIn}}

    I'm Logged In!

    {{/if}} {{outlet login}}. In this case the outlet will always be in the DOM. And it is the task of your router implementation to connect the outlet just in the case, that the user is not logged in (e.g.: Disconnect the outlet upon login).
    – mavilein Dec 20 '12 at 11:55
  • 1
    This kind of logic should not be handled in the view imho. This is complex logic which affects the whole app and should therefore be handled in the router. – mavilein Dec 20 '12 at 11:56
  • In the context of something like "are you logged in," I suppose I could delegate the logic to the router - but I still feel like I'm missing something about the overall function of the {{view}} helper. A view is rendered with the controller's content as its context, always, correct? So if I want to call on a property, I need to either specify an absolute path, specify a path relative to the view (view.content.somethingOrOther), or I need to set the content of the controller? And yet, I don't seem to be able to set the content of a controller using a view helper - is that correct? – mg2 Dec 20 '12 at 14:19
  • That's correct @mg2. You should only be setting the `content` if controllers in a router/stateManager. – Luke Melia Dec 22 '12 at 03:17
  • 1
    @mg2, I think [this jsfiddle](http://jsfiddle.net/r2Dw6/12/) accomplishes what you were originally trying to do. I set the view's context to a new UserInfo object at view init. There is definitely a breakdown in abstraction (global paths, nowhere to know about the logged in user's username), but it's a starting point. – tuxedo25 Dec 22 '12 at 15:05
  • 2
    To build on @mavilein's idea, maybe instead of handling login state in the router (whose responsibility should be limited to routing), you could have an App.loginManager (class LoginManager extends StateManager) that handles the state of being logged in our out and authenticating (if you're doing that client side). You could make a handlebars helper to echo out {{username}} or other details, too. – tuxedo25 Dec 22 '12 at 15:14
  • Thanks all. These are all good suggestions and a combination of them will definitely work for me - I appreciate all the help and feedback. I confess I'm still a little confused about why this functionality doesn't belong as an argument to the view helper - again, a view is commonly rendered with the controller's content as its context so it seems totally natural to me that you'd want to set up the content of the controller as part of the view - but setting the content in the router or using a specialized stateManager both seem like very workable solutions. Appreciate it! – mg2 Dec 23 '12 at 14:50

0 Answers0