Skip to content

Repository files navigation

@depack/form

npm version

@depack/form is The Bootstrap Form Component For Entering Data.

@depack/form demo
Click For The Demo

yarn add -E @depack/form

Table Of Contents

API

The package is available by importing its default and named functions:

importForm,{FormGroup,Input,TextArea,Select,}from'@depack/form'

Form

Creates the form that maintains the values of each field that is found inside its children. Any additional properties will be passed down to the form. Each child component will receive values in its context.

_depackForm.FormProps: Options for the Form component.

NameTypeDescription
onChange!FunctionThe callback to call when a change is made to any of the inputs inside of the form.
formRef!FunctionThe function to call with the reference to the form HTML.
onSubmit!FunctionThe function to call on form submit.
importForm,{FormGroup,TextArea,Input,Select,SubmitButton,SubmitForm,}from'@depack/form'classExampleFormextendsSubmitForm{render({ onChange, ...props}){const{ formLoading, error, success }=this.statereturn(<Form{...props}onSubmit={this.submit.bind(this)}onChange={values=>{this.reset()if(onChange)onChange(values)}}><FormGrouplabel="Input"help="Type in something..."><Inputname="input"value="hello-world"/></FormGroup><FormGrouplabel="Select"help="Please select..."><Selectname="select"value="2"options={[{title: 'Free will',value: '1',},{title: 'Unfree will',value: '2',},]}/></FormGroup><FormGrouplabel="TextArea"help="Multiple row input..."><TextAreaname="textarea">
One must still have chaos in oneself to be able to give birth to a dancing star.
</TextArea></FormGroup><SubmitButtonloading={formLoading}type="warning"confirmText="Submit Data"/>{error&&`Error: ${error}`}{success&&`OK`}</Form>)}}exportdefaultExampleForm
<form><divclass="form-group"><labelfor="i70984">Input</label><inputname="input" class="form-control" value="hello-world" type="text"
aria-describedby="hi70984" id="i70984"><smallid="hi70984" class="form-text text-muted">Type in something...</small></div><divclass="form-group"><labelfor="i97426">Select</label><selectname="select" class="custom-select" id="i97426"
aria-describedby="hi97426"><optionvalue></option><optionvalue="1">Free will</option><optionselectedvalue="2" selected>Unfree will</option></select><smallid="hi97426" class="form-text text-muted">Please select...</small></div><divclass="form-group"><labelfor="i20008">TextArea</label><textareaname="textarea" aria-describedby="hi20008" class="form-control"
id="i20008" rows="3">One must still have chaos in oneself to be able to give birth to a dancing star.</textarea><smallid="hi20008" class="form-text text-muted">Multiple row input...</small></div><buttonclass="btn btn-warning" type="submit">Submit Data</button></form>

FormGroup

The form group is used to represent a logical combination of a label, input, help text and validation error message. The FormGroup component generates id and hid values and passes them to children components in the context.

_depackForm.FormGroupProps: Options for the FormGroup component.

NameTypeDescription
labelstringThe label to display for the group.
classNamestringThe additional class name to add to form-group.
labelClassNamestringThe additional class name to add to the label.
colstringIf any of the col properties are passed (e.g., col-12, col-sm-8, etc), they will be set on the label.
rowbooleanWhether the group should be displayed in a row. Children must manually be wrapped in divs with col classes. Adds the col-form-label class to the label and the row class to the group.
form-rowbooleanSame as row, but adds the form-row class to the group.
detailsbooleanWhether to display the group in details block.
helpstringThe help text to show in <small className="form-text text-muted">{help}</small>. To support validation with valid and invalid classes, set help on inputs rather than group.
importForm,{FormGroup,Input}from'@depack/form'constExample=()=>(<Form><FormGrouplabel="What is your name?"help="Your name, your name, what is your name?"><Input/></FormGroup></Form>)
<form><divclass="form-group"><labelfor="i70984">What is your name?</label><inputclass="form-control" type="text" aria-describedby="hi70984" id="i70984"><smallid="hi70984" class="form-text text-muted">
Your name, your name, what is your name?</small></div></form>

