forms - 포커스 - 아이폰 input focus




입력 값이 변경되면 양식 입력란이 포커스를 잃습니다. (2)

문제는 매우 간단합니다. 렌더링 메서드에서 FormWithConditionals 구성 요소를 만들고 onChange 핸들러에서 setState 를 사용하여 다시 렌더링을 트리거하므로 FormWithConditionals 의 새 인스턴스가 만들어 지므로 포커스가 손실됩니다. 이 인스턴스를 렌더링 메서드 밖으로 이동해야하고 정적 값을 사용하기 때문에 구성 요소 자체 외부로 이동해야합니다.

schema , uiSchemarulesConditionalForm 소품으로 전달되므로 constructor 함수에서 FormWithConditionals 인스턴스를 생성하고이를 다음과 같이 렌더링에 사용할 수 있습니다

    import React from 'react';
    import PropTypes from 'prop-types';
    import Engine from "json-rules-engine-simplified";
    import Form from "react-jsonschema-form";
    import applyRules from "react-jsonschema-form-conditionals";

    function FormModelInspector (props) {

      return (
        <div>
          <div className="checkbox">
            <label>
              <input type="checkbox" onChange={props.onChange} checked={props.showModel}/>
              Show Form Model
            </label>
          </div>
          {
            props.showModel && <pre>{JSON.stringify(props.formData, null, 2)}</pre>
          }
        </div>
      )
    }


    class ConditionalForm extends React.Component {

      constructor (props) {
        super(props);
        this.state = {
          formData: {},
          showModel: true
        };
        const { schema, uiSchema, rules } = props;
        this.FormWithConditionals = applyRules(schema, uiSchema, rules, Engine)(Form);
        this.handleFormDataChange = this.handleFormDataChange.bind(this);
        this.handleShowModelChange = this.handleShowModelChange.bind(this);
      }

      handleShowModelChange (event) {
        this.setState({showModel: event.target.checked});
      }

      handleFormDataChange ({formData}) {
        this.setState({formData});
      }

      render () {
        const FormWithConditionals = this.FormWithConditionals;
        return (
          <div className="row">
            <div className="col-md-6">
              <FormWithConditionals schema={schema}
                    uiSchema={uiSchema}
                    formData={this.state.formData}
                    onChange={this.handleFormDataChange}
                    noHtml5Validate={true}>
              </FormWithConditionals>
            </div>
            <div className="col-md-6">
              <FormModelInspector formData={this.state.formData}
                                  showModel={this.state.showModel}
                                  onChange={this.handleShowModelChange}/>
            </div>
          </div>
        );
      }
    }

    ConditionalForm.propTypes = {
      schema: PropTypes.object.isRequired,
      uiSchema: PropTypes.object.isRequired,
      rules: PropTypes.array.isRequired
    };

    ConditionalForm.defaultProps = {
      uiSchema: {},
      rules: []
    };

나는 react-jsonschema-formreact-jsonschem-form-conditionals 사용하여 JSON 스키마로부터 조건부 필드를 가진 react-jsonschema-formreact-jsonschem-form-conditionals .

렌더링중인 구성 요소는 FormWithConditionalsFormModelInspector 입니다. 후자는 폼 모델을 보여주는 매우 간단한 구성 요소입니다.

관련 소스 코드는 다음과 같습니다.

import React from 'react';
import PropTypes from 'prop-types';
import Engine from "json-rules-engine-simplified";
import Form from "react-jsonschema-form";
import applyRules from "react-jsonschema-form-conditionals";

function FormModelInspector (props) {

  return (
    <div>
      <div className="checkbox">
        <label>
          <input type="checkbox" onChange={props.onChange} checked={props.showModel}/>
          Show Form Model
        </label>
      </div>
      {
        props.showModel && <pre>{JSON.stringify(props.formData, null, 2)}</pre>
      }
    </div>
  )
}

class ConditionalForm extends React.Component {

  constructor (props) {
    super(props);
    this.state = {
      formData: {},
      showModel: true
    };
    this.handleFormDataChange = this.handleFormDataChange.bind(this);
    this.handleShowModelChange = this.handleShowModelChange.bind(this);
  }

  handleShowModelChange (event) {
    this.setState({showModel: event.target.checked});
  }

  handleFormDataChange ({formData}) {
    this.setState({formData});
  }

  render () {
    const schema = {
      type: "object",
      title: "User form",
      properties: {
        nameHider: {
          type: 'boolean',
          title: 'Hide name'
        },
        name: {
          type: 'string',
          title: 'Name'
        }
      }
    };

    const uiSchema = {};

    const rules = [{
      conditions: {
        nameHider: {is: true}
      },
      event: {
        type: "remove",
        params: {
          field: "name"
        }
      }
    }];

    const FormWithConditionals = applyRules(schema, uiSchema, rules, Engine)(Form);

    return (
      <div className="row">
        <div className="col-md-6">
          <FormWithConditionals schema={schema}
                uiSchema={uiSchema}
                formData={this.state.formData}
                onChange={this.handleFormDataChange}
                noHtml5Validate={true}>
          </FormWithConditionals>
        </div>
        <div className="col-md-6">
          <FormModelInspector formData={this.state.formData}
                              showModel={this.state.showModel}
                              onChange={this.handleShowModelChange}/>
        </div>
      </div>
    );
  }
}

ConditionalForm.propTypes = {
  schema: PropTypes.object.isRequired,
  uiSchema: PropTypes.object.isRequired,
  rules: PropTypes.array.isRequired
};

ConditionalForm.defaultProps = {
  uiSchema: {},
  rules: []
};

그러나 필드 값을 변경할 때마다 필드는 포커스를 잃습니다. 문제의 원인은 react-jsonschema-form-conditionals 라이브러리에있는 것으로 의심됩니다. <FormWithConditionals><Form> <FormWithConditionals> 문제가 발생하지 않기 때문입니다.

onChange={this.handleFormDataChange} 처리기를 제거하면 입력 필드가 값 변경시 더 이상 포커스를 잃지 않습니다 (단,이 핸들러를 제거하면 FormModelInspector ).

곁에

위 코드에서 onChange={this.handleFormDataChange} 처리기를 제거하면 양식 데이터가 변경 될 때 <FormModelInspector> 가 업데이트되지 않습니다. <FormModelInspector>formData 특성을 통해 양식 데이터에 대한 참조를 전달하기 때문에이 처리기가 필요한 이유를 formData . 아마도 폼 데이터를 변경할 때마다 동일한 객체를 수정하는 대신 새 객체가 만들어지기 때문입니다.


function FormModelInspector 화살표 func로 선언 해 보았습니다.

const FormModelInspector = props => (
    <div>
      <div className="checkbox">
        <label>
          <input type="checkbox" onChange={props.onChange} checked={props.showModel}/>
          Show Form Model
        </label>
      </div>
      {
        props.showModel && <pre>{JSON.stringify(props.formData, null, 2)}</pre>
      }
    </div>
  )




jsonschema