2014-12-23 4 views
3

У меня есть следующие реакции компонента:Реагировать компонентов и Invalid Input

var App = React.createClass({ 
    getInitialState: function() { 
     return {value: 4.5} 
    }, 
    change: function(event) { 
     this.setState({value: parseFloat(event.target.value)}); 
    }, 
    render: function() { 
     return <input type="number" value={this.state.value} onChange={this.change}/>; 
    } 
}); 

React.render(<App/>, document.body); 

Вы можете увидеть здесь: http://jsfiddle.net/2hauj2qg/

Проблема заключается в том, что если я хочу, чтобы ввести число, например: «4.7» , Когда пользователь вводит «4.», он становится «4», из-за того, что он преобразуется в поплавок сзади. Но это прерывает то, что пользователь вводил. Каков рекомендуемый способ решения этой проблемы?

ответ

4

Как imjared упоминалось, это потому, что вы используете parseFloat

this.setState({value: parseFloat(event.target.value)}); 

Вместо этого, вы можете разрешить только цифры и десятичные. Он остается хранимым в виде строки и никогда не изменяет их вход, но им не удается набирать такие символы, как буквы и пробелы.

var nonNumericRegex = /[^0-9.]+/g; 

this.setState({value: event.target.value.replace(nonNumericRegex, "")}); 

Чтобы разрешить отрицательные числа вам нужно сделать, это:

this.setState({ 
    value: event.target.value 
     .replace(nonNumericRegex, "") 
     .replace(/^(-.*?)-/g, "$1") 
}); 

Для усиления ведущего знака доллара и не более двух знаков после запятой, и если первый символ (после $) десятичный , префикс с 0.

this.setState({ 
    value: "$" + event.target.value 
     .replace(nonNumericRegex, "") 
     .replace(/(\.\d\d)\d+/g, "$1") 
     .replace(/^\./g, "0.") 
}) 
+0

Как я отметил в своем вопросе, я знаю, что это из-за parseFloat. Ваше решение позволит мне сохранить строку, но мне нужны фактические числа в моей модели данных, а не строка. –

+0

'this.state' - это состояние ui, вы можете преобразовать его в число, прежде чем передавать его в другом месте. Нет лучшего решения, о котором я знаю. – FakeRainBrigand

0

Если это не имеет смысла делать что-либо с номером, пока они не сделали печатать и следовать стандартному способу повышения события сигнализировать измененные данные, вы можете выполнитьэто со следующим:

var MyComponent = React.createClass({ 
    getInitialState: function() { 
     return {value: 4.5}; 
    }, 
    change: function(event) { 
     this.setState({value: event.target.value}); 
    }, 
    blur: function(event) { 
     this.props.onChange({value: parseFloat(event.target.value)}); 
    }, 
    render: function() { 
     return <input type="number" value={this.state.value} onBlur={this.blur} onChange={this.change}/>; 
    } 
}); 

React.render(<MyComponent/>, document.body); 

Это не делает слишком много смысла в этом изолированном примере, но если предположить, что кто-то использует MyComponent и что они дают ему обратный вызов OnChange, то это хорошо работает. Вы получаете преимущества встроенного управления вводом, но все же возвращаете (через обратный вызов) номер как фактический поплавок.

0

А как насчет написания небольшого компонента, который будет обрабатывать строковые значения и передавать только легальные значения поплавка слушателям?

class NumberInput extends React.Component<{ onChange: (n: number) => void, value: number }, { value: number }> { 

    constructor(props: { onChange: ((n: number) => void); value: number }, context: any) { 
    super(props, context); 
    this.state = { 
     value: props.value || 0 
    }; 
    } 

    handleInputChange = (e) => { 
    const value = e.target.value; 
    this.setState({ 
     value: value 
    }); 
    if (this.props.onChange) { 
     const floatValue = parseFloat(value); 
     if (!isNaN(floatValue)) { 
     this.props.onChange(floatValue) 
     } 
    } 
    }; 

    componentWillReceiveProps(newProps) { 
    this.setState({ 
     value: newProps.value 
    }) 
    } 

    render() { 
    return (
     <Input step="0.1" value={this.state.value} onChange={this.handleInputChange} type="number"/> 
    ) 
    } 
} 
Смежные вопросы