2014-12-23 45 views
3

我有以下反應組分:陣營組件和無效的輸入

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"/> 
    ) 
    } 
}