├── .gitignore ├── README.md ├── demo ├── app.coffee └── server.coffee ├── generated └── keepme ├── index.js ├── karma.conf.js ├── lib └── FormDataMixin.coffee ├── package.json └── test ├── FormDataMixinTest.cjsx └── TestForm.cjsx /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | generated 4 | !generated/keepme 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-form-data 2 | React form data is a React mixin that will allow you to get data from an html form in a nice javascript object format. 3 | ## installation 4 | ```bash 5 | npm i react-form-data -S 6 | ``` 7 | or if you prefer the verbose format: 8 | ```bash 9 | npm install react-form-data --save 10 | ``` 11 | 12 | ## usage 13 | 1. Create a component containing form elements. 14 | 2. Add the form data mixin to the component 15 | 3. On an element wrapping all input elements, bind the ```onChange``` handler to ```this.updateFormData``` 16 | 4. You will now have access to the form data by accessing ```this.formData``` 17 | 18 | ### example 19 | ``` 20 | var React = require('react'); 21 | var FormData = require('react-form-data'); 22 | var MyForm = React.createClass({ 23 | mixins: [ FormData ], 24 | handleSubmit: function() { 25 | var url = 'urlToSendDataTo'; 26 | myRequestLib.post(url, this.formData); 27 | }, 28 | render: function() { 29 | return ( 30 |
33 | ) 34 | } 35 | }); 36 | ``` 37 | ## input elements 38 | react-form-data supports ```input```, ```textarea``` and ```select``` elements. The name of an element is used as key in the created object and the value is fetched form the entered text, the selected ```option``` element or the defined ```value``` on the checked radio button. 39 | 40 | ### checkboxes 41 | Checkboxes can be used in two different ways. 42 | 1. A single checkbox can map ```true``` or ```false``` to its key. 43 | 2. Several checkboxes can be used to map an array of values to the same key. 44 | 45 | To use case 1, don't give the checkbox a value: 46 | ``` 47 | 48 | ``` 49 | ```this.formData.acceptTerms``` will be true or false depending on if the checkbox is checked or not. 50 | 51 | To use case 2, create several checkboxes with the same name but different values: 52 | ``` 53 | 54 | 55 | 56 | ``` 57 | ```this.formData.skills``` will be an array of the checked values. E.g. ```[ 'javascript', 'coffeescript' ]``` 58 | 59 | ## methods 60 | When adding the mixin to your component, these methods will be available on it: 61 | 62 | ### getInitialFormData() 63 | Implement this method to let ```this.formData``` be a non empty object in its initial state. Useful when you want to edit an existing entity. Any changes to the form will be added to this object. 64 | 65 | ### formDataDidChange() 66 | Called whenever there is a change in the form. The new data is available in `this.formData`. 67 | 68 | ### setFormData(key, value) 69 | Manually update ```this.formData``` with ```key``` and ```value``` 70 | 71 | ### clearFormData() 72 | Sets ```this.formData``` to an empty object. 73 | 74 | ### resetFormData(obj) 75 | Makes a shallow clone of object and replaces ```this.formData``` with the clone. 76 | 77 | ## demo 78 | This repository contains a demo. To run it, clone the repo and execute ```npm run demo```. You can now view the demo by visiting [http://localhost:3000](http://localhost:3000) 79 | -------------------------------------------------------------------------------- /demo/app.coffee: -------------------------------------------------------------------------------- 1 | React = require 'react' 2 | Form = require '../test/TestForm.cjsx' 3 | 4 | window.init = -> React.renderComponent , document.body 5 | 6 | -------------------------------------------------------------------------------- /demo/server.coffee: -------------------------------------------------------------------------------- 1 | http = require 'http' 2 | browserify = require 'browserify' 3 | 4 | html = ''' 5 | 6 | 7 | 8 | 9 | Browserifying. Hold on... 10 | 11 | 12 | 13 | ''' 14 | 15 | http.Server (req, res) -> 16 | if req.url == '/js' 17 | b = browserify() 18 | b.add __dirname + '/app.coffee' 19 | b.transform 'coffee-reactify' 20 | b.bundle (e, out) -> 21 | console.log e if e? 22 | res.setHeader 'Content-Type', 'application/javascript' 23 | res.end out 24 | else 25 | res.end html 26 | .listen 3000, (e) -> 27 | if e? 28 | console.err e 29 | else 30 | console.log 'Demo server running on port 3000' 31 | -------------------------------------------------------------------------------- /generated/keepme: -------------------------------------------------------------------------------- 1 | Im only here to make sure the generated folder is tracked by git. 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./dist/FormDataMixin'); 2 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Fri Sep 12 2014 11:43:12 GMT+0200 (CEST) 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: '', 9 | 10 | 11 | // frameworks to use 12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 13 | frameworks: [ 'mocha' ], 14 | 15 | 16 | // list of files / patterns to load in the browser 17 | files: [ 18 | 'generated/react-browserified.js', 19 | 'generated/testsbundle.js' 20 | ], 21 | 22 | 23 | // list of files to exclude 24 | exclude: [], 25 | 26 | 27 | // preprocess matching files before serving them to the browser 28 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 29 | preprocessors: { 30 | }, 31 | 32 | // test results reporter to use 33 | // possible values: 'dots', 'progress' 34 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 35 | reporters: ['progress'], 36 | 37 | // web server port 38 | port: 9876, 39 | 40 | 41 | // enable / disable colors in the output (reporters and logs) 42 | colors: true, 43 | 44 | 45 | // level of logging 46 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 47 | logLevel: config.LOG_INFO, 48 | 49 | 50 | // enable / disable watching file and executing tests whenever any file changes 51 | autoWatch: true, 52 | 53 | 54 | // start these browsers 55 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 56 | browsers: ['Chrome'], 57 | 58 | 59 | // Continuous Integration mode 60 | // if true, Karma captures browsers, runs the tests and exits 61 | singleRun: false 62 | }); 63 | }; 64 | -------------------------------------------------------------------------------- /lib/FormDataMixin.coffee: -------------------------------------------------------------------------------- 1 | isCheckbox = (el) -> el.getAttribute('type') == 'checkbox' 2 | 3 | isMultiChoice = (checkbox) -> checkbox.getAttribute('value')? 4 | 5 | toggleValue = (arr, val) -> 6 | valueIndex = arr.indexOf val 7 | if valueIndex != -1 then arr.splice valueIndex, 1 else arr.push val 8 | return arr 9 | 10 | getValue = (el, currentValue) -> 11 | unless isCheckbox el 12 | return el.value 13 | else 14 | if isMultiChoice el 15 | currentValue ?= [] 16 | return toggleValue currentValue, el.value 17 | else 18 | return el.checked 19 | 20 | module.exports = 21 | 22 | UNSAFE_componentWillMount: -> 23 | if @getInitialFormData? 24 | @formData = @getInitialFormData() 25 | else 26 | @formData = {} 27 | 28 | updateFormData: (e) -> 29 | t = e.target 30 | key = t.getAttribute 'name' 31 | if key? 32 | newValue = getValue t, @formData[key] 33 | @setFormData key, newValue 34 | @formDataDidChange() if @formDataDidChange? 35 | 36 | setFormData: (key, value) -> @formData[key] = value 37 | 38 | clearFormData: -> @formData = {} 39 | 40 | resetFormData: (obj) -> 41 | @clearFormData() 42 | Object.keys(obj).forEach (key) => 43 | @formData[key] = obj[key] 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-form-data", 3 | "version": "0.2.4", 4 | "description": "React mixin to get form data in nice javascript object format.", 5 | "main": "index.js", 6 | "scripts": { 7 | "prepublishOnly": "coffee -o dist -cb lib", 8 | "bundleReact": "browserify -r react/addons > generated/react-browserified.js", 9 | "testWatch": "watchify -x react/addons -t coffee-reactify test/FormDataMixinTest.cjsx -o generated/testsbundle.js -v", 10 | "runtests": "touch generated/testsbundle.js && karma start", 11 | "dev": "npm run testWatch & npm run runtests", 12 | "pretest": "npm run bundleReact && browserify -x react/addons -t coffee-reactify test/FormDataMixinTest.cjsx -o generated/testsbundle.js", 13 | "test": "karma start --single-run", 14 | "predemo": "npm i", 15 | "demo": "coffee demo/server.coffee" 16 | }, 17 | "keywords": [ 18 | "react", 19 | "react-component", 20 | "react-mixin", 21 | "form-data" 22 | ], 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/TheLudd/react-form-data" 26 | }, 27 | "homepage": "https://github.com/TheLudd/react-form-data", 28 | "files": [ 29 | "README.md", 30 | "dist/", 31 | "lib/", 32 | "index.js" 33 | ], 34 | "author": "Ludwig Magnusson", 35 | "license": "ISC", 36 | "peerDependencies": { 37 | "react": ">=0.11.1" 38 | }, 39 | "devDependencies": { 40 | "browserify": "^5.11.2", 41 | "coffee-reactify": "^0.5.2", 42 | "coffee-script": "^1.8.0", 43 | "karma": "^0.12.23", 44 | "karma-chrome-launcher": "^0.1.4", 45 | "karma-cli": "0.0.4", 46 | "karma-mocha": "^0.1.9", 47 | "react": "~0.12.0", 48 | "should": "^4.0.4", 49 | "watchify": "^1.0.2" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/FormDataMixinTest.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | TestUtils = require('react/addons').addons.TestUtils 3 | TestForm = require './TestForm.cjsx' 4 | should = require 'should' 5 | 6 | describe 'ReactFormMixin', -> 7 | 8 | component = null 9 | 10 | beforeEach -> 11 | component = TestUtils.renderIntoDocument{JSON.stringify(@state.display, undefined, 2)}50 |