├── .babelrc ├── .storybook ├── addons.js └── config.js ├── storybook-static └── favicon.ico ├── dist ├── index.js ├── ReactstrapFormikInput.js ├── ReactstrapRadioInput.js └── ReactstrapSelectInput.js ├── src ├── components │ ├── index.js │ ├── ReactstrapFormikInput.js │ ├── ReactstrapRadioInput.js │ └── ReactstrapSelectInput.js └── stories │ ├── index.js │ ├── RadioStory.js │ ├── InputStory.js │ └── SelectStory.js ├── .gitignore ├── README.md ├── LICENSE └── package.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react-app"] 3 | } -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-actions/register'; 2 | import '@storybook/addon-links/register'; -------------------------------------------------------------------------------- /storybook-static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shoaibkhan94/reactstrap-formik/HEAD/storybook-static/favicon.ico -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import {configure} from '@storybook/react'; 2 | 3 | function loadStories() { 4 | require('../src/stories'); 5 | } 6 | 7 | configure(loadStories, module); 8 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | import ReactstrapInput from './ReactstrapFormikInput'; 2 | import ReactstrapRadio from './ReactstrapRadioInput'; 3 | import ReactstrapSelect from './ReactstrapSelectInput'; 4 | 5 | export { ReactstrapInput, ReactstrapRadio, ReactstrapSelect }; -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | import ReactstrapInput from './ReactstrapFormikInput'; 2 | import ReactstrapRadio from './ReactstrapRadioInput'; 3 | import ReactstrapSelect from './ReactstrapSelectInput'; 4 | 5 | 6 | export {ReactstrapInput, ReactstrapRadio, ReactstrapSelect}; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | .idea 19 | .out 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | -------------------------------------------------------------------------------- /src/stories/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import 'bootstrap/dist/css/bootstrap.min.css' 3 | 4 | import {storiesOf} from '@storybook/react'; 5 | import InputStory from "./InputStory"; 6 | import SelectStory from "./SelectStory"; 7 | import RadioStory from "./RadioStory"; 8 | 9 | //storiesOf('Welcome', module).add('to Storybook', () => ); 10 | 11 | storiesOf('Formik with Reactstrap', module) 12 | .add('Input', () => ) 13 | .add('Select', () => ) 14 | .add('Radio', () => ); 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Bindings for using [Formik](https://github.com/jaredpalmer/formik) with [Reactstrap](https://reactstrap.github.io/). 3 | 4 | ## Getting Started 5 | 6 | npm install reactstrap-formik 7 | 8 | ## Usage Examples 9 | * Text Input [Example](https://codesandbox.io/s/xl6mx6w8z4) 10 | * Select Input [Example](https://codesandbox.io/s/6l3oo28kq3) 11 | * Radio Input [Example](https://codesandbox.io/s/0vm7yo754w) 12 | 13 | ## Development 14 | 15 | npm install 16 | npm run storybook 17 | 18 | [Demo](https://shoaibkhan94.github.io/reactstrap-formik) 19 | -------------------------------------------------------------------------------- /src/components/ReactstrapFormikInput.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {FormFeedback, FormGroup, Input, Label} from "reactstrap"; 3 | 4 | const ReactstrapFormikInput = ( 5 | { 6 | field: {...fields}, 7 | form: {touched, errors, ...rest}, 8 | ...props 9 | }) => ( 10 | 11 | 12 | 13 | {touched[fields.name] && errors[fields.name] ? {errors[fields.name]} : ''} 14 | 15 | ); 16 | export default ReactstrapFormikInput; 17 | -------------------------------------------------------------------------------- /src/components/ReactstrapRadioInput.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {FormGroup, Input, Label} from "reactstrap"; 3 | 4 | const ReactstrapRadioInput = ({ 5 | field, 6 | form: {isSubmitting, setFieldValue, touched, errors, values}, 7 | disabled = false, 8 | ...props 9 | }) => { 10 | return ( 11 | 12 | 16 | 17 | ) 18 | }; 19 | 20 | export default ReactstrapRadioInput; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 shoaib khan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dist/ReactstrapFormikInput.js: -------------------------------------------------------------------------------- 1 | function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } 2 | 3 | import React from 'react'; 4 | import { FormFeedback, FormGroup, Input, Label } from "reactstrap"; 5 | 6 | var ReactstarpFormikInput = function ReactstarpFormikInput(_ref) { 7 | var fields = _objectWithoutProperties(_ref.field, []), 8 | _ref$form = _ref.form, 9 | touched = _ref$form.touched, 10 | errors = _ref$form.errors, 11 | rest = _objectWithoutProperties(_ref$form, ["touched", "errors"]), 12 | props = _objectWithoutProperties(_ref, ["field", "form"]); 13 | 14 | return React.createElement( 15 | FormGroup, 16 | null, 17 | React.createElement( 18 | Label, 19 | { "for": props.id, className: "label-color" }, 20 | props.label 21 | ), 22 | React.createElement(Input, Object.assign({}, props, fields, { invalid: Boolean(touched[fields.name] && errors[fields.name]) })), 23 | touched[fields.name] && errors[fields.name] ? React.createElement( 24 | FormFeedback, 25 | null, 26 | errors[fields.name] 27 | ) : '' 28 | ); 29 | }; 30 | export default ReactstarpFormikInput; -------------------------------------------------------------------------------- /dist/ReactstrapRadioInput.js: -------------------------------------------------------------------------------- 1 | function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } 2 | 3 | import * as React from 'react'; 4 | import { FormGroup, Input, Label } from "reactstrap"; 5 | 6 | var ReactstrapRadioInput = function ReactstrapRadioInput(_ref) { 7 | var field = _ref.field, 8 | _ref$form = _ref.form, 9 | isSubmitting = _ref$form.isSubmitting, 10 | setFieldValue = _ref$form.setFieldValue, 11 | touched = _ref$form.touched, 12 | errors = _ref$form.errors, 13 | values = _ref$form.values, 14 | _ref$disabled = _ref.disabled, 15 | disabled = _ref$disabled === undefined ? false : _ref$disabled, 16 | props = _objectWithoutProperties(_ref, ["field", "form", "disabled"]); 17 | 18 | return React.createElement( 19 | FormGroup, 20 | { check: true, inline: true }, 21 | React.createElement( 22 | Label, 23 | { "for": props.id }, 24 | React.createElement(Input, Object.assign({}, props, { type: "radio", name: field.name, checked: values[field.name] === field.value, value: field.value, 25 | onChange: function onChange(event, value) { 26 | return setFieldValue(field.name, field.value); 27 | } })), 28 | props.label 29 | ) 30 | ); 31 | }; 32 | 33 | export default ReactstrapRadioInput; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reactstrap-formik", 3 | "version": "1.0.9", 4 | "dependencies": { 5 | "bootstrap": "^4.1.3", 6 | "formik": "^1.3.0", 7 | "reactstrap": "^6.4.0" 8 | }, 9 | "devDependencies": { 10 | "@storybook/addon-actions": "^3.4.11", 11 | "@storybook/addon-links": "^3.4.11", 12 | "@storybook/addons": "^3.4.11", 13 | "@storybook/react": "^3.4.11", 14 | "@storybook/storybook-deployer": "^2.3.0", 15 | "babel-cli": "^6.26.0", 16 | "babel-core": "^6.26.3", 17 | "babel-runtime": "^6.26.0", 18 | "react": "^16.5.2", 19 | "react-dom": "^16.5.2", 20 | "react-scripts": "1.1.5" 21 | }, 22 | "peerDependencies": { 23 | "react": "^16.5.2", 24 | "react-dom": "^16.5.2" 25 | }, 26 | "scripts": { 27 | "start": "react-scripts start", 28 | "build": "rm -rf dist && NODE_ENV=production babel src/components --out-dir dist --copy-files --ignore __tests__,spec.js,test.js,__snapshots__", 29 | "test": "react-scripts test --env=jsdom", 30 | "eject": "react-scripts eject", 31 | "storybook": "start-storybook -p 9009 -s .out", 32 | "build-storybook": "build-storybook -c .storybook -o .out", 33 | "deploy-storybook": "storybook-to-ghpages" 34 | }, 35 | "author": "Shoaib Khan { 5 | if (this.ignoreNextBlur === true) { 6 | // The parent components are relying on the bubbling of the event. 7 | event.stopPropagation(); 8 | this.ignoreNextBlur = false; 9 | event.target.name = this.props.name; 10 | return; 11 | } 12 | };*/ 13 | 14 | const ReactstrapSelectInput = ({ 15 | field, 16 | form: {isSubmitting, touched, errors}, 17 | disabled = false, 18 | ...props 19 | }) => { 20 | let error = errors[field.name]; 21 | let touch = touched[field.name]; 22 | return ( 23 | 24 | 25 | 28 | 29 | {props.inputprops.options.map((option, index) => { 30 | if (option.name) 31 | return (); 32 | return () 33 | })} 34 | 35 | {touch && error && {error}} 36 | 37 | ) 38 | }; 39 | 40 | export default ReactstrapSelectInput; -------------------------------------------------------------------------------- /src/stories/RadioStory.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Field, Form, Formik} from 'formik'; 3 | import RadioInput from '../components/ReactstrapRadioInput'; 4 | import {action} from '@storybook/addon-actions'; 5 | import {Col, Container, Row} from "reactstrap"; 6 | 7 | export default () => ( 8 | { 11 | const errors = {}; 12 | if (!values.available) { 13 | errors.available = 'Required'; 14 | } 15 | return errors; 16 | }} 17 | onSubmit={(values, {setSubmitting}) => { 18 | 19 | console.log(values); 20 | //Make API calls here 21 | 22 | setTimeout(() => { 23 | setSubmitting(false); 24 | action('submit')(values); 25 | alert(`Submitted Successfully -> ${JSON.stringify(values, null, 2)}`) 26 | }, 2000); 27 | }} 28 | render={({submitForm, isSubmitting, values}) => ( 29 |
30 | 31 | 32 | 33 | Available 34 | 35 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 50 | 51 | 52 |
53 |                         {JSON.stringify(values, null, 2)}
54 |                     
55 |
56 |
57 | )} 58 | /> 59 | ); -------------------------------------------------------------------------------- /dist/ReactstrapSelectInput.js: -------------------------------------------------------------------------------- 1 | function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } 2 | 3 | import * as React from 'react'; 4 | import { FormFeedback, FormGroup, Input, Label } from "reactstrap"; 5 | 6 | /*let handleBlur = event => { 7 | if (this.ignoreNextBlur === true) { 8 | // The parent components are relying on the bubbling of the event. 9 | event.stopPropagation(); 10 | this.ignoreNextBlur = false; 11 | event.target.name = this.props.name; 12 | return; 13 | } 14 | };*/ 15 | 16 | var ReactstrapSelectInput = function ReactstrapSelectInput(_ref) { 17 | var field = _ref.field, 18 | _ref$form = _ref.form, 19 | isSubmitting = _ref$form.isSubmitting, 20 | touched = _ref$form.touched, 21 | errors = _ref$form.errors, 22 | _ref$disabled = _ref.disabled, 23 | disabled = _ref$disabled === undefined ? false : _ref$disabled, 24 | props = _objectWithoutProperties(_ref, ["field", "form", "disabled"]); 25 | 26 | var error = errors[field.name]; 27 | var touch = touched[field.name]; 28 | return React.createElement( 29 | FormGroup, 30 | null, 31 | React.createElement( 32 | Label, 33 | { "for": props.inputprops.id, className: "label-color" }, 34 | props.label 35 | ), 36 | React.createElement( 37 | Input, 38 | Object.assign({ id: props.inputprops.id }, field, props, { type: "select", 39 | invalid: Boolean(touched[field.name] && errors[field.name]), 40 | placeholder: "Test" }), 41 | React.createElement( 42 | "option", 43 | { value: "" }, 44 | props.inputprops.defaultOption 45 | ), 46 | props.inputprops.options.map(function (option, index) { 47 | if (option.name) return React.createElement( 48 | "option", 49 | { value: option.id, key: index }, 50 | option.name 51 | ); 52 | return React.createElement( 53 | "option", 54 | { value: option, key: index }, 55 | option 56 | ); 57 | }) 58 | ), 59 | touch && error && React.createElement( 60 | FormFeedback, 61 | null, 62 | error 63 | ) 64 | ); 65 | }; 66 | 67 | export default ReactstrapSelectInput; -------------------------------------------------------------------------------- /src/stories/InputStory.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Field, Form, Formik} from 'formik'; 3 | import TextField from '../components/ReactstrapFormikInput'; 4 | import {action} from '@storybook/addon-actions'; 5 | import {Col, Container, Row} from "reactstrap"; 6 | 7 | export default () => ( 8 | { 11 | const errors = {}; 12 | if (!values.email) { 13 | errors.email = 'Required'; 14 | } else if ( 15 | !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email) 16 | ) { 17 | errors.email = 'Invalid email address'; 18 | } 19 | return errors; 20 | }} 21 | onSubmit={(values, {setSubmitting}) => { 22 | 23 | console.log(values); 24 | //Make API calls here 25 | 26 | setTimeout(() => { 27 | setSubmitting(false); 28 | action('submit')(values); 29 | alert(`Submitted Successfully -> ${JSON.stringify(values, null, 2)}`) 30 | }, 2000); 31 | }} 32 | render={({submitForm, isSubmitting, values}) => ( 33 |
34 | 35 | 36 | 37 | 44 | 45 | 46 | 53 | 54 | 55 | 60 | 61 | 62 |
63 |                         {JSON.stringify(values, null, 2)}
64 |                     
65 |
66 |
67 | )} 68 | /> 69 | ); -------------------------------------------------------------------------------- /src/stories/SelectStory.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Field, Form, Formik} from 'formik'; 3 | import SelectInput from '../components/ReactstrapSelectInput'; 4 | import {action} from '@storybook/addon-actions'; 5 | import {Col, Container, Row} from "reactstrap"; 6 | 7 | export default () => ( 8 | { 11 | const errors = {}; 12 | if (!values.country) { 13 | errors.country = 'Required'; 14 | } 15 | return errors; 16 | }} 17 | onSubmit={(values, {setSubmitting}) => { 18 | 19 | console.log(values); 20 | //Make API calls here 21 | 22 | setTimeout(() => { 23 | setSubmitting(false); 24 | action('submit')(values); 25 | alert(`Submitted Successfully -> ${JSON.stringify(values, null, 2)}`) 26 | }, 2000); 27 | }} 28 | render={({submitForm, isSubmitting, values}) => ( 29 |
30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 56 | 57 | 58 | 59 | 64 | 65 | 66 |
67 |                         {JSON.stringify(values, null, 2)}
68 |                     
69 |
70 |
71 | )} 72 | /> 73 | ); --------------------------------------------------------------------------------