Reputation: 276
Thanks to the great presentation from Luke Melia during the last EmberJS NYC meetup, I've spent the night and all day refactoring my stuff to apply some of your concept and I really appreciate how I got to better understand part of the framework.
When questioned about how he would handle enabling the controller to dictate some of the view's behavior, he mentioned observing the controller's attribute in the view. With that in mind, I went ahead and split my app to make sure I was leveraging the router ability to manage state. So I created an EditProfile route.
To dictate the toggling of my EditProfile section I created a showEditProfile attribute on my EditProfileController and I set up an observer in my EditProfileView.
The problem is that I can't get it to work. If I click on the "save" or "cancel" button in my EditProfile template, it triggers the "confirmProfileUpdate" or "cancelProfileUpdate" respectively which in turns set the showEditProfile to false. Doing that should trigger the view's observer, right? It doesn't seems to be the case.
Here is the code:
application_routes.coffee
App.ApplicationRoute = Ember.Route.extend(
setupController: ->
@controllerFor("user").set "model" App.User.find(App.current_profile_id)
)
edit_profile.hbs
<div id="profile_edit">
<div class="section">
<h1>Edit Profile</h1>
</div>
<form id="edit_user">
<div class="section">
<label>Name</label>
{{view Em.TextField valueBinding="name" }}
<label>Location</label>
{{view Em.TextField valueBinding="location" }}
<label>Motto</label>
{{view Em.TextField valueBinding="description" }}
</div>
<div class="section">
<label>Email</label>
{{view Em.TextField valueBinding="email" }}
<label>Password</label>
{{view Em.TextField valueBinding="password" type="password" }}
<label>Re-enter Password</label>
{{view Em.TextField valueBinding="password_confirmation" type="password" }}
<div class="btns">
<button type="submit" class="btn" {{action "confirmProfileUpdate" content}}>Save</button>
<button type="submit" class="btn" {{action "cancelProfileUpdate" content}}>Cancel</button>
</div>
</div>
</form>
</div>
edit_profile_controller.coffee
App.EditProfileController = Ember.ObjectController.extend(
showEditProfile: true
)
edit_profile_routes.coffee
App.EditProfileRoute = Ember.Route.extend(
renderTemplate: ->
@render "edit_profile", {outlet: "edit_profile", controller: 'user'}
events:
confirmProfileUpdate: (record) ->
record.get("transaction").commit()
# @transitionTo('index')
console.log "confirmed! toggling the slider back up"
@controller.set "showEditProfile", false
cancelProfileUpdate: (record) ->
record.get("transaction").rollback()
# @transitionTo('index')
console.log "cancelling! toggling the slider back up"
@controller.set "showEditProfile", false
)
edit_profile_view.coffee
App.EditProfileView = Ember.View.extend(
toggleEditProfile: (->
console.log "toggling!"
$("#profile_ edit").slideToggle "slow"
).observes("controller.showEditProfile")
didInsertElement: ->
@controller.set "showEditProfile", true
)
I've created a simplified example of Luke's approach which works: http://jsbin.com/ujosew/4/edit
So at this point, I am wondering if there is not a confusion about which controller my view is observing (you will have noted that EditProfileController is using the User model).
Any hint to a solution would be beneficial as I am running short of options...
--- Edit thanks to the help of Alex Matchneer (@machty) on the #emberjs IRC chan (which I recommend to everyone looking for guidance) ---
As Teddy pointed out in his answer, by changing the controller, it was normal that the observer was not going to react. So I changed the code to this and it now works
application_routes.coffee
App.ApplicationRoute = Ember.Route.extend(
setupController: ->
@controllerFor("user").set "model" App.User.find(App.current_profile_id)
)
edit_profile.hbs
<div class="section">
<h1>Edit Profile</h1>
</div>
<form id="edit_user">
<div class="section">
<label>Name</label>
{{view Em.TextField valueBinding="name" }}
<label>Location</label>
{{view Em.TextField valueBinding="location" }}
<label>Description</label>
{{view Em.TextField valueBinding="description" }}
</div>
<div class="section">
<label>Email</label>
{{view Em.TextField valueBinding="email" }}
<label>Password</label>
{{view Em.TextField valueBinding="password" type="password" }}
<label>Re-enter Password</label>
{{view Em.TextField valueBinding="password_confirmation" type="password" }}
<div class="btns">
<button type="submit" class="btn" {{action "confirmProfileUpdate" content}}>Save</button>
<button type="submit" class="btn" {{action "cancelProfileUpdate" content}}>Cancel</button>
</div>
</div>
</form>
edit_profile_controller.coffee
App.EditProfileController = Ember.ObjectController.extend(
needs: ['user']
visible: true
)
edit_profile_routes.coffee
App.EditProfileRoute = Ember.Route.extend(
renderTemplate: Ember.K
setupController: ->
@controllerFor("edit_profile").set "model", App.User.find(App.current_profile_id)
activate: ->
@controllerFor("edit_profile").set "visible", true
deactivate: ->
@controllerFor("edit_profile").set "visible", false
events:
confirmProfileUpdate: (record) ->
record.get("transaction").commit()
@transitionTo('index')
cancelProfileUpdate: (record) ->
record.get("transaction").rollback()
@transitionTo('index')
)
edit_profile_view.coffee
App.EditProfileView = Ember.View.extend(
classNames: ['profile_edit']
toggleEditProfile: (->
$(".profile_edit").slideToggle "slow"
).observes("controller.visible")
didInsertElement: ->
$(".profile_edit").slideToggle "slow" if @get("controller.visible")
)
Upvotes: 0
Views: 2529
Reputation: 3971
By overriding renderTemplate
:
@render "edit_profile", {outlet: "edit_profile", controller: 'user'}
You set the view's controller to be App.UserController
.
In the route, @controller
is App.EditProfileController
, but in the view, controller
property refers to App.UserController
.
They are referencing different controllers.
Upvotes: 1