diff --git a/build/index.html b/build/index.html index 24eb24c..0a5bfbb 100644 --- a/build/index.html +++ b/build/index.html @@ -3,6 +3,7 @@ Formsy Test +
\ No newline at end of file diff --git a/build/test.js b/build/test.js index f8aee32..d38c77d 100644 --- a/build/test.js +++ b/build/test.js @@ -1,4 +1,36 @@ var React = require('react'); var Formsy = require('./../src/main.js'); -// Write your test code here \ No newline at end of file +var Input = React.createClass({ + + mixins: [Formsy.Mixin], + + render: function () { + return + } +}); + +var FormApp = React.createClass({ + getInitialState: function () { + return { + bool: true + }; + }, + flip: function () { + this.setState({ + bool: !this.state.bool + }); + }, + render: function () { + return ( + + {this.state.bool ? + : + + } + + ); + } +}); + +React.render(, document.getElementById('app')); \ No newline at end of file diff --git a/specs/Formsy-spec.jsx b/specs/Formsy-spec.jsx index b483a7f..5fae13c 100755 --- a/specs/Formsy-spec.jsx +++ b/specs/Formsy-spec.jsx @@ -613,4 +613,66 @@ describe('Formsy', function () { expect(input.getValue()).toBe(true); }); }); + + describe('.isChanged()', function() { + var onChange; + var TestInput = React.createClass({ + mixins: [Formsy.Mixin], + changeValue: function (event) { + this.setValue(event.target.value); + }, + render: function () { + return + } + }); + + var TestForm = React.createClass({ + getDefaultProps: function() { + return { + inputs: [], + }; + }, + render: function () { + var builtInputs = []; + var inputs = this.props.inputs; + for (var i=0; i < inputs.length; i++) { + var input = inputs[i]; + builtInputs.push(); + } + return + { builtInputs } + { this.props.children } + ; + } + }); + + beforeEach(function() { + onChange = jasmine.createSpy("onChange"); + }); + + it('initially returns false', function() { + var form = TestUtils.renderIntoDocument(); + expect(form.refs.formsy.isChanged()).toEqual(false); + expect(onChange).not.toHaveBeenCalled(); + }); + + it('returns true when changed', function() { + var form = TestUtils.renderIntoDocument(); + var input = TestUtils.findRenderedDOMComponentWithTag(form, 'input'); + TestUtils.Simulate.change(input.getDOMNode(), {target: {value: 'bar'}}); + expect(form.refs.formsy.isChanged()).toEqual(true); + expect(onChange).toHaveBeenCalledWith({one: 'bar'}, true); + }); + + it('returns false if changes are undone', function() { + var form = TestUtils.renderIntoDocument(); + var input = TestUtils.findRenderedDOMComponentWithTag(form, 'input'); + TestUtils.Simulate.change(input.getDOMNode(), {target: {value: 'bar'}}); + expect(onChange).toHaveBeenCalledWith({one: 'bar'}, true); + TestUtils.Simulate.change(input.getDOMNode(), {target: {value: 'foo'}}); + expect(form.refs.formsy.isChanged()).toEqual(false); + expect(onChange).toHaveBeenCalledWith({one: 'foo'}, false); + }); + }); + }); diff --git a/src/main.js b/src/main.js index 3c46d1c..72a9a1a 100644 --- a/src/main.js +++ b/src/main.js @@ -123,6 +123,20 @@ Formsy.Form = React.createClass({ }.bind(this)); }, + // Checks if the values have changed from their initial value + isChanged: function() { + return !utils.isSame(this.getPristineValues(), this.getCurrentValues()); + }, + + getPristineValues: function() { + var inputs = this.inputs; + return Object.keys(inputs).reduce(function (data, name) { + var component = inputs[name]; + data[name] = component.props.value; + return data; + }, {}); + }, + // Go through errors from server and grab the components // stored in the inputs map. Change their state to invalid // and set the serverError message @@ -213,7 +227,7 @@ Formsy.Form = React.createClass({ // Trigger onChange if (this.state.canChange) { - this.props.onChange(this.getCurrentValues()); + this.props.onChange(this.getCurrentValues(), this.isChanged()); } var validation = this.runValidation(component);