From 2b249113d819620cfaefcc787ae6282d4746d695 Mon Sep 17 00:00:00 2001 From: Aesop Wolf Date: Thu, 8 Dec 2016 22:24:19 -0800 Subject: [PATCH] feat: expose inner element when using HOC (#399) Use `innerRef={(c) => { this.myInput = c; }}` on your HOC to access the internal element --- API.md | 26 ++++++++++++++++++++++++-- src/HOC.js | 11 +++++++++-- tests/Formsy-spec.js | 18 ++++++++++++++++++ tests/utils/TestInputHoc.js | 13 +++++++++++++ 4 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 tests/utils/TestInputHoc.js diff --git a/API.md b/API.md index 08e123c..88c67f5 100644 --- a/API.md +++ b/API.md @@ -37,6 +37,7 @@ - [validate](#validate) - [formNoValidate](#formnovalidate) - [Formsy.HOC](#formsyhoc) + - [innerRef](#innerRef) - [Formsy.Decorator](#formsydecorator) - [Formsy.addValidationRule](#formsyaddvalidationrule) - [Validators](#validators) @@ -566,7 +567,7 @@ The same methods as the mixin are exposed to the HOC version of the element comp ```jsx import {HOC} from 'formsy-react'; -class MyInput extends React.Component { +class MyInputHoc extends React.Component { render() { return (
@@ -575,9 +576,30 @@ class MyInput extends React.Component { ); } }; -export default HOC(MyInput); +export default HOC(MyInputHoc); ``` +#### innerRef + +Use an `innerRef` prop to get a reference to your DOM node. + +```jsx +var MyForm = React.createClass({ + componentDidMount() { + this.searchInput.focus() + }, + render: function () { + return ( + + { this.searchInput = c; }} /> + + ); + } +}) +``` + +Sets a class name on the form itself. + ### Formsy.Decorator The same methods as the mixin are exposed to the decorator version of the element component, though through the `props`, not on the instance. ```jsx diff --git a/src/HOC.js b/src/HOC.js index e8717a6..849b69c 100644 --- a/src/HOC.js +++ b/src/HOC.js @@ -4,8 +4,10 @@ module.exports = function (Component) { return React.createClass({ displayName: 'Formsy(' + getDisplayName(Component) + ')', mixins: [Mixin], + render: function () { - return React.createElement(Component, { + const { innerRef } = this.props; + const propsForElement = { setValidations: this.setValidations, setValue: this.setValue, resetValue: this.resetValue, @@ -22,7 +24,12 @@ module.exports = function (Component) { showError: this.showError, isValidValue: this.isValidValue, ...this.props - }); + }; + + if (innerRef) { + propsForElement.ref = innerRef; + } + return React.createElement(Component, propsForElement); } }); }; diff --git a/tests/Formsy-spec.js b/tests/Formsy-spec.js index 05b8c2c..a1cdc4b 100755 --- a/tests/Formsy-spec.js +++ b/tests/Formsy-spec.js @@ -4,12 +4,30 @@ import TestUtils from 'react-addons-test-utils'; import Formsy from './..'; import TestInput from './utils/TestInput'; +import TestInputHoc from './utils/TestInputHoc'; import immediate from './utils/immediate'; import sinon from 'sinon'; export default { 'Setting up a form': { + 'should expose the users DOM node through an innerRef prop': function (test) { + const TestForm = React.createClass({ + render() { + return ( + + { this.name = c; }} /> + + ); + } + }); + + const form = TestUtils.renderIntoDocument(); + const input = form.name; + test.equal(input.methodOnWrappedInstance('foo'), 'foo'); + + test.done(); + }, 'should render a form into the document': function (test) { diff --git a/tests/utils/TestInputHoc.js b/tests/utils/TestInputHoc.js new file mode 100644 index 0000000..085be8f --- /dev/null +++ b/tests/utils/TestInputHoc.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { HOC as formsyHoc } from './../..'; + +const defaultProps = { + methodOnWrappedInstance(param) { + return param; + }, + render() { + return (); + }, +}; + +export default formsyHoc(React.createClass(defaultProps));