-
Notifications
You must be signed in to change notification settings - Fork 165
Conversation
@@ -0,0 +1,22 @@ | |||
# Choice Field |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the reasoning for naming this a ChoiceField, as opposed to something like RadioGroup?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the main decision was to keep in consistent naming with the textareaField and textField components. I'm not opposed to renaming it radio group though. Perhaps it should be RadioGroupField to indicate that it utilizes a field component as well?
|
||
const propTypes = { | ||
/** | ||
* Choices to populate radio buttosn for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo on buttons
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const defaultProps = { | ||
choices: [], | ||
choiceName: 'name', | ||
choiceValue: 'value', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From a form submission standpoint I think defaulting these values could be really dangerous, accidentally submitting incorrect information to a server or selecting unintentional fields as the default.
Edit: I might be confusing choiceName / choiceValue from name / value
It looks like these define the key value pairs in the choices
prop hash array, this feels like a really confusing API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct. the choiceName is the label of the input, and choiceValue is the value of the input. I like the idea you posted down with the children. I'll see what other developers think of it as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about nameKey
and valueKey
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if that's better though. I see a need to pass in additional attributes to the individual nodes as well. I think we should just require the same api structure as that of the actual choice input, meaning we just rely on the name and value attributes straight up. Otherwise, this api will be very confusing for users to consume.
packages/terra-form/package.json
Outdated
}, | ||
"peerDependencies": { | ||
"react": "^15.4.2", | ||
"react-dom": "^15.4.2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to add "terra-base": "^0.x",
to peerDependencies and dependencies.
/** | ||
* Choices to populate radio buttosn for | ||
*/ | ||
choices: PropTypes.array, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe Brett called out on the original Tech Design that this prop might make more sense being called options
.
I personally don't think we should use a prop API that consists of an Array of hashes with key value pairs. The React form libraries I've worked with use children and I think it makes it a lot easier for the consumer.
<RadioGroup onChange={this.onChange} value={this.state.value}>
<Radio value={1}>A</Radio>
<Radio value={2}>B</Radio>
<Radio value={3}>C</Radio>
<Radio value={4}>D</Radio>
</RadioGroup>
https://ant.design/components/radio/#components-radio-demo-radiogroup
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to that idea. I think that looks more clear than passing in choiceName and choiceValue as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The React form libraries I've worked with use children and I think it makes it a lot easier for the consumer
I think this depends on if you are dealing with static choices that are coded or dynamic choices populated from the server.
These options aren't mutually exclusive. Technically what you're describing can already be done use the current design.. ChoiceField is just a higher order component that does that for you. It prevents consumers from having to do the boilerplate code of listing our the radio fields or looping over them and creating them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish these conversations would have happened on the design as it would have been easier to follow... but the Field components are convenience molecules to make it easy to create the proper inputs to capture the proper data. Nothing prevents anyone from generating forms in a style that leaks the implementation details of HTML
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultimately, OCS from what I hear is going to specify rules that dictate when you use radios/checkboxes vs select vs search. That will rule out using a static approach of rendering radios such as this because it should flex depending on how many choices there are.
I propose enable what you're suggesting, but also create choiceField which will be the abstraction to flip impl between select and radios depending on how many choices there are.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added this topic to the War Room agenda, will you be able to attend on Friday?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
War room discussion output was that we create the <RadioGroup />
component that uses children API and a <ChoiceField />
that uses a hash API.
error="This field is required" | ||
help="State Locations help determine what campus to place you at" | ||
required={true} | ||
attrs={{ className: 'healtheintent-application' }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the ChoiceField.jsx below I don't think attrs is actually used in this component.
@@ -0,0 +1,103 @@ | |||
/* eslint-disable jsx-a11y/label-has-for */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the error being thrown for on this?
/** | ||
* Additional attributes for the input object | ||
*/ | ||
attrs: PropTypes.object, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does anyone have strong opinions on this? Something like inputAttributes seems more clear to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think some of us agreed to switch it to that. I'll make the change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inputAttributes
seems extremely verbose.... FWIW, this follows the pattern of what Django does which uses attrs
and has worked there. I'd rather have to check the documentation once, learn what it is and then use that going forward over having to type inputAttributes
every time I set this...
https://docs.djangoproject.com/en/1.11/ref/forms/widgets/#django.forms.Widget.attrs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the war room, we came to a census for inputAttrs
* Initial Value of the input | ||
*/ | ||
value: PropTypes.string, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should there be a first class prop for defaulting the value to be checked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To that comment, wondering if control would be simplified if it simply had an input property and was explicitly passed the input (rather than attempting to wrap it)
packages/terra-form/docs/Field.md
Outdated
value="children_present" | ||
error="This field is required" | ||
help="Families are eligible for family package plans" | ||
required={true} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the Field accept the required prop?
/** | ||
* Functional to be called when the input is changed. | ||
*/ | ||
onChange: PropTypes.func, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the description meant to have function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure its worth calling this out but we can. Technically other events are needed like keydown, focus, etc. But they are all available to be set via custom props
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, I think we should keep just onChange as first class, as that's the most critical one for dealing with controlled inputs. There are several others we could add, but that could make this list very large.
packages/terra-form/docs/Input.md
Outdated
import { Input } from 'terra-form'; | ||
|
||
<Input | ||
required={false} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Our Booleans are getting a little awkward. This is kind of up to preference, this value defaults to false, so passing in an explicit false does the same thing. There are also examples in these docs that use required={true}
when just passing required in should do the same thing. Do we have a preference or standard on how we recommend using booleans? The two generic paths being:
<Input required />
or
<Input required={true} />
The current prop required
also breaks our is
prefix, but it matches the html API, so I don't know which one is more user friendly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our linter prefers us to use the top approach you have when the boolean value is known to be true. Looks like I forgot to update the documentation to reflect the change. I'll get the MD fixes.
As for the is prefix, I feel like the solution is situational. required is a standard html attribute, so for a variable like required, I think keeping it as it would be the ideal approach. For something like isInline, inline isn't a mapped html attribute, so I feel that the prefix would be needed there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In our early meetings I thought we had discussed not using html attributes as prop names to avoid conflicts, but I could be remembering that conversation incorrectly, it was a while back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did see these standards where they wanted to mirror the DOM whenever it was possible. https://github.cerner.com/terra/conventions/blob/master/react.md#mirror-dom-wherever-possible
I'll look through war room agendas to see if we had updates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was most likely when there were conflicting props, like using title as a prop to display text, when title would otherwise be spread onto the dom element and perform a different role. When the roles are the same it probably makes more sense to mirror.
@@ -0,0 +1,76 @@ | |||
import React, { PropTypes } from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the file that was causing all the case sensitive issues? Should this be TextArea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I debated that myself. I mainly stick to Textarea to keep the same naming convention of the html node textarea. I'm not picky on this though, and if you'd like it changed, I have no problem doing so.
<ChoiceField | ||
label="What State do you live in?" | ||
name="children_present" | ||
value="children_present" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the values used in the name
and value
props need updated, they don't seem to make sense in the ChoiceField example.
packages/terra-form/docs/README.md
Outdated
|
||
To use these components, create a React component that contains a form element, and then insert the Terra form components into that form. | ||
|
||
The recommended approach for building forms is to stick with the field components that are build for you (ChoiceField, MultiChoiceField, NumberField, Textarea, TextareaField, Field). If you need to create a custom field, the Field, Control, Input, and Textarea components are available for use. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: build
=> built
|
||
The recommended approach for building forms is to stick with the field components that are build for you (ChoiceField, MultiChoiceField, NumberField, Textarea, TextareaField, Field). If you need to create a custom field, the Field, Control, Input, and Textarea components are available for use. | ||
|
||
When using input fields, React has two ways of using inputs: controlled or uncontrolled. Controlled maps the value of the input to the state of the component, while uncontrolled does not (https://facebook.github.io/react/docs/uncontrolled-components.html). If you would like to use a controlled input (ideal for forms that need to do validations with JavaScript and send ajax requests), provide a value and an onChange function to the component. If you would like to use an uncontrolled input (ideal for forms that do straight backend requests), provide just a defaultValue into the input **Note: If you provide both a value and defaultValue to the input, React will be confused as to whether you are working with an uncontrolled input or a controlled one. Provide either a value or a defaultValue to the input, but not both.** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's link the first reference of controlled in this paragraph to https://facebook.github.io/react/docs/forms.html#controlled-components and link the first reference on uncontrolled to https://facebook.github.io/react/docs/uncontrolled-components.html
nit: drop the word just in this phrase: provide just a defaultValue into
=> provide a defaultValue into
packages/terra-form/src/Form.scss
Outdated
border-radius: 0.25em; | ||
font-size: 16px; | ||
line-height: 1.428em; | ||
padding: 0.178em; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can these reference variables ?
const defaultProps = { | ||
choices: [], | ||
choiceName: 'name', | ||
choiceValue: 'value', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about nameKey
and valueKey
?
* Initial Value of the input | ||
*/ | ||
value: PropTypes.string, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To that comment, wondering if control would be simplified if it simply had an input property and was explicitly passed the input (rather than attempting to wrap it)
/** | ||
* Functional to be called when the input is changed. | ||
*/ | ||
onChange: PropTypes.func, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure its worth calling this out but we can. Technically other events are needed like keydown, focus, etc. But they are all available to be set via custom props
[![NPM version](http://img.shields.io/npm/v/terra-form.svg)](https://www.npmjs.org/package/terra-form) | ||
[![Build Status](https://travis-ci.org/cerner/terra-core.svg?branch=master)](https://travis-ci.org/cerner/terra-core) | ||
|
||
Components for building forms |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have a more detailed description of what components are available for building a form? I see the other read me doc goes into more depth into it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, we should provide links to the packages that this module contains as opposed to describing them here. Otherwise, we could risk this page getting rather large when folders like validations are later included.
}, | ||
"scripts": { | ||
"compile": "npm run compile:clean && npm run compile:build", | ||
"compile:clean": "rm -rf lib", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"compile:clean": "$(cd ..; npm bin)/rimraf lib",
@@ -0,0 +1,106 @@ | |||
/* eslint-disable jsx-a11y/label-has-for */ | |||
|
|||
import React, { PropTypes } from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once Matt's PR for React 15.5 compatibility is merged in, PropTypes will need imported from the prop-types package. Should this be done before his is merged in so there are less changes in the future?
const defaultProps = { | ||
defaultValue: undefined, | ||
name: null, | ||
onChange: () => {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are inconsistent between packages on how to handle default onChange/onClick/onKeyDown functions. Button has no default defined, ActionHeader defaults to null, Table & List defaults to undefined, and here it defaults to an empty function. Do we need to use a standard?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's bring that up on the war room as well today
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is onChange defaulted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have the need to support both controlled and uncontrolled inputs, so we can't always expect the developer to provide an onChange function.
One option is to just put it on the inputAttrs attribute for forms, and delegate it that way to the input element.
// eslint-disable react/jsx-boolean-value | ||
|
||
import React, { PropTypes } from 'react'; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing import 'terra-base/lib/baseStyles';
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or did you not include it because its using the Field Component? If that is the case, then you added import 'terra-base/lib/baseStyles'
to the ChoiceFeild component
choices=[{ name: 'C', value: 'C' }, { name: 'java', value: 'Java' }] | ||
isInline={false} | ||
required={false} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to pre select choices with this API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like the original tech design called in for passing those in through a values array, but I don't feel like that's the best API. The place that would belong most likely is on this hash
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@StephenEsser thats what the values is for.
Will there be any css styling on ChoiceField, MultiChoiceField, NumberField,TextField, or TextAreaField? There was nothing specific to these components in Field.scss so just wondering how that worked or if they weren't special. |
@@ -11,6 +11,7 @@ const TestLinks = () => ( | |||
<li><Link to="/tests/button-tests">Button Tests</Link></li> | |||
<li><Link to="/tests/button-group-tests">Button Group Tests</Link></li> | |||
<li><Link to="/tests/date-picker-tests">DatePicker Tests</Link></li> | |||
<li><Link to="/tests/form-tests">DatePicker Tests</Link></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, you forgot to change this to Form Tests!
After looking at the site examples, it appears the consumer needs to declare Would it be reasonable to create a wrapper component called |
Terra form actually will not be providing a base component. Consumers would have to provide the form node theirselves, and then use the components listed here to build that form. This is similar to the approach react-form uses. You can view more details here. https://jira2.cerner.com/browse/TERRAUI-573?focusedCommentId=2634665&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-2634665 |
@emilyrohrbough The styling for components such as TextField and NumberField will come from the base field. They will use the styles that a Field uses for it's components. |
This pull request is too lengthy. I'll split up the forms into multiple pull requests. |
Summary
There are the base components used for building forms with Terra.
Additional Details
This is bare bones forms. Features such as validation will come at a later date.