variable valor una obtener number los guardar formularios formulario elementos crear acceder forms reactjs jsonschema

forms - una - Los campos de formulario pierden el foco cuando cambia el valor de entrada



obtener valor de un input php (3)

Estoy tratando de construir un formulario con campos condicionales a partir de un esquema JSON usando react-jsonschema-form y react-jsonschem-form-conditionals .

Los componentes que estoy representando son un FormWithConditionals y un FormModelInspector . Este último es un componente muy simple que muestra el modelo de formulario.

El código fuente relevante es:

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: [] };

Sin embargo, cada vez que cambio el valor de un campo, el campo pierde el foco. Sospecho que la causa del problema es algo en la biblioteca react-jsonschema-form-conditionals , porque si reemplazo <FormWithConditionals> por <Form> , el problema no ocurre.

Si onChange={this.handleFormDataChange} el controlador onChange={this.handleFormDataChange} el campo de entrada ya no pierde el foco cuando cambia su valor (pero al eliminar este controlador se rompe el FormModelInspector ).

Aparte

En el código anterior, si quito el controlador onChange={this.handleFormDataChange} , el <FormModelInspector> no se actualiza cuando los datos del formulario cambian. No entiendo por qué este controlador es necesario porque al <FormModelInspector> se le pasa una referencia a los datos del formulario a través del atributo formData . ¿Quizás es porque cada cambio en los datos del formulario hace que se construya un nuevo objeto, en lugar de una modificación del mismo objeto?


¿Ha intentado declarar la function FormModelInspector como una función de flecha:

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> )


El problema es bastante sencillo, está creando un componente FormWithConditionals en su método de procesamiento y en su controlador setState usted establece el setState que activa un nuevo procesamiento y, por lo tanto, se crea una nueva instancia de FormWithConditionals y, por lo tanto, pierde el enfoque. Debe mover esta instancia fuera del método de procesamiento y quizás fuera del componente en sí mismo, ya que utiliza valores estáticos.

A medida que el schema , uiSchema y las rules se pasan como props al ConditionalForm , puede crear una instancia de FormWithConditionals en la función de constructor y usarla en un render como este.

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: [] };


Para cualquier persona que se tope con el mismo problema pero que usa Hooks, aquí hay cómo sin una clase:

Simplemente use una variable declarada fuera del componente e useEffect dentro de useEffect . (no olvide pasar [] como segundo parámetro para indicar que no dependemos de ninguna variable, replicando el efecto componentWillMount )

// import ... import Engine from ''json-rules-engine-simplified'' import Form from ''react-jsonschema-form'' let FormWithConditionals = () => null const MyComponent = (props) => { const { formData, schema, uischema, rules, } = props; useEffect(() => { FormWithConditionals = applyRules(schema, uischema, rules, Engine)(Form) }, []) return ( <FormWithConditionals> <div></div> </FormWithConditionals> ); } export default MyComponent