Input

The input is a one-line entry field.

_depackForm.InputProps: The rest is all other options to be passed to the input element. When compiling with Depack, the props must be added like <Input {...({ 'onClick': test })}>.

NameTypeDescriptionDefault
requiredbooleanWhether this is a required field.-
namestringThe input name.-
placeholderstringThe input placeholder.-
filebooleanWhether the input is for selecting files.-
valuestringThe initial value.-
classNamestringThe additional class name to add to form-control and form-control-file.-
colstringIf any of the col properties are passed (e.g., col-12, col-sm-8, etc), the Form will create a div wrapper around the input with the column class.-
typestringThe input type.text
helpstringThe help text to show under the input. Supports validation classes.-
invalidbooleanAdds the invalid-feedback class to help text.-
validbooleanAdds the valid-feedback class to help text.-
import{Input}from'@depack/form'constExample=()=>(<Inputname="example"placeholder="enter the value..."value="initial value"type="text"required/>)
<inputrequiredname="example" placeholder="enter the value..."
class="form-control" value="initial value" type="text">

Select

This element present the values to select from.

_depackForm.SelectProps: Options for the Select component.

NameTypeDescription
requiredbooleanWhether this is a required field.
namestringThe select name.
valuestringThe initial value.
colstringIf any of the col properties are passed (e.g., col-12, col-sm-8, etc), the Form will create a div wrapper around the select with the column class.
classNamestringThe additional class name to add to custom-select.
defaultText?stringThe default option's text. Pass null to disable the default option.
options!Array<{ value: *, title: string }>The array with options to render inside of the select element.
import{Select}from'@depack/form'constExample=()=>(<Selectname="example"requiredvalue="1"options={[{value: 1,title: 'hello'},{value: 2,title: 'world'},]}></Select>)
<selectname="example" class="custom-select" required><optionvalue></option><optionselectedvalue="1" selected>hello</option><optionvalue="2">world</option></select>

Textarea

The input field with multiple lines. The child of the component will set the initial value inside of the textarea.

_depackForm.TextAreaProps: Options for the TextAreaProps component.

NameTypeDescriptionDefault
requiredbooleanWhether this is a required field.-
namestringThe textarea name.-
placeholderstringThe textarea placeholder.-
rowsnumberHow many rows should the textarea have.3
import{TextArea}from'@depack/form'constExample=()=>(<TextAreaname="example"rows="4"requiredplaceholder="enter the multiline value...">
Hello World
</TextArea>)
<textarearequiredname="example" placeholder="enter the multiline value..."
class="form-control" rows="4">Hello World</textarea>

SubmitForm

This class extends the Preact.Component and implements the submit method which will send the data to the server and await for the response while setting the formLoading property of the state to true. The error and success properties will also be set upon the arrival of data, with the JSON response being used to extract the error. The submitFinish callback can be used to receive the result of the form submission. Components implementing this abstract class must write their own render method.

_depackForm.SubmitFormProps: Options for the SubmitForm component.

NameTypeDescription
path*stringThe path where to send data.
submitFinish(arg0: Object) => !PromiseThe callback after the data has been sent with possible response from the server.

_depackForm.SubmitFormState: The state structure for the SubmitForm.

NameTypeDescription
formLoading*booleanWhether the data has been sent for submission.
error*?stringThe error returned by the server.
success*?booleanWhether the form has been submitted successfully.
importForm,{SubmitForm,Input}from'@depack/form'classDataFormextendsSubmitForm{render(){const{ error, success, formLoading }=this.statereturn(<FormonSubmit={this.submit.bind(this)}><Inputname="example"/>{error&&`Error: ${error}`}{success&&'Success!'}<buttontype="submit"disabled={formLoading}>Submit</button></Form>)}}constExample=()=>(<DataFormpath="/send-data"submitFinish={()=>{console.log('hooray!')}}/>)
<form><inputname="example" class="form-control" type="text"><buttontype="submit">Submit</button></form>

