key features
- write JSX in the react containment style
- automatic dependency injection on values and event handlers
- instictive validation interfaces
npm
npm install --save-dev osci-react-form
a basic example
import React Component from "react";import Form enhance Input from "osci-react-form"; { ; thisstate = values: config: asyncValidateOnBlur: true asyncValidateOnInit: true touchNonEmptyOnInit: true fieldsToNormalize: normailzeTest: /^$/ ; } { return <Form = => <Input ="username" /> <Input ="password" ="password" /> <button ="submit">Sign in</button> <button ="reset">reset</button> </Form> ; }
scope attribute
-
The attribute
scope
is the client that has the state of Form. -
If it is not defined, it will be the instance of Form itself.
state control methods
-
You can execute
enhance(scope)
to enable the state control methods. -
This method should be executed before any execution of the methods.
-
scope can be either an instance or a class. (not plain functions. React plain functions cannot have
this
.) -
It is trivial that the scope attribute and the scope argument should be the same.
fields definition
- Form regards components with names as fields.
method caveats
If a method modifies this.state
or reads it not in the 'render' method frame, put the previous state as its argument,
this;
else just use the mothod directly.
this;
If you implemented React.Component abstract methods like getSnapShotBeforeUpdate
, you have to set the state in the immutable way. (frankly speaking...i have not tested this case yet)
this;
define validators
- the custom validator interface
validator : String || { name : String, regex : RegExp || api : function, async : boolean [Optional], message : String [Optional] }
- client definition
<input = ... />
- built-in definition
<input ="confirm" ="password" ... />
-
the list of the built-in validators
- type="email"
- required
- match="anyNameOfField"
- notMatch="anyNameOfField"
- pattern={/.*/}
- assertTrue={anyCustomValidator}
- assertFalse={anyCustomValidator}
-
ordering built-in validators with strings
<Input = = ="password" ... />
- validation scoping
You can avoid each component having the same validator objects and their value caches for the same validation functionality.
<ul> arr</ul><Input = ="serialNumber" />
-
validator caveats
- Once validators are registered, you cannot change them.
api
mothods should return a promise that returns a boolean.- The
required
built-in validator always goes first.
this.state
methods that reads -
'getValue(name : String, prev : Object [Optional]) : String'
-
'isTouched(name : String, prev : Object [Optional]) : Boolean'
-
'syncValidate(name : String, prev : Object [Optional], value : Object [Optional]) : String || null'
-
'syncValidateFull(name : String, prev : Object [Optional], value : Object [Optional]) : Array'
-
'isSyncValid(name : String, prev : Object [Optional]) : Boolean'
-
'getSyncValidator(name : String, prev : Object [Optional]) : Array'
- no Validator class yet
-
'getAsyncStatus(name : String, prev : Object [Optional]) : Object { [asyncName1] : 'processing' || 'resolved' || 'rejected', [asyncName2] : ... } || null'
-
'getFieldNames(prev : Object [Optional]) : Array'
-
'isAsyncValidating(name : String [Optional], prev : Object [Optional]) : Boolean'
-
'isAsyncRejected(name : String [Optional], prev : Object [Optional]) : Boolean'
-
'getAsyncErrors(name : String, prev : Object [Optional]) : Object { [asyncName1] : 'message or name', [asyncName2] : ... } || null'
-
'getAsyncIdleFields(name : String, prev : Object [Optional]) : Array'
-
'getProcessingPromises(prev : Object [Optional]) : Array'
this.state
methods that modifies -
'setValue(name : String, value : any, prev : Object) : Boolean'
-
'deleteValue(name : String, prev : Object) : true'
-
'touch(name : String, prev : Object) : Boolean'
-
'touchAll(name : String, prev : Object) : Boolean'
-
'untouch(name : String, prev : Object) : true'
-
'asyncValidate(name : String, prev : Object, value : Object [Optional]) : Promise<{asyncName : String, message : String, value : Object, result : Boolean}>'
-
'normalize(prev : Object, names : Array [Optional]) : undefined'
-
cleans up empty strings for the names in the second argument or field names defined in the configuration of 'fieldsToNormalize'
-
this method is for dynamic fields that are not assigned any values to.
-
plain methods
-
'getCopy(original : Object) : Object'
- deeply copy all properties
submit interface
<Form = = =/>
- Form attributes could have
onSubmit
,onSuccess
andonFailure
. onSubmit
is supposed to return a promise. If you cannot do so in certain cases like bcrypt, you have to implementthis.setState({submitting : false})
manually.- The inner source code of submit handling is below
{ const scope = this; const body = scope; const submitAction = thisprops; if submitAction instanceof Promise submitAction ; }
control the unmounted component
- You can put the code below to avoid the unmounted component error with setState.
if scopeisUnmounted // scope.setState({ any });
the sample page
http://osci-react-form.surge.sh/
test the sample code
git clone git@github.com:OpenSourceConsulting/osci-react-form.git
cd osci-react-form
npm install
npm start
update logs
- 2018/5/15 update logs have been refreshed.
issues
-
eager
- test React.Component abstract methods with the state control methods
- asyncValidateOnChange, asyncValidateOnChangeForNonText, asyncValidateOnBlurForNonText, suppressAutoDenpency
-
lazy
- uncontrolled component 디자인 구상, ref? no? ex) type="file"
- html5 의 모든 스펙을 구현해야한다. (range, textarea, contenteditable, submit action async ...)
- old browser, study of xss cases
- old browser, onSubmit setState promise event loop hole 학습 및 테스트, 최신브라우져는 테스트 완료
- customizing 혹은 logging 을 위해 다양한 hook 을 제공해야한다. promise 의 대부분 stack 에서 logging 할 수 있도록 할 것이다.
-
extra
- componentDidCatch 사용성 테스트, 좋은 인터페이스인가
- dev logging, dev minifying 구현
- chrome dev tool perfomance test
LICENSE
-
The MIT License (MIT)
-
Copyright (c) 2018 OSCI