Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering a form inside a bootstrap modal in Ember

There are plenty of questions already that ask about modals in Ember (like this one and this one). Even the cookbook has an article that explains how to use modals, but none of these cover form submissions that require validation from the server within the modal (ie, username already taken).

Following along with the cookbook, I have a named outlet in my application template.

{{outlet}}
{{outlet modal}}

And an action that triggers rendering a template inside the modal outlet (using bootstrap).

App.ApplicationRoute = Ember.Route.extend

  actions:
    openModal: (template, model) ->
      @controllerFor(template).set('model', model)
      @render template, into: 'application', outlet: 'modal'

    closeModal: ->
      @render '', into: 'application', outlet: 'modal'

Obviously I'm calling this action from within a link.

<a href="#" {{action openModal "person.edit" model}}>Edit</a>

Where model is the model of the current route.

In the PesonEditView I hook into the didInsertElement function to enable the bootstrap modal. Inside this hook, I also listen to the hidden.bs.modal event fired by bootstrap when the close button is clicked to clear out the modal outlet.

App.PersonEditView = Ember.View.extend

  didInsertElement: ->
    @$('.modal').modal('show').on 'hidden.bs.modal', =>
      @get('controller').send('closeModal')

My question is, how can I define a save action that will close the modal (using bootstraps animations) after it has validated on the server? The sequence of events that I see are required are, 1) save gets triggered on controller, 2) if successful save, close the modal (which would require calling @$('.modal').modal('hide') from the view).

I'm not sure what Ember experts would suggest here, since it seems as though the view and controller will need to communicate very closely.

Thanks!


EDIT

In response to edpaez's comment, I have tried resolving the promise returned by save from within the view. For example, in my template

<button type="button" class="btn btn-primary" {{action "save" target="view"}}>Save</button>

The view

App.PersonEditView = Ember.View.extend
  actions:
    save: ->
      @get('controller').send('save').then(@closeModal.bind(@))

  closeModal: ->
    @$('.modal').modal('hide')

  # the rest omitted for brevity

And the controller

App.PersonEditController = Ember.ObjectController.extend
  actions:
    save: ->
      @get('model').save()

I get the following error

Uncaught TypeError: Cannot call method 'then' of undefined
like image 899
Feech Avatar asked Nov 11 '22 16:11

Feech


1 Answers

Try targeting the save action to the view:

<button type="button" class="btn btn-primary" {{action "save" target="view"}}>Save</button>

and call a save method in the controller. That method would return a promise that would resolve when the save method from the model resolves.

App.PersonEditView = Ember.View.extend
  actions:
    save: ->
      @get('controller').save().then(@closeModal.bind(@))

  closeModal: ->
    @$('.modal').modal('hide')


App.PersonEditController = Ember.ObjectController.extend
    save: ->
      @get('model').save()

This way, the controller abstracts the model-saving logic and the view gets notified when the model saves so it can behave as expected.

Make sure you call the save method in the controller instead of sending an action. the send method returns nothing.

Hope it helps!

like image 71
edpaez Avatar answered Dec 06 '22 17:12

edpaez