reset(): void

Resets the error and success properties of the form.

SubmitButton

The button that can be placed inside the form and used for submission since it has type="submit" property. It also has the loading property to disable the button and show the spinning wheel indicator.

_depackForm.SubmitButtonProps: Options for the SubmitButton component.

NameTypeDescriptionDefault
loadingbooleanWhether the button should display as loading.false
loadingTextstringThe text to show during the loading progress.-
confirmText*stringThe text for the normal state.-
classNamestringThe class name, such as btn-lg.-
typestringThe type of the button to add to the class as btn-{type}. One of ('primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark').primary
outlinebooleanDisplay the outline style of the button via setting the btn-outline-{type} class.false
disabledbooleanWhether the button is disabled. It becomes disabled when the form is loading by default.false
import{SubmitButton}from'@depack/form'constExample=({ formLoading })=>(<SubmitButtontype="light"confirmText="Add Data"loading={formLoading}loadingText="Loading..."outline="1"/>)
<buttonclass="btn btn-outline-light" type="submit">Add Data</button>

Custom Components

To implement a custom component, one must write a class component that would report its initial value in componentDidMount method via the onChange method that it receives in the context. Overall, there are 4 properties that a component can receive in the context:

  • id: If placed in the FormGroup, this will be set to the ID that the component should set on the input so that the label can focus on it on click.
  • hid: If placed in the FormGroup, this will be set to auto-generated value for the help field.
  • values: This is the overall values hash containing all the values of the fields in the form. It is set by the Form parent component.
  • onChange: This is the callback set by the Form to report changes to the values of the component. It must also be fired after the component is mounted to set its initial model value in the form (i.e. update the values field).

The components are controlled which means their values are set via the model, and are contained in the values context property. Whenever an update is needed, the onChange method has to be fired. To allow server-side rendering of the component when the initial value is not going to be reported to the Form via the componentDidMount, it must be set manually after checking if values contain the name of the component. If the component for some reason is going to be used also outside of the form, the values must be defaulted to {}.

Here is an example of the Input component which accounts for all the above points:

import{Component}from'preact'import{shouldComponentUpdate,getClasses}from'./lib'importHelpfrom'./help'exportdefaultclassInputextendsComponent{constructor(){super()/** @type {!_depackForm.InputProps} */this.props=this.props}shouldComponentUpdate(newProps,__,newContext){constres=shouldComponentUpdate.call(this,newProps,newContext)returnres}componentDidMount(){const{ value, name }=this.propsconst{ onChange }=this.contextif(value!==undefined&&onChange)onChange(name,value)}/** * Triggers the onchange event on the form. * @param {string} value */onChange(value){this.context.onChange(this.props.name,value)}/** * @param {!_depackForm.InputProps} [props] */render({
required, name, placeholder, type ='text', file, value, className,
invalid, valid, help, ...props}){const{ colClasses, prop }=getClasses(props)constc=[`form-control${file ? '-file' : ''}`,className,invalid ? 'is-invalid' : null,valid ? 'is-valid' : null,].filter(Boolean).join(' ')const{ hid, id, values ={}}=this.contextconstrendered=nameinvalues// for SSRconstinput=(<inputrequired={required}name={name}placeholder={placeholder}className={c}value={rendered ? values[name] : value}type={type}aria-describedby={hid}id={id}onChange={(e)=>{this.onChange(e.currentTarget.value)}}{...prop}/>)if(colClasses.length){consthe=help ? (<Helphelp={help}hid={hid}valid={valid}invalid={invalid}/>) : nullreturn(<divclassName={colClasses.join(' ')}>{input}{he}</div>)}returninput}}/** * @suppress {nonStandardJsDocs} * @typedef {import('../types').InputProps} _depackForm.InputProps */

Copyright

Art Deco© Art Deco for Depack 2020Tech Nation VisaTech Nation Visa Sucks

About

The Bootstrap Form Component For Entering Data.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages