Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example of advanced form #527

Closed
wants to merge 1 commit into from
Closed

Conversation

jeffcarbs
Copy link
Member

Based on the comment I left of #407 regarding a more advanced form component, I put together an example. Right now the whole thing is in the example file but ideally we'd be able to move some/all of this logic into the Form itself.

The goals here are:

  • being able to describe a form's structure as data and have it be rendered automatically
  • have the form track it's own state outside of the DOM
  • automatically handle advanced functionality like adding/removing items

The schema is basically just an array of form subcomponent props, which can be continually nested.

The following schema:

[
  {
    type: 'group',
    schema: [
      { type: 'text', name: 'firstName' },
      { type: 'text', name: 'lastName' }
    ]
  },
  { type: 'text', name: 'title' },
  { type: 'text', name: 'company' },
  {
    type: 'nested',
    name: 'emailAddresses',
    schema: [
      { type: 'text', name: 'label', label: null },
      { type: 'text', name: 'value', label: null }
    ]
  },
  {
    type: 'dropdown', name: 'gender', options: [
      { text: 'Male', value: 'male' },
      { text: 'Female', value: 'female' }
    ]
  },
  {
    type: 'checkbox', name: 'newsletter', label: 'Interested in receiving newletter'
  },
  { type: 'submit', name: 'Submit' }
]

produces:
screen shot 2016-09-22 at 2 09 20 pm

The component can almost certainly be cleaned up a little, I just whipped this together this morning. It also doesn't have provide a way for an outside component listen for onChange, but that would be pretty straightforward. I'd imagine in the setValue call we'd just pass those same arguments to a onChange.

@levithomason
Copy link
Member

Cool, will pull this and offer some feedback.

}
}

const formSchema = [
Copy link
Member

@levithomason levithomason Sep 22, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, let's iterate on it and see where it goes! Here's my first proposal:

  • each object should be spread on the field
  • explicitly define the field control prop, instead of reusing type
  • use an array of fields where nested arrays would be groups
  • default the control to Input and type to text
  • capitalized control values will use the Stardust control, lower case for HTML controls (e.g. input vs Input)

This would make it more inline with our other shorthand. It also gives the user more control, we could allow them to pass an actual control component and it's props, just like the Field does. Finally, we're just spreading prop objects, a good thing.

I've left out the email nested part for now. A refactor might look like this:

const formSchema = {
  fields: [
    [
      { name: 'firstName' },
      { name: 'lastName' },
    ],
    { name: 'title' },
    { name: 'company' },
    {
      control: 'Dropdown',
      name: 'gender',
      selection: true,
      options: [
        { text: 'Male', value: 'male' },
        { text: 'Female', value: 'female' },
      ],
    },
    { control: 'Checkbox', name: 'newsletter', label: 'Interested in receiving newletter' },
    { control: 'Button', type: 'submit', name: 'Submit' },
  ],
}

I could see an argument for allowing a simple string for the name. Not sure how feel about adding more special case magic though:

const formSchema = {
  fields: [
    ['firstName', 'lastName'],
    'title',
    'company',
    // ...
  ],
}

@UnbrandedTech
Copy link
Contributor

In the forms my company use, there are a lot of "duplicators" where an entry has an array of objects

{
    "Supplies":[
	    {
	    	"Name":"Thing1",
	    	...
	    },
	    {
	    	"Name":"Thing2",
	    	...
	    },
    ]
}

Which looks like this when rendered

<Grid>
	{fields.map((field, index) =>
	<Grid.Row key={index}>
		<Grid.Column>
			<Input name={`Supplies[${index}].Name`}>
		</Grid.Column>
		...
		<Grid.Column verticalAlign='middle'>
			<Button type="Button" icon='remove' onClick={() => fields.remove(index)}/>
		</Grid.Column>
	</Grid.Row>
	)}
	<Grid.Row>
		<Grid.Column>
			<Button type="button" content={`Add a Supply`} onClick={() => fields.push()} icon='plus' labelPosition='left' ></Button>
		</Grid.Column>
	</Grid.Row>
</Grid>

We use redux-form which handles this, but we'd like to use semantic's version what ever you decide to implement.

@levithomason
Copy link
Member

Cool, good info. Also @UnbrandedTech Grids/Rows/Columns can almost be replaced directly with Forms/Groups/Fields 👍 The layout APIs are somewhat similar.

@levithomason
Copy link
Member

Closing for housekeeping.

@levithomason levithomason deleted the feature/advanced-forms branch July 16, 2017 22:13
@levithomason levithomason restored the feature/advanced-forms branch July 16, 2017 22:13
@layershifter layershifter deleted the feature/advanced-forms branch May 8, 2018 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants