jonjamz / blaze-forms

Dead easy reactive forms with validation (Meteor).
https://atmospherejs.com/templates/forms
MIT License
113 stars 11 forks source link

Add `onDataChange` hook and expose useful API endpoints #55

Closed matthieugicquel closed 9 years ago

matthieugicquel commented 9 years ago

Hi,

Let's suppose you have a UI with a list of items and an edition form. A click on an item in the list triggers its edition in the form. And there is a "new item" button. For me this is a fairly common usecase, and this package would be really great if it allowed to do that easily.

I tried but this is really painful for now :

  1. I had to enable passThroughData on all the elements I use, to support changing the document reactively, but this feature was not designed for that.
  2. There is no way to reset the form when the "new item" button is clicked, and no way to reset form state when changing the item being edited because the reset callback is only available in the action function.
  3. When you switch to an item where some fields are absent, form elements are not cleared, they keep the data of the previous item.

I tried to think about a good and unobtrusive way to implement this feature... There should be a way to tell the form component that the document has changed, and when this happens it must :

The simplest solution would be to make it an "alternate mode" of handling any change of the reactive data. But you could not have this and the current in-document reactive changes handling at the same time...

A better way would be to be able to specify one variable in data that identifies the document : when it changes, it means the document has changed, when it does not exist, it means we're starting a new document → full reset. There would be an API like that :

ReactiveForms.createFormBlock
    template: 'myItemForm'
    dataID: '_id' # When data._id changes, the form will be "reset" with the new initial data

So, 1 one line for the user, but clearly some work to do on the package...

What do you think of it ?

jonjamz commented 9 years ago

This is a good idea. Let me think about this for a bit. I don't think it will be too hard to add.

jonjamz commented 9 years ago

I think what you're really looking for here is a hook that's called when underlying data changes and gives you access to some useful methods. Like this:

ReactiveForms.createFormBlock
  onDataChange: (oldData, newData) ->
    if oldData._id isnt newData._id then @reset(true)

Or even a function you pass in via template helpers, like:

{{#myFormBlock 
  data=data 
  action=action 
  schema=schema 
  onDataChange=onDataChange}}
  ...
{{/myFormBlock}}

That way it's more situational than putting it in createFormBlock.

What do you think?

matthieugicquel commented 9 years ago

That seems great. I agree the helper function is better.

After the reset, we need a way to say explicitly that we want to use the new data, even if passthroughData is not enabled. Either a @setData(newData) method or simply returning true in the hook...

jonjamz commented 9 years ago

This is coming along. Should have an update out in the next day or two.

matthieugicquel commented 9 years ago

Any news on that ?

jonjamz commented 9 years ago

This should be working in the latest release. Please see the changelog and test it out. Thanks!

matthieugicquel commented 9 years ago

It works great ! One issue though : How do you clear elements changed state ? this.reset(true) does not seem to do it.

jonjamz commented 9 years ago

I'll add this today, not a problem.