Реагировать: копировать значения из одного поля ввода в другое при установке флажка

У меня есть форма, в которой у меня есть две группы полей адреса (представьте, что это адрес доставки и адрес выставления счета). Я хочу предложить пользователю возможность копировать значения из одной группы в другую при установке флажка «Платежный адрес совпадает с адресом доставки».

My code looks as follows:

class PetitionForm extends React.Component {
    render() {
        return (
            <Form 
                onValidSubmit={this._handleValidSubmit.bind(this)}
                onInvalidSubmit={this._handleInvalidSubmit.bind(this)}>
                <div className="panel panel-default">
                    <div className="panel-heading">
                        <h2 className="panel-title">Shipping Address</h2>
                    </div>
                    <div className="panel-body">
                        <ValidatedInput name="streetShip" type="text" label="Street" validate="required" errorHelp="Needs to be completed" groupClassName="col-sm-12"/>
                        <ValidatedInput name="zipShip" type="number" label="ZIP Code" validate="required" errorHelp="Needs to be completed" groupClassName="col-xs-4"/>
                        <ValidatedInput name="cityShip" type="text" label="City" validate="required" errorHelp="Needs to be completed" groupClassName="col-xs-8"/>
                    </div>
                </div>
                <div className="panel panel-default">
                    <div className="panel-heading">
                        <h2 className="panel-title">Billing Address</h2>
                    </div>
                    <div className="panel-body">
                        <Input type="checkbox" ref="checkbox" name="sameCheck" label="Shipping address is billing address" onChange={this._copyAddress} />
                        <ValidatedInput name="streetBill" type="text" label="Street" validate="required" errorHelp="Needs to be completed" groupClassName="col-sm-12" />
                        <ValidatedInput name="zipBill" type="number" label="ZIP Code" validate="required" errorHelp="Needs to be completed" groupClassName="col-xs-4"/>
                        <ValidatedInput name="cityBill" type="text" label="Ciudad" validate="required" errorHelp="Needs to be completed" groupClassName="col-xs-8"/>
                    </div>
                </div>
                <ButtonInput type="submit" groupClassName="col-sm-12" />
            </Form>
        );
    }

    _copyAddress() {
        this.refs.checkbox.getValue();
    }

    _handleValidSubmit(values) {
      // handle submit
    }

    _handleInvalidSubmit(errors, values) {
      // handle invalids
    }
}

onChange={this._copyAddress} — это моя отчаянная попытка зафиксировать, когда флажок установлен. copyAddress запускается, но this.refs.checkbox не определено.

Даже если бы это сработало, как бы я получил значения из верхней группы форм?

Спасибо за вашу помощь!

- Hg


person hko    schedule 26.01.2016    source источник
comment
почему бы тебе не использовать e.target из _copyAddress(e)? (И ваша орфография отключена :/   -  person ryan0319    schedule 26.01.2016
comment
Спасибо, переименовал функции при создании фрагмента, так что, к счастью, проблема была не в этом. e.target.checked делает свое дело, но я выяснил, что вызвало this.refs.checkbox is undefined — должно быть onChange={this._copyAddress}.bind(this) Теперь я все еще не понимаю, как копировать значения. :-(   -  person hko    schedule 26.01.2016
comment
facebook.github.io/react/docs/component-specs.html Используйте жизненные циклы. Затем используйте состояние, чтобы передать значения форме.   -  person ryan0319    schedule 26.01.2016
comment
Государства решили это — спасибо! Ответ смотрите ниже, я ценю любые отзывы о коде.   -  person hko    schedule 27.01.2016


Ответы (1)


Некоторые из моих первоначальных проблем можно решить, привязав this к вызову onChange:

onChange={this._copyAddress.bind(this)}

Таким образом, я смог получить доступ к this.refs.checkbox.

Для копирования значений мне сначала пришлось привязать значения к состоянию компонента, превратив их в управляемые компоненты (см. https://facebook.github.io/react/docs/forms.html).

Это означало установку состояния следующим образом (я использую классы ES6):

class PetitionForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            values: {
                firstName: "",
                lastName: "",
                email: "",
                streetShip: "",
                zipShip: "",
                cityShip: "",
                streetBill: "",
                zipBill: "",
                cityBill: ""
            }
        };
    }
...
}

Теперь для каждого из входов мы должны добавить свойство-значение: value={this.state.values.firstName}

Теперь, если мы оставим все как есть, пользователь не сможет вносить какие-либо изменения в форму, поэтому мы должны связать свойство onChange с функцией handleChange. Поскольку я не хотел писать 9 разных обработчиков для 9 полей, это был мой ярлык:

handleChange(e) {
    var key = e.target.name;
    var obj = {};
    obj[key] = e.target.value;
    var updatedValues = Object.assign({}, this.state.values, obj);
    this.setState({values: updatedValues});
}

target.name эквивалентен ключу, который мы использовали для установки значений состояния. e.target.value фиксирует пользовательский ввод. Object.assign используется, чтобы избежать непосредственного вмешательства в состояние (которое следует рассматривать как неизменяемое). Предоставляется отличное руководство по проблеме при манипулировании состоянием здесь

Копирование содержимого затем довольно просто:

_copyAddress(e) {
    if(this.refs.copyAddress.getChecked()) {
        var obj = {
                streetBill: this.state.values.streetShip,
                zipBill: this.state.values.zipShip,
                cityBill: this.state.values.cityShip
        }
        var updatedValues = Object.assign({}, this.state.values, obj);
        this.setState({values: updatedValues});
    }
}

Флажок, запускающий копирование и примерное поле ввода, теперь выглядит так:

<Input type="checkbox" name="copyAddress" ref="copyAddress" label="Same as shipping" onChange={this._copyAddress.bind(this)} />
<ValidatedInput name="streetBills" value={this.state.values.streetBills} onChange={this.handleChange.bind(this)} type="text" label="Street" ... />

Не уверен, насколько это «реагирует» — дайте мне знать, если у вас есть отзывы!

person hko    schedule 26.01.2016
comment
В чем причина использования подчеркивания для _copyAddress, но не для метода handleChange? - person A7DC; 07.12.2018