Próbuję utworzyć prosty formularz z funkcją reagowania, ale mam trudności z prawidłowym powiązaniem danych z wartością domyślną formularza.
Zachowanie, którego szukam, jest następujące:
- Kiedy otwieram moją stronę, pole tekstowe powinno być wypełnione tekstem mojej AwayMessage w mojej bazie danych. To jest „Przykładowy tekst”
- Idealnie byłoby, gdyby w polu wprowadzania tekstu znajdował się symbol zastępczy, jeśli komunikat AwayMessage w mojej bazie danych nie zawiera tekstu.
Jednak w tej chwili stwierdzam, że pole tekstowe jest puste za każdym razem, gdy odświeżam stronę. (Chociaż to, co wpisuję w danych wejściowych, jest zapisywane prawidłowo i utrwalane). Myślę, że dzieje się tak, ponieważ kod HTML pola wejściowego jest ładowany, gdy AwayMessage jest pustym obiektem, ale nie odświeża się, gdy ładuje się awayMessage. Nie mogę również określić wartości domyślnej dla tego pola.
Usunąłem część kodu dla przejrzystości (np. OnToggleChange)
window.Pages ||= {}
Pages.AwayMessages = React.createClass
getInitialState: ->
App.API.fetchAwayMessage (data) =>
@setState awayMessage:data.away_message
{awayMessage: {}}
onTextChange: (event) ->
console.log "VALUE", event.target.value
onSubmit: (e) ->
window.a = @
e.preventDefault()
awayMessage = {}
awayMessage["master_toggle"]=@refs["master_toggle"].getDOMNode().checked
console.log "value of text", @refs["text"].getDOMNode().value
awayMessage["text"]=@refs["text"].getDOMNode().value
@awayMessage(awayMessage)
awayMessage: (awayMessage)->
console.log "I'm saving", awayMessage
App.API.saveAwayMessage awayMessage, (data) =>
if data.status == 'ok'
App.modal.closeModal()
notificationActions.notify("Away Message saved.")
@setState awayMessage:awayMessage
render: ->
console.log "AWAY_MESSAGE", this.state.awayMessage
awayMessageText = if this.state.awayMessage then this.state.awayMessage.text else "Placeholder Text"
`<div className="away-messages">
<div className="header">
<h4>Away Messages</h4>
</div>
<div className="content">
<div className="input-group">
<label for="master_toggle">On?</label>
<input ref="master_toggle" type="checkbox" onChange={this.onToggleChange} defaultChecked={this.state.awayMessage.master_toggle} />
</div>
<div className="input-group">
<label for="text">Text</label>
<input ref="text" onChange={this.onTextChange} defaultValue={awayMessageText} />
</div>
</div>
<div className="footer">
<button className="button2" onClick={this.close}>Close</button>
<button className="button1" onClick={this.onSubmit}>Save</button>
</div>
</div>
Mój console.log dla AwayMessage zawiera następujące informacje:
AWAY_MESSAGE Object {}
AWAY_MESSAGE Object {id: 1, company_id: 1, text: "Sample Text", master_toggle: false}
źródło
Innym sposobem rozwiązania tego problemu jest zmiana
key
wejścia.<input ref="text" key={this.state.awayMessage ? 'notLoadedYet' : 'loaded'} onChange={this.onTextChange} defaultValue={awayMessageText} />
Aktualizacja: Ponieważ otrzymuję głosy upvotes, będę musiał powiedzieć, że powinieneś odpowiednio mieć
disabled
lubreadonly
prop podczas ładowania treści, więc nie zmniejszasz doświadczenia UX.I tak, to najprawdopodobniej hack, ale spełnia swoje zadanie .. ;-)
źródło
select
zkey
jakdefaultValue
co jest rzeczywiścievalue
.key
wejścia jest kluczem do uzyskania nowej wartości odzwierciedlonej na wejściu. Użyłem go ztype="text"
powodzeniem.Może nie jest to najlepsze rozwiązanie, ale zrobiłbym komponent taki jak poniżej, aby móc go ponownie wykorzystać w całym kodzie. Szkoda, że nie było już domyślnie w reakcji.
<MagicInput type="text" binding={[this, 'awayMessage.text']} />
Komponent może wyglądać następująco:
window.MagicInput = React.createClass onChange: (e) -> state = @props.binding[0].state changeByArray state, @path(), e.target.value @props.binding[0].setState state path: -> @props.binding[1].split('.') getValue: -> value = @props.binding[0].state path = @path() i = 0 while i < path.length value = value[path[i]] i++ value render: -> type = if @props.type then @props.type else 'input' parent_state = @props.binding[0] `<input type={type} onChange={this.onChange} value={this.getValue()} />`
Gdzie zmiana przez tablicę jest funkcją uzyskującą dostęp do skrótu za pomocą ścieżki wyrażonej przez tablicę
changeByArray = (hash, array, newValue, idx) -> idx = if _.isUndefined(idx) then 0 else idx if idx == array.length - 1 hash[array[idx]] = newValue else changeByArray hash[array[idx]], array, newValue, ++idx
źródło
Najbardziej niezawodnym sposobem ustawienia wartości początkowych jest użycie metody componentDidMount () {} oprócz renderowania () {}:
... componentDidMount(){ const {nameFirst, nameSecond, checkedStatus} = this.props; document.querySelector('.nameFirst').value = nameFirst; document.querySelector('.nameSecond').value = nameSecond; document.querySelector('.checkedStatus').checked = checkedStatus; return; } ...
Może się okazać, że łatwo będzie zniszczyć element i zastąpić go nowym z
<input defaultValue={this.props.name}/>
lubię to:
if(document.querySelector("#myParentElement")){ ReactDOM.unmountComponentAtNode(document.querySelector("#myParentElement")); ReactDOM.render( <MyComponent name={name} />, document.querySelector("#myParentElement") ); };
Możesz również użyć tej wersji metody odmontowania:
ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(this).parentNode);
źródło
Podaj wartość dla parametru „placeHolder”. Na przykład :-
<input type="text" placeHolder="Search product name." style={{border:'1px solid #c5c5c5', padding:font*0.005,cursor:'text'}} value={this.state.productSearchText} onChange={this.handleChangeProductSearchText} />
źródło