Skip to content

Commit

Permalink
expose a .focus() method
Browse files Browse the repository at this point in the history
It will be present on formsy-material-ui components that
wrap material-ui components that possess a `.focus()`
method.  It will call the underlying material-ui
component's `.focus()` method.
  • Loading branch information
py-in-the-sky committed Feb 6, 2016
1 parent 7ff9a61 commit 859a582
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 6 deletions.
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,60 @@ const Form = React.createClass({
});
```

Material-ui provides a `.focus()` method for some its components, such as `TextField`. formsy-material-ui components wrap Material-UI components, and if the underlying Material-UI component has a `.focus()` method, then the formsy-material-ui components will also expose a `.focus()` method, which just delegates to the underlying Material-UI component's `.focus()`.

In the example below, we implement part of a chat-messaging application. The component is a form that provides a text input and a submit button; users can enter their message in the input and send it with the submit button. As a UX feature, we clear the form (`resetForm()`) and put the user's cursor back in the text field (`this.messageInput.focus()`) so that the user can easily begin to type his or her next message. We set a React `ref` on the `FormsyText` component (setting it to `this.messageInput`) in order to have access to it and use `.focus()`.


```jsx
import React, { Component, PropTypes } from 'react'
import { Form } from 'formsy-react'
import RaisedButton from 'material-ui/lib/raised-button'
import FormsyText from 'formsy-material-ui/lib/FormsyText'

export default class ChatMessageForm extends Component {
constructor (props) {
super(props)
this.submit = this.submit.bind(this)
this.refMessageInput = c => this.messageInput = c
}

submit (model, resetForm) {
this.props.submitMessage(model.message)
resetForm()
this.messageInput.focus()
}

render () {
return (
<Form onValidSubmit={this.submit}>

<FormsyText
ref={this.refMessageInput}
name="message"
required
formNoValidate
hintText="What's on your mind?"
validations="isAlpha,minLength:1,maxLength:1000"
/>

<RaisedButton
type="submit"
primary={true}
label="SEND"
/>

</Form>
)
}
}

