Skip to content

Instantly share code, notes, and snippets.

@jamesarosen
Last active September 9, 2016 19:37
Show Gist options
  • Save jamesarosen/a7d6299caec9f05befb93dd53a759b86 to your computer and use it in GitHub Desktop.
Save jamesarosen/a7d6299caec9f05befb93dd53a759b86 to your computer and use it in GitHub Desktop.
A discussion of fields and forms in Ember

I have a form with three fields: Foo, Bar, Baz. Bar is really sensitive, so if the user changes it, I want to show a confirmation modal when the user tries to submit the form (but not until then). Currently, we have the is-bar-changed and show-modal logic in the containing form. I'd prefer to move it down into a component:edit-bar. But I can't figure out a good way to model that component having an opportunity to pause the parent form's submission, then continue or abort asynchronously.

Pass Down Hook Registry

One option would be for the form to yield some sort of hook registry:

{{#generic-form action='saveModel' as |form|}}
  {{generic-field 'Foo' value=model.foo}}
  
  {{bar-field value=model.bar form=form}}
  
  {{generic-field 'Baz' value=model.baz}}
{{/generic-form}}
// component:bar-field
export default Ember.Component({
  form: null,
  
  init() {
    this._super(...arguments);
    const form = this.get('form');
    if (form != null) { form.onBeforeSave(this, 'confirmChangeBar'); }
  },
  
  willDestroy() {
    const form = this.get('form');
    if (form != null) { form.offBeforeSave(this, 'confirmChangeBar'); }
    this._super(...arguments);
  },
  
  confirmChangeBar() {
    if (this.get('valueIsDirty')) {
      return new Ember.RSVP.Promise((resolve, reject) => {
        const ok = confirm('Are you sure you want to change Bar?');
        if (ok) { resolve(); }
        else { reject(); }
      });
    }
  }
});

Unfortunately, it can't use Ember.Evented because the form doesn't have any way to get the return values of the handlers from .trigger.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment