A few changes to API for better Wrapped component support (#472)
* Add propTypes to API docs; move innerRef doc to match location in table of contents * Change HOC to Wrapper (be consistent everywhere) * Inject defaultProps.value from wrapped component into Formsy.Wrapper This way users can provide a default value for their form field. Previously, this was possible because mixins were on the same level as the actual component. * Add optional parameter to setState to disable validation * Update prepublish script to clean `lib`; rebuild release folder
This commit is contained in:
parent
998e2be44f
commit
b413f9db77
47
API.md
47
API.md
|
|
@ -37,6 +37,7 @@
|
|||
- [isFormSubmitted()](#isformsubmitted)
|
||||
- [validate](#validate)
|
||||
- [formNoValidate](#formnovalidate)
|
||||
- [Formsy.propTypes](#formsyproptypes)
|
||||
- [Formsy.addValidationRule](#formsyaddvalidationrule)
|
||||
- [Validators](#validators)
|
||||
|
||||
|
|
@ -238,6 +239,26 @@ export default Wrapper(MyInput);
|
|||
```
|
||||
The name is required to register the form input component in the form. You can also use dot notation. This will result in the "form model" being a nested object. `{email: 'value', address: {street: 'value'}}`.
|
||||
|
||||
|
||||
#### <a name="innerRef">innerRef</a>
|
||||
|
||||
Use an `innerRef` prop to get a reference to your DOM node.
|
||||
|
||||
```jsx
|
||||
class MyForm extends React.Component {
|
||||
componentDidMount() {
|
||||
this.searchInput.focus()
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<MyInput name="search" innerRef={(c) => { this.searchInput = c; }} />
|
||||
</Formsy.Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### <a name="value">value</a>
|
||||
```jsx
|
||||
<MyInputComponent name="email" value="My initial value"/>
|
||||
|
|
@ -314,7 +335,7 @@ class MyInput extends React.Component {
|
|||
```
|
||||
Gets the current value of the form input component.
|
||||
|
||||
#### <a name="setvalue">setValue(value)</a>
|
||||
#### <a name="setvalue">setValue(value[, validate = true])</a>
|
||||
```jsx
|
||||
class MyInput extends React.Component {
|
||||
changeValue = (event) => {
|
||||
|
|
@ -329,6 +350,8 @@ class MyInput extends React.Component {
|
|||
```
|
||||
Sets the value of your form input component. Notice that it does not have to be a text input. Anything can set a value on the component. Think calendars, checkboxes, autocomplete stuff etc. Running this method will trigger a **setState()** on the component and do a render.
|
||||
|
||||
You can also set the value without forcing an immediate validation by passing a second parameter of `false`. This is useful in cases where you want to only validate on blur / change / etc.
|
||||
|
||||
#### <a name="resetvalue">resetValue()</a>
|
||||
```jsx
|
||||
class MyInput extends React.Component {
|
||||
|
|
@ -559,22 +582,16 @@ class MyInput extends React.Component {
|
|||
}
|
||||
```
|
||||
|
||||
#### <a name="innerRef">innerRef</a>
|
||||
|
||||
Use an `innerRef` prop to get a reference to your DOM node.
|
||||
|
||||
### <a name="formsyproptypes">Formsy.propTypes</a>
|
||||
If you are using React's PropType typechecking, you can spread Formsy's propTypes into your local propTypes to avoid having to repeatedly add `Formsy.Wrapper`'s methods to your components.
|
||||
```jsx
|
||||
class MyForm extends React.Component {
|
||||
componentDidMount() {
|
||||
this.searchInput.focus()
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Formsy.Form>
|
||||
<MyInput name="search" innerRef={(c) => { this.searchInput = c; }} />
|
||||
</Formsy.Form>
|
||||
);
|
||||
class MyInput extends React.Component {
|
||||
static propTypes = {
|
||||
firstProp: PropTypes.string,
|
||||
secondProp: PropTypes.object,
|
||||
...Formsy.propTypes
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
"build": "NODE_ENV=production webpack -p --config webpack.production.config.js",
|
||||
"test": "babel-node testrunner",
|
||||
"examples": "webpack-dev-server --config examples/webpack.config.js --content-base examples",
|
||||
"prepublish": "babel ./src/ -d ./lib/"
|
||||
"prepublish": "rm -Rf ./lib && babel ./src/ -d ./lib/"
|
||||
},
|
||||
"author": "Christian Alfoni",
|
||||
"license": "MIT",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -35,11 +35,11 @@ module.exports = function (Component) {
|
|||
static displayName = 'Formsy(' + getDisplayName(Component) + ')';
|
||||
|
||||
state = {
|
||||
_value: this.props.value,
|
||||
_value: typeof this.props.value !== 'undefined' ? this.props.value : Component.defaultProps ? Component.defaultProps.value : undefined,
|
||||
_isRequired: false,
|
||||
_isValid: true,
|
||||
_isPristine: true,
|
||||
_pristineValue: this.props.value,
|
||||
_pristineValue: typeof this.props.value !== 'undefined' ? this.props.value : Component.defaultProps ? Component.defaultProps.value : undefined,
|
||||
_validationError: [],
|
||||
_externalError: null,
|
||||
_formSubmitted: false
|
||||
|
|
@ -100,15 +100,22 @@ module.exports = function (Component) {
|
|||
this._requiredValidations = required === true ? {isDefaultRequiredValue: true} : convertValidationsToObject(required);
|
||||
}
|
||||
|
||||
// We validate after the value has been set
|
||||
setValue = (value) => {
|
||||
this.setState({
|
||||
_value: value,
|
||||
_isPristine: false
|
||||
}, () => {
|
||||
this.context.formsy.validate(this);
|
||||
//this.props._validate(this);
|
||||
});
|
||||
// By default, we validate after the value has been set.
|
||||
// A user can override this and pass a second parameter of `false` to skip validation.
|
||||
setValue = (value, validate = true) => {
|
||||
if (!validate) {
|
||||
this.setState({
|
||||
_value: value
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
_value: value,
|
||||
_isPristine: false
|
||||
}, () => {
|
||||
this.context.formsy.validate(this);
|
||||
//this.props._validate(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
resetValue = () => {
|
||||
|
|
@ -4,11 +4,11 @@ var Formsy = {};
|
|||
var validationRules = require('./validationRules.js');
|
||||
var formDataToObject = require('form-data-to-object');
|
||||
var utils = require('./utils.js');
|
||||
var HOC = require('./HOC.js');
|
||||
var Wrapper = require('./Wrapper.js');
|
||||
var options = {};
|
||||
var emptyArray = [];
|
||||
|
||||
Formsy.Wrapper = HOC;
|
||||
Formsy.Wrapper = Wrapper;
|
||||
Formsy.propTypes = {
|
||||
setValidations: PropTypes.func,
|
||||
setValue: PropTypes.func,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,33 @@ export default {
|
|||
|
||||
},
|
||||
|
||||
'should only set the value and not validate when calling setValue(val, false)': function (test) {
|
||||
|
||||
const Input = Formsy.Wrapper(class TestInput extends React.Component {
|
||||
updateValue = (event) => {
|
||||
this.props.setValue(event.target.value, false);
|
||||
}
|
||||
render() {
|
||||
return <input type="text" value={this.props.getValue()} onChange={this.updateValue}/>;
|
||||
}
|
||||
})
|
||||
const form = TestUtils.renderIntoDocument(
|
||||
<Formsy.Form>
|
||||
<Input name="foo" value="foo" innerRef="comp" />
|
||||
</Formsy.Form>
|
||||
);
|
||||
const inputComponent = TestUtils.findRenderedComponentWithType(form, Input);
|
||||
const setStateSpy = sinon.spy(inputComponent, 'setState');
|
||||
const inputElement = TestUtils.findRenderedDOMComponentWithTag(form, 'INPUT');
|
||||
|
||||
test.equal(setStateSpy.called, false);
|
||||
TestUtils.Simulate.change(inputElement, {target: {value: 'foobar'}});
|
||||
test.equal(setStateSpy.calledOnce, true);
|
||||
test.equal(setStateSpy.calledWithExactly({ _value: 'foobar' }), true);
|
||||
test.done();
|
||||
|
||||
},
|
||||
|
||||
'should set back to pristine value when running reset': function (test) {
|
||||
|
||||
let reset = null;
|
||||
|
|
@ -317,7 +344,6 @@ export default {
|
|||
|
||||
},
|
||||
|
||||
|
||||
'should override all error messages with error messages passed by form': function (test) {
|
||||
|
||||
class TestForm extends React.Component {
|
||||
|
|
|
|||
Loading…
Reference in New Issue