Prismatik / dendritic-ui

redbeard compartible standard UI library
3 stars 0 forks source link

Form the first spec #8

Open kaievns opened 8 years ago

kaievns commented 8 years ago

Well we need a FORM tag abstraction as well. As the first spec form should be able to abstract all the submit events and collect data from the child input fields:

<Form onSubmit={ data => this.save(data) }>
  <Input type="text" name="username" label="Username" />
  <Input type="password" name="password" label="Password" />
  <Button type="primary" submit busy={ this.props.saving }>Sign In</Button>
</Form>
nwinch commented 8 years ago

I suggest we use something such as redux-form (for redux projects) or formsy-react or react-forms, or something else.

redux-form is fantastic and works well, but if we don't want to be tied to redux implementation, then using one of the others might be an idea.

kaievns commented 8 years ago

i don't know, i feel like the ui components shouldn't care about how they are used much. redux form is okay, but i'd rather have a form that just does all the validation and spits back an object with all the data in it, so that then you could pass it into your application redux structure and deal with it there.

i feel like tying forms with apps redux will create unnecessary coupling between those two.

to reiterate, I think those should be just smart components, each does its small thing. and being that a Form component should just wait until everything is valid and it is submitted one way or another. once that happened it should just hand over the data and let the application deal with the actual business logic.

later on we will have to add web-socket syncs, and stuff to it, but for now we just solving a submit + data collection problem

nwinch commented 8 years ago

but i'd rather have a form that just does all the validation and spits back an object with all the data in it, so that then you could pass it into your application redux structure and deal with it there.

That's exactly what redux-form does ;) But you also have the bonus of onBlur, onChange et all events being tracked in realtime, validation, data normalization etc.. so much good stuff that we have used on at least 4 projects I've worked on so far, it would feel like a step backwards to remove this and start from step 1 again.

i feel like tying forms with apps redux will create unnecessary coupling between those two.

to reiterate, I think those should be just smart components, each does its small thing. and being that a Form component should just wait until everything is valid and it is submitted one way or another. once that happened it should just hand over the data and let the application deal with the actual business logic.

Yes and no. Yes, it will tie it to redux, but no, I don't think it's unnecessary. I think this a good thing. We're happy with redux and it seems like we'll be using it for a while yet, so I don't feel it's a big issue to have some of the components/functionality tied to that because of the context that we want to scaffold and build things fast and efficiently. The operative word being "some". If/when we move away from redux, we could look at doing our own thing then, but until then we should reap the speed bonus we get from using it. We can create a form with validation + submit/error API dispatching, onBlur credit card no. normalization, event handlers promisified, with tests blah blah in minutes.

To clarify - I'm not debating the merits of a loosely coupled architecture. But in this context, for getting MVP projects up and going quickly, I think it gives us an efficiency we shouldn't cast aside.

If there are other contenders for client state management we are thinking about using for upcoming projects other than redux, then yes perhaps we should look at something more broad - but I haven't heard that being the case at this stage.

kaievns commented 8 years ago

i think you misunderstood me here a bit. i'm not against redux, not at all. what i'm saying here is that the UI library should not know anything about the application that will use it.

i'm trying to avoid a situation where the UI components will tap directly into the application state tree. i'm all for optimizing the development process, and that is exactly what this is all about. if there is an external library that can do god knows what to my app inner state, it is an error prone solution. because time will come and things will go wrong and you will have to chaise the problem between two code bases. this is bad, and i want to avoid it.

look at the problem another way. as i'm building an application, i just want good data from a form. i have specified validation criteria with my schema or props, and at that point i don't really care how it works. i just want good data back so i could POST it to an API. for that reason i would normally use an onSubmit callback on a form, to separate concerns:

class App extends React.Component {
  render() {
    return <Form onSubmit={ goodData => this.save(goodData) }>
      <InputSet schema={ this.props.schema } />
    </Form/>
  }

  save(goodData) {
    this.props.saveData(goodData);
  }
}

if the form component takes care of all the validation and events for me, this is the shortest route to delivering a feature there is.

as for the onBlur and onChange we can surface those as well through props and callback, i don't see any problem with that. again my only concern here is that application should not know about the implementation details of the UI components.

if we end up using redux for those forms on the UI components side, that's all good, as long as it is a separate state tree from the application

nwinch commented 8 years ago

Yep, I definitely get what you're saying. And I don't think you're against redux at all, that wasn't an intended point from my response!

I don't think redux-form has the issues you're looking to avoid. Specifically this:

i'm trying to avoid a situation where the UI components will tap directly into the application state tree

redux-form works on top of, and alongside, react-reduxs connect function so it works in the same way. As per your example, we can do exactly that.

if the form component takes care of all the validation and events for me, this is the shortest route to delivering a feature there is.

Yep, we can do that.

Shall we sit down and look through some forms together? Might be easier for us to work through any concerns. I think if we kick the wheels of redux-form we'll end up smiles and high fives :)

kaievns commented 8 years ago

I think that will be the best

nwinch commented 8 years ago

I just had an idea when looking at the current form I'm working on - it's using redux-form - we could probably have both, if we build this component with the same props signature as what redux-form uses.

With redux-form:

import { reduxForm } from 'redux-form'
<Form />
export default reduxForm(Form);

Without redux-form:

const handleSubmit = () => apiSubmitAction;
const fields = { firstName: 'Garry' };
const validate = () => true;

<Form handleSubmit={handleSubmit} fields={fields} validate={validate} />

That way, both ways are possible with minimal hassle, and the form can be used in isolation without redux if a developer so wishes.

Thoughts?