ChatMessageForm.propTypes = {
submitMessage: PropTypes.func.isRequired
}
```


## Known Issues

See [issues](https://github.com/mbrookes/formsy-material-ui/issues).
Expand Down
7 changes: 5 additions & 2 deletions src/FormsyCheckbox.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Formsy from 'formsy-react';
import Checkbox from 'material-ui/lib/checkbox';
import { _setMuiComponentAndMaybeFocus } from './utils';

let FormsyCheckbox = React.createClass({
mixins: [ Formsy.Mixin ],
Expand All @@ -14,14 +15,16 @@ let FormsyCheckbox = React.createClass({
},

componentDidMount: function () {
this.setValue(this._checkbox.isChecked());
this.setValue(this._muiComponent.isChecked());
},

_setMuiComponentAndMaybeFocus: _setMuiComponentAndMaybeFocus,

render: function () {
return (
<Checkbox
{...this.props}
ref={(c) => this._checkbox = c}
ref={this._setMuiComponentAndMaybeFocus}
onCheck={this.handleValueChange}
checked={this.getValue()}
/>
Expand Down
4 changes: 4 additions & 0 deletions src/FormsyDate.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Formsy from 'formsy-react';
import DatePicker from 'material-ui/lib/date-picker/date-picker';
import { _setMuiComponentAndMaybeFocus } from './utils';

let FormsyDate = React.createClass({
mixins: [ Formsy.Mixin ],
Expand All @@ -13,12 +14,15 @@ let FormsyDate = React.createClass({
this.setValue(value);
},

_setMuiComponentAndMaybeFocus: _setMuiComponentAndMaybeFocus,

render: function () {
return (
<DatePicker
// Sets the default date format to be ISO8601 (YYYY-MM-DD), accounting for current timezone
formatDate={(date) => (new Date(date.toDateString()+" 12:00:00 +0000")).toISOString().substring(0,10)}
{...this.props}
ref={this._setMuiComponentAndMaybeFocus}
defaultValue={this.props.value}
onChange={this.handleValueChange}
errorText={this.getErrorMessage()}
Expand Down
7 changes: 5 additions & 2 deletions src/FormsyRadioGroup.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Formsy from 'formsy-react';
import RadioButtonGroup from 'material-ui/lib/radio-button-group';
import { _setMuiComponentAndMaybeFocus } from './utils';

let FormsyRadioGroup = React.createClass({
mixins: [ Formsy.Mixin ],
Expand All @@ -14,14 +15,16 @@ let FormsyRadioGroup = React.createClass({
},

componentDidMount: function () {
this.setValue(this._radio.getSelectedValue());
this.setValue(this._muiComponent.getSelectedValue());
},

_setMuiComponentAndMaybeFocus: _setMuiComponentAndMaybeFocus,

render: function () {
return (
<RadioButtonGroup
{...this.props}
ref={(c) => this._radio = c}
ref={this._setMuiComponentAndMaybeFocus}
onChange={this.handleValueChange}
>
{this.props.children}
Expand Down
4 changes: 4 additions & 0 deletions src/FormsySelect.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Formsy from 'formsy-react';
import SelectField from 'material-ui/lib/select-field';
import { _setMuiComponentAndMaybeFocus } from './utils';

let FormsySelect = React.createClass({
mixins: [ Formsy.Mixin],
Expand All @@ -20,12 +21,15 @@ let FormsySelect = React.createClass({
this.setState({hasChanged: true});
},

_setMuiComponentAndMaybeFocus: _setMuiComponentAndMaybeFocus,

render: function () {
var value = this.state.hasChanged ? this.getValue() : this.props.value;

return (
<SelectField
{...this.props}
ref={this._setMuiComponentAndMaybeFocus}
onChange={this.handleChange}
errorText={this.getErrorMessage()}
value={value}
Expand Down
4 changes: 4 additions & 0 deletions src/FormsyText.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Formsy from 'formsy-react';
import TextField from 'material-ui/lib/text-field';
import { _setMuiComponentAndMaybeFocus } from './utils';

let FormsyText = React.createClass({
mixins: [ Formsy.Mixin ],
Expand Down Expand Up @@ -38,10 +39,13 @@ let FormsyText = React.createClass({
this.setValue(event.currentTarget.value);
},

_setMuiComponentAndMaybeFocus: _setMuiComponentAndMaybeFocus,

render: function () {
return (
<TextField
{...this.props}
ref={this._setMuiComponentAndMaybeFocus}
defaultValue={this.props.value}
onChange={this.handleChange}
onBlur={this.handleBlur}
Expand Down
4 changes: 4 additions & 0 deletions src/FormsyTime.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Formsy from 'formsy-react';
import TimePicker from 'material-ui/lib/time-picker/time-picker';
import { _setMuiComponentAndMaybeFocus } from './utils';

let FormsyTime = React.createClass({
mixins: [ Formsy.Mixin ],
Expand All @@ -13,10 +14,13 @@ let FormsyTime = React.createClass({
this.setValue(value);
},

_setMuiComponentAndMaybeFocus: _setMuiComponentAndMaybeFocus,

render: function () {
return (
<TimePicker
{...this.props}
ref={this._setMuiComponentAndMaybeFocus}
onChange={this.handleValueChange}
/>
);
Expand Down
7 changes: 5 additions & 2 deletions src/FormsyToggle.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Formsy from 'formsy-react';
import Toggle from 'material-ui/lib/toggle';
import { _setMuiComponentAndMaybeFocus } from './utils';

let FormsyToggle = React.createClass({
mixins: [ Formsy.Mixin ],
Expand All @@ -14,14 +15,16 @@ let FormsyToggle = React.createClass({
},

componentDidMount: function () {
this.setValue(this._toggle.isToggled());
this.setValue(this._muiComponent.isToggled());
},

_setMuiComponentAndMaybeFocus: _setMuiComponentAndMaybeFocus,

render: function () {
return (
<Toggle
{...this.props}
ref={(c) => this._toggle = c}
ref={this._setMuiComponentAndMaybeFocus}
onToggle={this.handleValueChange}
/>
);
Expand Down
11 changes: 11 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function _setMuiComponentAndMaybeFocus (c) {
if (c === this._muiComponent) return;

this._muiComponent = c;

if (c && typeof c.focus === 'function') {
this.focus = () => c.focus();
} else if (this.hasOwnProperty('focus')) {
delete this.focus;
}
}

0 comments on commit 859a582

Please sign in to comment.