javascript - library - ¿Cómo validar correctamente los valores de entrada con React.JS?
valid input react (6)
Hace poco pasé una semana estudiando muchas soluciones para validar mis formularios en una aplicación. Comencé con todo lo que tenía más fijo, pero no pude encontrar uno que funcionara como se esperaba. Después de unos días, me sentí bastante frustrado hasta que encontré un plugin nuevo e increíble: https://github.com/kettanaito/react-advanced-form
El desarrollador es muy receptivo y su solución, después de mi investigación, merece ser la más vista desde mi perspectiva. Espero que pueda ayudar y lo apreciarás.
Tengo una forma simple. Todos los componentes y el estado se mantienen en el componente Página. Hay 2 encabezados de visualización y 3 campos de entrada. La primera entrada se supone que es texto, y la segunda y tercera son supuestas. Cuando el usuario ingresa el tipo de datos incorrecto, quiero que aparezca un mensaje de error al lado del campo de entrada. Mis preguntas se relacionan con las mejores prácticas en React.JS
¿Quién decide que el valor es válido? Supongo que el único trabajo del campo de entrada es dirigir el valor de vuelta al componente que contiene el estado, ¿significa esto que solo Page puede determinar si un valor es válido?
¿Cómo debo hacer que aparezca la ventana emergente? ¿Debería Page tener que desencadenar un nuevo elemento de estado booleano que pasará por el perp que le dirá a Adaptive_Input que revele el mensaje de error?
JS:
/**
* @jsx React.DOM
*/
var Adaptive_Input = React.createClass({
handle_change: function(){
var new_text = this.refs.input.getDOMNode().value;
this.props.on_Input_Change(new_text);
},
render: function(){
return (
<div className=''adaptive_placeholder_input_container''>
<input
className="adaptive_input"
type="text"
required="required"
onChange= {this.handle_change}
ref="input"
></input>
<label
className="adaptive_placeholder"
alt={this.props.initial}
placeholder={this.props.focused}
></label>
</div>
);
}
});
var Form = React.createClass({
render: function(){
return (
<form>
<Adaptive_Input
initial={''Name Input''}
focused={''Name Input''}
on_Input_Change={this.props.handle_text_input}
/>
<Adaptive_Input
initial={''Value 1''}
focused={''Value 1''}
on_Input_Change={this.props.handle_value_1_input}
/>
<Adaptive_Input
initial={''Value 2''}
focused={''Value 2''}
on_Input_Change={this.props.handle_value_2_input}
/>
</form>
);
}
});
var Page = React.createClass({
getInitialState: function(){
return {
Name : "No Name",
Value_1 : ''0'',
Value_2 : ''0'',
Display_Value: ''0''
};
},
handle_text_input: function(new_text){
this.setState({
Name: new_text
});
},
handle_value_1_input: function(new_value){
console.log("===");
var updated_display = parseInt(new_value) + parseInt(this.state.Value_2);
updated_display = updated_display.toString();
this.setState({
Display_Value: updated_display
});
},
handle_value_2_input: function(new_value){
var updated_display = parseInt(this.state.Value_1) + parseInt(new_value);
updated_display = updated_display.toString();
this.setState({
Display_Value: updated_display
});
},
render: function(){
return(
<div>
<h2>{this.state.Name}</h2>
<h2>Value 1 + Value 2 = {this.state.Display_Value}</h2>
<Form
handle_text_input={this.handle_text_input}
handle_value_1_input = {this.handle_value_1_input}
handle_value_2_input = {this.handle_value_2_input}
/>
</div>
);
}
});
React.renderComponent(<Page />, document.body);
He escrito Esta biblioteca, que le permite ajustar los componentes de su elemento de formulario, y le permite definir sus validadores en el formato: -
<Validation group="myGroup1"
validators={[
{
validator: (val) => !validator.isEmpty(val),
errorMessage: "Cannot be left empty"
},...
}]}>
<TextField value={this.state.value}
className={styles.inputStyles}
onChange={
(evt)=>{
console.log("you have typed: ", evt.target.value);
}
}/>
</Validation>
Primero, aquí hay un ejemplo de lo que mencionaré a continuación: http://jsbin.com/rixido/2/edit
¿Cómo validar correctamente los valores de entrada con React.JS?
Como tú quieras. React es para renderizar un modelo de datos. El modelo de datos debe saber qué es válido o no. Puede usar modelos Backbone, datos JSON o cualquier otra cosa que desee para representar los datos y su estado de error.
Más específicamente:
Reaccionar es generalmente agnóstico hacia sus datos. Es para renderizar y lidiar con eventos.
Las reglas a seguir son:
- los elementos pueden cambiar su estado.
- no pueden cambiar los accesorios.
- pueden invocar una devolución de llamada que cambiará los accesorios de nivel superior.
¿Cómo decidir si algo debe ser un apoyo o un estado? Considere esto: ¿CUALQUIER parte de su aplicación que no sea el campo de texto quiere saber que el valor ingresado es malo? Si no, conviértalo en un estado. Si es así, debería ser un apoyo.
Por ejemplo, si desea una vista separada para procesar "Tiene 2 errores en esta página". entonces su error debería ser conocido por un modelo de datos de nivel superior.
¿Dónde debería vivir ese error?
Si su aplicación estaba representando modelos Backbone (por ejemplo), el modelo en sí tendría un método validate () y una propiedad validateError que podría usar. Podría renderizar otros objetos inteligentes que podrían hacer lo mismo. React también dice que trate de mantener los accesorios al mínimo y genere el resto de los datos. por lo tanto, si tuviera un validador (por ejemplo, https://github.com/flatiron/revalidator ), sus validaciones podrían gotear y cualquier componente podría verificar los accesorios con su validación coincidente para ver si son válidos.
En gran medida depende de ti.
( Personalmente estoy usando modelos Backbone y los renderizo en React. Tengo una alerta de error toplevel que muestro si hay un error en alguna parte, describiendo el error).
Puede usar npm install --save redux-form
Estoy escribiendo un formulario simple de correo electrónico y botón de enviar, que valida el correo electrónico y envía el formulario. con formato redux, la forma predeterminada ejecuta event.preventDefault () en la acción html onSubmit.
import React, {Component} from ''react'';
import {reduxForm} from ''redux-form'';
class LoginForm extends Component {
onSubmit(props) {
//do your submit stuff
}
render() {
const {fields: {email}, handleSubmit} = this.props;
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<input type="text" placeholder="Email"
className={`form-control ${email.touched && email.invalid ? ''has-error'' : '''' }`}
{...email}
/>
<span className="text-help">
{email.touched ? email.error : ''''}
</span>
<input type="submit"/>
</form>
);
}
}
function validation(values) {
const errors = {};
const emailPattern = /(.+)@(.+){2,}/.(.+){2,}/;
if (!emailPattern.test(values.email)) {
errors.email = ''Enter a valid email'';
}
return errors;
}
LoginForm = reduxForm({
form: ''LoginForm'',
fields: [''email''],
validate: validation
}, null, null)(LoginForm);
export default LoginForm;
Tu jsfiddle ya no funciona. Lo arreglé: http://jsfiddle.net/tkrotoff/bgC6E/40/ usando las clases de React 16 y ES6.
class Adaptive_Input extends React.Component {
handle_change(e) {
var new_text = e.currentTarget.value;
this.props.on_Input_Change(new_text);
}
render() {
return (
<div className="adaptive_placeholder_input_container">
<input
className="adaptive_input"
type="text"
required="required"
onChange={this.handle_change.bind(this)} />
<label
className="adaptive_placeholder"
alt={this.props.initial}
placeholder={this.props.focused} />
</div>
);
}
}
class Form extends React.Component {
render() {
return (
<form>
<Adaptive_Input
initial={''Name Input''}
focused={''Name Input''}
on_Input_Change={this.props.handle_text_input} />
<Adaptive_Input
initial={''Value 1''}
focused={''Value 1''}
on_Input_Change={this.props.handle_value_1_input} />
<Adaptive_Input
initial={''Value 2''}
focused={''Value 2''}
on_Input_Change={this.props.handle_value_2_input} />
</form>
);
}
}
class Page extends React.Component {
constructor(props) {
super(props);
this.state = {
Name: ''No Name'',
Value_1: ''0'',
Value_2: ''0'',
Display_Value: ''0''
};
}
handle_text_input(new_text) {
this.setState({
Name: new_text
});
}
handle_value_1_input(new_value) {
new_value = parseInt(new_value);
var updated_display = new_value + parseInt(this.state.Value_2);
updated_display = updated_display.toString();
this.setState({
Value_1: new_value,
Display_Value: updated_display
});
}
handle_value_2_input(new_value) {
new_value = parseInt(new_value);
var updated_display = parseInt(this.state.Value_1) + new_value;
updated_display = updated_display.toString();
this.setState({
Value_2: new_value,
Display_Value: updated_display
});
}
render() {
return(
<div>
<h2>{this.state.Name}</h2>
<h2>Value 1 + Value 2 = {this.state.Display_Value}</h2>
<Form
handle_text_input={this.handle_text_input.bind(this)}
handle_value_1_input={this.handle_value_1_input.bind(this)}
handle_value_2_input={this.handle_value_2_input.bind(this)}
/>
</div>
);
}
}
ReactDOM.render(<Page />, document.getElementById(''app''));
Y ahora el mismo código hackeado con la validación de formularios gracias a esta biblioteca: https://github.com/tkrotoff/react-form-with-constraints => http://jsfiddle.net/tkrotoff/k4qa4heg/
const { FormWithConstraints, FieldFeedbacks, FieldFeedback } = ReactFormWithConstraints;
class Adaptive_Input extends React.Component {
static contextTypes = {
form: PropTypes.object.isRequired
};
constructor(props) {
super(props);
this.state = {
field: undefined
};
this.fieldWillValidate = this.fieldWillValidate.bind(this);
this.fieldDidValidate = this.fieldDidValidate.bind(this);
}
componentWillMount() {
this.context.form.addFieldWillValidateEventListener(this.fieldWillValidate);
this.context.form.addFieldDidValidateEventListener(this.fieldDidValidate);
}
componentWillUnmount() {
this.context.form.removeFieldWillValidateEventListener(this.fieldWillValidate);
this.context.form.removeFieldDidValidateEventListener(this.fieldDidValidate);
}
fieldWillValidate(fieldName) {
if (fieldName === this.props.name) this.setState({field: undefined});
}
fieldDidValidate(field) {
if (field.name === this.props.name) this.setState({field});
}
handle_change(e) {
var new_text = e.currentTarget.value;
this.props.on_Input_Change(e, new_text);
}
render() {
const { field } = this.state;
let className = ''adaptive_placeholder_input_container'';
if (field !== undefined) {
if (field.hasErrors()) className += '' error'';
if (field.hasWarnings()) className += '' warning'';
}
return (
<div className={className}>
<input
type={this.props.type}
name={this.props.name}
className="adaptive_input"
required
onChange={this.handle_change.bind(this)} />
<label
className="adaptive_placeholder"
alt={this.props.initial}
placeholder={this.props.focused} />
</div>
);
}
}
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
Name: ''No Name'',
Value_1: ''0'',
Value_2: ''0'',
Display_Value: ''0''
};
}
handle_text_input(e, new_text) {
this.form.validateFields(e.currentTarget);
this.setState({
Name: new_text
});
}
handle_value_1_input(e, new_value) {
this.form.validateFields(e.currentTarget);
if (this.form.isValid()) {
new_value = parseInt(new_value);
var updated_display = new_value + parseInt(this.state.Value_2);
updated_display = updated_display.toString();
this.setState({
Value_1: new_value,
Display_Value: updated_display
});
}
else {
this.setState({
Display_Value: ''Error''
});
}
}
handle_value_2_input(e, new_value) {
this.form.validateFields(e.currentTarget);
if (this.form.isValid()) {
new_value = parseInt(new_value);
var updated_display = parseInt(this.state.Value_1) + new_value;
updated_display = updated_display.toString();
this.setState({
Value_2: new_value,
Display_Value: updated_display
});
}
else {
this.setState({
Display_Value: ''Error''
});
}
}
render() {
return(
<div>
<h2>Name: {this.state.Name}</h2>
<h2>Value 1 + Value 2 = {this.state.Display_Value}</h2>
<FormWithConstraints ref={form => this.form = form} noValidate>
<Adaptive_Input
type="text"
name="name_input"
initial={''Name Input''}
focused={''Name Input''}
on_Input_Change={this.handle_text_input.bind(this)} />
<FieldFeedbacks for="name_input">
<FieldFeedback when="*" error />
<FieldFeedback when={value => !/^/w+$/.test(value)} warning>Should only contain alphanumeric characters</FieldFeedback>
</FieldFeedbacks>
<Adaptive_Input
type="number"
name="value_1_input"
initial={''Value 1''}
focused={''Value 1''}
on_Input_Change={this.handle_value_1_input.bind(this)} />
<FieldFeedbacks for="value_1_input">
<FieldFeedback when="*" />
</FieldFeedbacks>
<Adaptive_Input
type="number"
name="value_2_input"
initial={''Value 2''}
focused={''Value 2''}
on_Input_Change={this.handle_value_2_input.bind(this)} />
<FieldFeedbacks for="value_2_input">
<FieldFeedback when="*" />
</FieldFeedbacks>
</FormWithConstraints>
</div>
);
}
}
ReactDOM.render(<Form />, document.getElementById(''app''));
La solución propuesta aquí es hackosa ya que he tratado de mantenerla cerca del jsfiddle original. Para la validación adecuada de formulario con reaccionar-forma-con-restricciones, compruebe https://github.com/tkrotoff/react-form-with-constraints#examples
otro más va en el mismo problema - form-container
en npm