From cb0e4cf4bc5c39fe49b62d8d8849790a6ff2f756 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Thu, 13 Apr 2017 16:35:19 +0300 Subject: [PATCH] fix(Input): add handling of input's ref --- src/elements/Input/Input.js | 20 +++++++--- test/specs/elements/Input/Input-test.js | 53 +++++++++++++++---------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/elements/Input/Input.js b/src/elements/Input/Input.js index 3abb1619fd..d77a66a9b0 100644 --- a/src/elements/Input/Input.js +++ b/src/elements/Input/Input.js @@ -1,6 +1,6 @@ -import _ from 'lodash' -import React, { Children, cloneElement, Component, PropTypes } from 'react' import cx from 'classnames' +import _ from 'lodash' +import React, { Children, Component, PropTypes } from 'react' import { createHTMLInput, @@ -114,6 +114,8 @@ class Input extends Component { type: META.TYPES.ELEMENT, } + focus = () => (this.inputRef.focus()) + handleChange = (e) => { const { onChange } = this.props const value = _.get(e, 'target.value') @@ -121,9 +123,12 @@ class Input extends Component { onChange(e, { ...this.props, value }) } - focus = () => { - this.inputRef.focus() - } + handleInputOverrides = predefinedProps => ({ + ref: c => { + _.invoke(predefinedProps, 'ref', c) + this.handleInputRef(c) + }, + }) handleInputRef = c => (this.inputRef = c) @@ -187,7 +192,10 @@ class Input extends Component { const childElements = _.map(Children.toArray(children), (child) => { if (child.type !== 'input') return child - return cloneElement(child, { ...htmlInputProps, ...child.props }) + return createHTMLInput(child, { + defaultProps: htmlInputProps, + overrideProps: this.handleInputOverrides, + }) }) return {childElements} diff --git a/test/specs/elements/Input/Input-test.js b/test/specs/elements/Input/Input-test.js index f5648fbad1..094364a12c 100644 --- a/test/specs/elements/Input/Input-test.js +++ b/test/specs/elements/Input/Input-test.js @@ -53,14 +53,14 @@ describe('Input', () => { common.hasUIClassName(Input) common.rendersChildren(Input) - common.implementsLabelProp(Input, { - shorthandDefaultProps: { className: 'label' }, - }) + common.implementsCreateMethod(Input) common.implementsButtonProp(Input, { propKey: 'action', shorthandDefaultProps: { className: 'button' }, }) - common.implementsCreateMethod(Input) + common.implementsLabelProp(Input, { + shorthandDefaultProps: { className: 'label' }, + }) common.implementsHTMLInputProp(Input, { alwaysPresent: true, shorthandDefaultProps: { type: 'text' }, @@ -138,6 +138,22 @@ describe('Input', () => { }) }) + describe('focus', () => { + it('can be set via a ref', () => { + const mountNode = document.createElement('div') + document.body.appendChild(mountNode) + + const wrapper = mount(, { attachTo: mountNode }) + wrapper.instance().focus() + + const input = document.querySelector('.ui.input input') + document.activeElement.should.equal(input) + + wrapper.detach() + document.body.removeChild(mountNode) + }) + }) + describe('onChange', () => { it('is called with (e, data) on change', () => { const spy = sandbox.spy() @@ -170,42 +186,39 @@ describe('Input', () => { }) }) + describe('ref', () => { + it('maintains ref on child node', () => { + const ref = sandbox.spy() + const wrapper = mount() + + // ref.should.have.been.calledOnce() + wrapper.instance().inputRef.tagName.should.equal('INPUT') + }) + }) + describe('tabIndex', () => { it('is not set by default', () => { shallow() .find('input') .should.not.have.prop('tabIndex') }) + it('defaults to -1 when disabled', () => { shallow() .find('input') .should.have.prop('tabIndex', -1) }) + it('can be set explicitly', () => { shallow() .find('input') .should.have.prop('tabIndex', 123) }) + it('can be set explicitly when disabled', () => { shallow() .find('input') .should.have.prop('tabIndex', 123) }) }) - - describe('focus', () => { - it('can be set via a ref', () => { - const mountNode = document.createElement('div') - document.body.appendChild(mountNode) - - const wrapper = mount(, { attachTo: mountNode }) - wrapper.instance().focus() - - const input = document.querySelector('.ui.input input') - document.activeElement.should.equal(input) - - wrapper.detach() - document.body.removeChild(mountNode) - }) - }) })