AppliedMathematicsANU / plexus-form

A dynamic form component for react using JSON-Schema.
MIT License
134 stars 31 forks source link

Make it easier to customize `buttons`? #20

Closed bebraw closed 9 years ago

bebraw commented 9 years ago

I feel the current button solution isn't easy to extend. I have a little demo running at http://bebraw.github.io/reactabular/ . As you can see, the form styling isn't that great. Besides #19 it would be useful if I could define buttons that are external to the form itself.

For this to work I would require some kind of hooks that I could trigger. I'm not sure what the correct API would look like. Perhaps something could be done through refs? In pseudocode something like this would work:

onOK() {
    this.refs.form.submit();
}

...

<Form ref='form' ... />

I guess ref works to some extent already. The problem is that if you are constructing a Form dynamically (no parent element yet), React won't allow you to assign a ref... Maybe ideal design is something else then.

odf commented 9 years ago

Maybe we could start by introducing a buttonClass property that is copied into className for buttons. If that's not enough, we might also add a renderButton property which allows users to specify an arbitrary function to be called when rendering a button.

I think the key to completely separating the button rendering from the form component itself, which I definitely see the appeal of, might be the submitOnChange property. This should make it quite easy to write a wrapper which monitors the state of the form and renders its own buttons.

Come to think of it, we might even make submit on change be the default behaviour in the core Form component and add a standard wrapper FormWithButtons which would take on the role of the current Form. Users who want different button rendering or different submit semantics could then simply copy and modify the FormWithButtons code.

bebraw commented 9 years ago

Come to think of it, we might even make submit on change be the default behaviour in the core Form component and add a standard wrapper FormWithButtons which would take on the role of the current Form. Users who want different button rendering or different submit semantics could then simply copy and modify the FormWithButtons code.

Yeah. It could make sense to separate the concepts of a Form and Buttons. It would be enough for me if it was possible to inject custom buttons to the current Form. Technically the easiest way to achieve this would be to do something like this:

    var buttonValues = this.props.buttons;

    var buttons = this.props.buttons || function(submit) {
      return $.p(null,
                 (buttonValues || ['Cancel', 'Submit']).map(function(value) {
                   return $.input({ type   : 'submit',
                                    key    : value,
                                    value  : value,
                                    onClick: submit })
                 }));
    };

    return $.form({ onSubmit: this.preventSubmit,
                    onKeyPress: this.handleKeyPress
                  },
                  this.props.extraButtons ? buttons() : $.span(),
                  fields,
                  buttons(this.handleSubmit));
  }

If you want to override the buttons now, all you need to do is to implement the same interface and bind submit handler.

odf commented 9 years ago

Sounds good to me. I think I'll implement both buttonClass and buttons-as-a-custom-function for now, and think a bit more about that refactoring idea.

odf commented 9 years ago

Support for a user-supplied buttons function is provided as of @20c2c0d68d962a060e57fa935edbe9cfa89b7438.