Prepared new release

This commit is contained in:
christianalfoni 2015-05-22 14:46:45 +02:00
parent dbb0653a2b
commit a1cf2236df
7 changed files with 175 additions and 25 deletions

31
API.md
View File

@ -12,6 +12,7 @@
- [onInvalidSubmit()](#oninvalidsubmit)
- [onChange()](#onchange)
- [reset()](#resetform)
- [preventExternalInvalidation](#preventexternalinvalidation)
- [Formsy.Mixin](#formsymixin)
- [name](#name)
- [value](#value)
@ -136,13 +137,13 @@ Triggers when form is submitted with a valid state. The arguments are the same a
```
Triggers when form is submitted with an invalid state. The arguments are the same as on `onSubmit`.
#### <a name="onchange">onChange(currentValues)</a>
#### <a name="onchange">onChange(currentValues, isChanged)</a>
```html
<Formsy.Form onChange={this.saveCurrentValuesToLocalStorage}></Formsy.Form>
```
"onChange" triggers when setValue is called on your form elements. It is also triggered when dynamic form elements have been added to the form. The "currentValues" is an object where the key is the name of the input and the value is the current value.
"onChange" triggers when setValue is called on your form elements. It is also triggered when dynamic form elements have been added to the form. The "currentValues" is an object where the key is the name of the input and the value is the current value. The second argument states if the forms initial values actually has changed.
#### <a name="resetform">reset()</a>
#### <a name="resetform">reset(values)</a>
```html
var MyForm = React.createClass({
resetForm: function () {
@ -157,15 +158,35 @@ var MyForm = React.createClass({
}
});
```
Manually reset the form to its pristine state.
Manually reset the form to its pristine state. You can also pass an object that inserts new values into the inputs. Keys are name of input and value is of course the value.
#### <a name="preventExternalInvalidation">preventExternalInvalidation</a>
```html
var MyForm = React.createClass({
onSubmit: function (model, reset, invalidate) {
invalidate({
foo: 'Got some error'
});
},
render: function () {
return (
<Formsy.Form onSubmit={this.onSubmit} preventExternalInvalidation>
...
</Formsy.Form>
);
}
});
```
With the `preventExternalInvalidation` the input will not be invalidated though it has an error.
### <a name="formsymixin">Formsy.Mixin</a>
#### <a name="name">name</a>
```html
<MyInputComponent name="email"/>
<MyInputComponent name="address.street"/>
```
The name is required to register the form input component in the form.
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="value">value</a>
```html

View File

@ -6,28 +6,29 @@ var Input = React.createClass({
mixins: [Formsy.Mixin],
render: function () {
return <input disabled={this.isFormDisabled()} />
return (
<div>
{this.showError()}
{this.getErrorMessage()}
<input disabled={this.isFormDisabled()} />
</div>
);
}
});
var FormApp = React.createClass({
getInitialState: function () {
return {
bool: true
};
},
flip: function () {
this.setState({
bool: !this.state.bool
componentDidMount: function () {
this.refs.form.updateInputsWithError({
'foo.bar': 'hmmm'
});
},
onSubmit: function (model) {
console.log('model', model);
},
render: function () {
return (
<Formsy.Form disabled={this.state.bool}>
{this.state.bool ?
<Input name="foo" /> :
<Input name="bar" />
}
<Formsy.Form ref="form" onInvalid={this.onInvalid}>
<Input name="foo.bar" />
</Formsy.Form>
);
}

View File

@ -558,4 +558,33 @@ it('should allow an undefined value to be updated to a value', function (done) {
});
it('should allow for dot notation in name which maps to a deep object', function () {
var TestInput = React.createClass({
mixins: [Formsy.Mixin],
render: function () {
return <input/>
}
});
var TestForm = React.createClass({
onSubmit: function (model) {
expect(model).toEqual({foo: {bar: 'foo', test: 'test'}});
},
render: function () {
return (
<Formsy.Form>
<TestInput name="foo.bar" value="foo"/>
<TestInput name="foo.test" value="test"/>
</Formsy.Form>
);
}
});
var form = TestUtils.renderIntoDocument(<TestForm/>);
var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
TestUtils.Simulate.submit(formEl);
});
});

View File

@ -612,6 +612,20 @@ describe('Formsy', function () {
formsyForm.reset();
expect(input.getValue()).toBe(true);
});
it("should be able to reset the form using custom data", function() {
var form = TestUtils.renderIntoDocument(<TestForm value={ true }/>);
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
var formsyForm = TestUtils.findRenderedComponentWithType(form, Formsy.Form);
expect(input.getValue()).toBe(true);
form.setProps({value: false});
expect(input.getValue()).toBe(false);
formsyForm.reset({
foo: 'bar'
});
expect(input.getValue()).toBe('bar');
});
});
describe('.isChanged()', function() {

View File

@ -217,4 +217,65 @@ describe('Validation', function() {
});
it('should not invalidate inputs on external errors with preventExternalInvalidation prop', function () {
var TestInput = React.createClass({
mixins: [Formsy.Mixin],
render: function () {
return <input value={this.getValue()}/>
}
});
var TestForm = React.createClass({
invalidate: function (model, reset, invalidate) {
invalidate({
foo: 'bar'
});
},
render: function () {
return (
<Formsy.Form onSubmit={this.invalidate} preventExternalInvalidation>
<TestInput name="foo" value="foo"/>
</Formsy.Form>
);
}
});
var form = TestUtils.renderIntoDocument(<TestForm/>);
var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
TestUtils.Simulate.submit(formEl);
expect(input.isValid()).toBe(true);
});
it('should invalidate inputs on external errors without preventExternalInvalidation prop', function () {
var TestInput = React.createClass({
mixins: [Formsy.Mixin],
render: function () {
return <input value={this.getValue()}/>
}
});
var TestForm = React.createClass({
invalidate: function (model, reset, invalidate) {
invalidate({
foo: 'bar'
});
},
render: function () {
return (
<Formsy.Form onSubmit={this.invalidate}>
<TestInput name="foo" value="foo"/>
</Formsy.Form>
);
}
});
var form = TestUtils.renderIntoDocument(<TestForm/>);
var formEl = TestUtils.findRenderedDOMComponentWithTag(form, 'form');
var input = TestUtils.findRenderedComponentWithType(form, TestInput);
TestUtils.Simulate.submit(formEl);
expect(input.isValid()).toBe(false);
});
});

View File

@ -34,7 +34,8 @@ Formsy.Form = React.createClass({
onValid: function () {},
onInvalid: function () {},
onChange: function () {},
validationErrors: null
validationErrors: null,
preventExternalInvalidation: false
};
},
@ -93,7 +94,21 @@ Formsy.Form = React.createClass({
},
mapModel: function () {
return this.props.mapping ? this.props.mapping(this.model) : this.model;
if (this.props.mapping) {
return this.props.mapping(this.model)
} else {
return Object.keys(this.model).reduce(function (mappedModel, key) {
var keyArray = key.split('.');
while (keyArray.length) {
var currentKey = keyArray.shift();
mappedModel[currentKey] = keyArray.length ? mappedModel[currentKey] || {} : this.model[key];
}
return mappedModel;
}.bind(this), {});
}
},
// Goes through all registered components and
@ -152,9 +167,8 @@ Formsy.Form = React.createClass({
if (!component) {
throw new Error('You are trying to update an input that does not exist. Verify errors object with input names. ' + JSON.stringify(errors));
}
var args = [{
_isValid: false,
_isValid: this.props.preventExternalInvalidation || false,
_externalError: errors[name]
}];
component.setState.apply(component, args);
@ -421,10 +435,10 @@ Formsy.Form = React.createClass({
},
render: function () {
return React.DOM.form({
return React.DOM.form(utils.extend({}, this.props, {
onSubmit: this.submit,
className: this.props.className
},
}),
this.traverseChildrenAndRegisterInputs(this.props.children)
);

View File

@ -37,5 +37,15 @@ module.exports = {
}
return a === b;
},
extend: function () {
var objects = [].slice.call(arguments);
var initialObject = objects.shift();
return objects.reduce(function (returnedObject, object) {
return Object.keys(object).reduce(function (returnedObject, key) {
returnedObject[key] = object[key];
return returnedObject;
}, returnedObject);
}, initialObject);
}
};