2015-01-21 8 views
7

Jestem w trochę dziwnej sytuacji, mam do czynienia z walutą w mojej aplikacji. Po stronie modelu zapisuję walutę jako centy przed wysłaniem na serwer, ponieważ nie chcę zajmować się dziesiętnymi punktami po stronie serwera. Jednak w widoku chcę wyświetlać normalną walutę, a nie centy.tłumaczenie centów i dolarów w html wejścia w React

Więc mam tego pola wprowadzania gdzie Biorę dane z dolarów i zmienić go centów:

<input name="balance" type="number" step="0.01" min="0" placeholder="Balance in cents" onChange={this.handleUpdate} value={this.props.user.balance/100)} /> 

A gdy istnieje zmiana wartości wejściowej, zmieniam ją z powrotem do centów przed wysłaniem upstream:

handleUpdate: function(e) { 

    var value = e.target.value; 

    // changing it back from cents to dollars 
    value = parseFloat(value) * 100; 

    // save back to the parent component managing the prop 
    this.props.onUserUpdate(value); 

} 

To stawia mnie w rodzaju impasu, nie ma dla mnie sposób, aby wprowadzić punkt dziesiętny „” Pozwól mi zademonstrować:

  1. 33 w polu tekstowym -> staje 3300 w państwie macierzystym -> wraca jako 33 w podporze Component - dobre

  2. 33.3 w polu tekstowym -> staje 3330 w państwie macierzystym -> wraca jako 33.3 w podporze Component - wszystkim dobry

  3. 33. w polu tekstowym -> staje 3300 w państwie macierzystym -> wraca jako 33 w podpory komponentu - to jest problem

Jak widać w przypadku # 3, gdy użytkownik najpierw wprowadza "." to nie tłumaczy z powrotem na tę samą liczbę z "."

Ponieważ jest to kontrolowane wejście, w zasadzie nie można pisać "."

Próbowałem za pomocą niekontrolowanego elementu z defaultValue, ale ilość prop nie jest gotowy czas składnik staje się więc to tylko pusty

http://jsfiddle.net/fpbhu1hs/

Odpowiedz

10

kontrolowane wejścia wykorzystujące wartości pochodzące mogą być tricksy - Jeśli muszą być w stanie wyświetlić nieprawidłowe lub w inny sposób dziwne dane wejściowe ...

  1. zawsze trzymać wejście na value w jego składnik własnego state

    <input value={this.state.value} onChange={this.handleUpdate} // rest as above... 
    
  2. czerpać początkowa value w getInitialState()

    getInitialState: function() { 
        return {value: this.props.user.balance/100} 
    } 
    
  3. wdrożyć componentWillReceiveProps(nextProps) wykryć, kiedy wartość podpory ulega zmianie od powyżej i ponownie uzyskać stat e wartość

    componentWillReceiveProps: function(nextProps) { 
        if (this.props.user.balance != nextProps.user.balance) { 
        this.setState({value: nextProps.user.balance/100}) 
        } 
    } 
    

Teraz, gdy użytkownik wpisze „33.”, przechowywanie ich wkład dosłownego korzystania setState(), a następnie zadzwonić do rodziców.

handleUpdate: function(e) { 
    var value = e.target.value 
    this.setState({value: value}) 
    this.props.onUserUpdate(parseFloat(value) * 100) 
} 

Jeżeli wartość rodzic przechodzi następnie z powrotem w dół do dziecka za pomocą rekwizytów nie uległa zmianie (3300 == 3300 w tym przypadku), a następnie componentWillReceiveProps() nie będzie nic.

fragment pracy:

<script src="http://fb.me/react-with-addons-0.12.2.js"></script> 
 
<script src="http://fb.me/JSXTransformer-0.12.2.js"></script> 
 
<div id="example"></div> 
 
<script type="text/jsx;harmony=true">void function() { 'use strict'; 
 

 
var Parent = React.createClass({ 
 
    getInitialState() { 
 
    return {cents: 3300} 
 
    }, 
 
    
 
    _changeValue() { 
 
    this.setState({cents: Math.round(Math.random() * 2000 + Math.random() * 2000)}) 
 
    }, 
 

 
    _onCentsChange(cents) { 
 
    this.setState({cents}) 
 
    }, 
 

 
    render() { 
 
    return <div> 
 
     <p><strong>Cents:</strong> {this.state.cents.toFixed(0)} <input type="button" onClick={this._changeValue} value="Change"/></p> 
 
     <Child cents={this.state.cents} onCentsChange={this._onCentsChange}/> 
 
    </div> 
 
    } 
 
}) 
 

 
var Child = React.createClass({ 
 
    getInitialState() { 
 
    return {dollars: this.props.cents/100} 
 
    }, 
 

 
    componentWillReceiveProps(nextProps) { 
 
    if (this.props.cents != nextProps.cents) { 
 
     this.setState({dollars: nextProps.cents/100}) 
 
    } 
 
    }, 
 

 
    _onChange(e) { 
 
    var dollars = e.target.value 
 
    this.setState({dollars}) 
 
    if (!isNaN(parseFloat(dollars)) && isFinite(dollars)) { 
 
     this.props.onCentsChange(parseFloat(dollars) * 100) 
 
    } 
 
    }, 
 

 
    render() { 
 
    return <div> 
 
     <input type="number" step="0.01" min="0" value={this.state.dollars} onChange={this._onChange}/> 
 
    </div> 
 
    } 
 
}) 
 

 
React.render(<Parent/>, document.querySelector('#example')) 
 

 
}()</script>

+0

Very nice! Thinking React wymaga pewnych korekt ... Dzięki! – Michael

+0

Twój przykład działa z React 0.14.0 https://jsfiddle.net/7h5o97wL/, ale nie działa React 15.4.2 https://jsfiddle.net/69z2wepo/73775/ –

+0

Oto mój problem https://github.com/facebook/react/issues/7253 –

0

Używam tego prostego rozwiązania do obsługi sterowanych wejść i wartości dziesiętnych.

  1. Utwórz dwa rekwizyty w swoim stanie, jeden do przechowywania wartości rzeczywistej, a drugi do przechowywania ciągu znaków.

    constructor(props) { 
        .... 
    
        this.state = { 
         myProperty: 1.42, 
         myPropertyString: '1.42' 
        } 
    } 
    
  2. Ustaw wartość wejściową do String jednej

    <input type="text" 
         onChange={this.handleUpdate} 
         value={this.state.myPropertyString}/> 
    
  3. W handleUpdate metoda aktualizacji obu zmiennych państwowe.

    handleUpdate(e) { 
        this.setState({ 
         myProperty: parseFloat(e.target.value), 
         myPropertyString: e.target.value 
        }); 
    } 
    
Powiązane problemy