Skip to content

Commit

Permalink
[TextField] added characterCount attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
heetvachhani committed Mar 1, 2016
1 parent 9e0b348 commit 3936295
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 2 deletions.
82 changes: 82 additions & 0 deletions src/TextField/TextCharCount.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';
const propTypes = {
/**
* True if current count exceeds maximum count.
*/
countError: React.PropTypes.bool,

/**
* Current number of character in the Textfield.
*/
currentChar: React.PropTypes.number,

/**
* Override the inline-styles of the error element.
*/
errorStyle: React.PropTypes.object,

/**
* Maximum number of character in the Textfield.
*/
maxChar: React.PropTypes.number,

/**
* @ignore
* The material-ui theme applied to this component.
*/
muiTheme: React.PropTypes.object.isRequired,

/**
* Override the inline-styles of the root element.
*/
style: React.PropTypes.object,
};

const defaultProps = {
};

const TextCharCount = (props) => {
const {
countError,
currentChar,
maxChar,
muiTheme,
style,
errorStyle,
} = props;

const {
prepareStyles,
textField: {
hintColor,
errorColor,
},
} = muiTheme;

const styles = {
root: {
position: 'relative',
color: hintColor,
float: 'right',
fontSize: '12px',
bottom: 8,
},
error: {
color: errorColor,
},
};

let regularStyle = Object.assign({}, styles.root, style);
if (countError) regularStyle = Object.assign({}, styles.root, styles.error, errorStyle);

return (
<div style={prepareStyles(regularStyle)}>
{currentChar}/{maxChar}
</div>
);
};

TextCharCount.propTypes = propTypes;
TextCharCount.defaultProps = defaultProps;

export default TextCharCount;
48 changes: 46 additions & 2 deletions src/TextField/TextField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import getMuiTheme from '../styles/getMuiTheme';
import TextFieldHint from './TextFieldHint';
import TextFieldLabel from './TextFieldLabel';
import TextFieldUnderline from './TextFieldUnderline';
import TextCharCount from './TextCharCount';


const getStyles = (props, state) => {
const {
Expand Down Expand Up @@ -81,6 +83,10 @@ const getStyles = (props, state) => {
styles.floatingLabel.color = ColorManipulator.fade(props.disabled ? disabledTextColor : floatingLabelColor, 0.5);
}

if(state.charCountError){
styles.floatingLabel.color = errorColor;
}

if (props.floatingLabelText) {
styles.input.boxSizing = 'border-box';

Expand Down Expand Up @@ -115,6 +121,16 @@ function isValid(value) {
const TextField = React.createClass({

propTypes: {
/**
* Maximum number of character in the Textfield
*/
charCountMax: React.PropTypes.number,

/**
* The style object to use to override character count style.
*/
charCountStyle: React.PropTypes.bool,

children: React.PropTypes.node,

/**
Expand Down Expand Up @@ -211,6 +227,10 @@ const TextField = React.createClass({
*/
onKeyDown: React.PropTypes.func,

/**
* Callback function fired when key is up.
*/

/**
* Number of rows to display when multiLine option is set to true.
*/
Expand Down Expand Up @@ -296,6 +316,8 @@ const TextField = React.createClass({
hasValue: isValid(props.value) || isValid(props.defaultValue) ||
(props.valueLink && isValid(props.valueLink.value)),
muiTheme: this.context.muiTheme || getMuiTheme(),
currentCharCount: (this.props.defaultValue) ? this.props.defaultValue.length : 0,
charCountError: false,
};
},

Expand Down Expand Up @@ -370,6 +392,12 @@ const TextField = React.createClass({
if (this.props.onKeyDown) this.props.onKeyDown(event);
},

_handleInputKeyUp() {
this.setState({currentCharCount: this.getValue().length});
if (this.props.charCountMax >= this.getValue().length) this.setState({charCountError: false});
if (this.props.charCountMax < this.getValue().length) this.setState({charCountError: true});
},

_handleTextAreaHeightChange(event, height) {
let newHeight = height + 24;
if (this.props.floatingLabelText) newHeight += 24;
Expand All @@ -384,6 +412,8 @@ const TextField = React.createClass({
render() {
const {
className,
charCountStyle,
charCountMax,
disabled,
errorStyle,
errorText,
Expand Down Expand Up @@ -424,7 +454,7 @@ const TextField = React.createClass({
const floatingLabelTextElement = floatingLabelText && (
<TextFieldLabel
muiTheme={this.state.muiTheme}
style={Object.assign(styles.floatingLabel, this.props.floatingLabelStyle)}
style= {Object.assign(styles.floatingLabel, this.props.floatingLabelStyle)}
htmlFor={inputId}
shrink={this.state.hasValue || this.state.isFocused}
disabled={disabled}
Expand All @@ -441,6 +471,7 @@ const TextField = React.createClass({
onFocus: this._handleInputFocus,
disabled: this.props.disabled,
onKeyDown: this._handleInputKeyDown,
onKeyUp: this._handleInputKeyUp,
};

const inputStyleMerged = Object.assign(styles.input, inputStyle);
Expand All @@ -467,13 +498,15 @@ const TextField = React.createClass({
rowsMax={rowsMax}
onHeightChange={this._handleTextAreaHeightChange}
textareaStyle={Object.assign(styles.textarea, textareaStyle)}
onKeyUp={this._handleInputKeyUp}
/>
) : (
<input
{...other}
{...inputProps}
style={prepareStyles(inputStyleMerged)}
type={type}
onKeyUp={this._handleInputKeyUp}
/>
);
}
Expand All @@ -495,7 +528,7 @@ const TextField = React.createClass({
<TextFieldUnderline
disabled={disabled}
disabledStyle={underlineDisabledStyle}
error={!!this.state.errorText}
error={!!this.state.errorText || this.state.charCountError}
errorStyle={errorStyle}
focus={this.state.isFocused}
focusStyle={underlineFocusStyle}
Expand All @@ -504,6 +537,17 @@ const TextField = React.createClass({
/> :
null
}
{(charCountMax && this.state.isFocused) ?
<TextCharCount
muiTheme={this.state.muiTheme}
style={charCountStyle}
maxChar={charCountMax}
currentChar={this.state.currentCharCount}
countError={this.state.charCountError}
errorStyle={errorStyle}
/> :
null
}
{errorTextElement}
</div>
);
Expand Down

0 comments on commit 3936295

Please sign in to comment.