Tcomb-form-native: Formvalidation not working

Created on 15 Apr 2016  路  13Comments  路  Source: gcanti/tcomb-form-native

Version

Tell us which versions you are using:

  • tcomb-form-native master-branch
  • react-native v0.23.1

Expected behaviour

Error message that field is empty

Actual behaviour

RegisterDetails.js page opens without validating the form of Register.js. There are no error messages

Steps to reproduce

I splitted the Form and started creating a FormLoader.

this is my FormLoader.js

export default class FormLoader extends React.Component {
    propTypes : {
        formType: PropTypes.string,
        form: PropTypes.object,
        style: Form.propType.style,
        value: PropTypes.object,
        onChange: PropTypes.func
    };

    render() {


        let options = {
            auto: 'none',
            fields: {},
            state: '',

        };

        let usernameOpt = {
            placeholder: 'Username',
            hasError: false,
            error: 'Please enter a Username'
        };

        let passwordOpt = {
            placeholder: 'Passwort',
            password: true,
            hasError: false,
            error: 'Please enter Password'
        };

        var max3 = s => s.length <= 3;
        var username = t.refinement(t.String, s=> max3(s));

        username.getValidationErrorMessage = s => {
            if(!s){
                return 'We need a name to proceed!';
            }
            if(!max3(s)){
                return 'test test test';
            }
        };

        let formType = this.props.formType;
        switch (formType) {
            case(REGISTER):
                formLoader = t.struct({
                    username: username,
                    password: t.String,
                });
                options.fields['username'] = usernameOpt;
                options.fields['password'] = passwordOpt;
                break;
        }

        return (
            <Form ref="form"
                  type={formLoader}
                  options={options}
                  value={this.props.value}
                  onChange={this.props.onChange}
                  isValid={true}
            />
        );
    }
}

and this is my Register.js

...
import {Actions} from "react-native-router-flux";
import FormLoader from "../../lib/FormLoader";
...

export default class Register extends React.Component {
    constructor() {
        super();
        this.onChange = this.onChange.bind(this);
        this.state = {
            user: {}
        }
    }

    _continueRegistration() {
        Actions.registerDetails(value);
    }

    onChange(value) {
        this.state.user = value;
    }

    render() {
        return (
            <View style={styles.container}>
                <View style={styles.input}>
                    <FormLoader ref="form"
                                formType={REGISTER}
                                value={this.state.user}
                                onChange={this.onChange}
                    />
                    <Button onPress={this._continueRegistration.bind(this)}>Continue</Button>
                </View>
            </View>
        );
    }
}

I would be happy if anyone can help me here...

All 13 comments

In order to validate the fields, you must call the getValue (or the validate) method:

https://github.com/gcanti/tcomb-form-native#example

calling getValue throws an exception: this.refs.form.getValue is not a function

Because you have nested components I guess, getValue is defined in the inner t.form.Form component

this is very strange... I have to do this.refs.form.refs.form.validate() to call the method.

Thank you very much!

That's usual, you have your Form wrapped into a component. You can define getValue function inside your form component if you want, and you'll not need to access extra form node.

Okay and how can I do this?

Inside FormLoader:

...
getValue () {
  return this.refs.form.getValue()
}
...

Thank you very much!

How could I add a repeat password validate in this case here?

With a custom refinement

const PasswordMinLength = t.refinement(t.String, value => {
  return value.length > 6
})
// Validate repeat password
const ConfirmPasswordEquality = t.refinement(t.String, value => {
  return value === this.state.value.password
})

const Form = t.struct({
  password: PasswordMinLength,
  confirm_password: ConfirmPasswordEquality,
})

Remember to save your Form state into the value object.

@alvaromb FormType may or may not be state aware. I feel like the right way to do this is to use context. in the refinement. cc @gcanti

@alvaromb in the example you have shown, how are you accessing this.state.value.password in ConfirmPasswordEquality?

hey.. am assiging a class component to template.. however its not working

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sibelius picture sibelius  路  5Comments

dvlprmartins picture dvlprmartins  路  4Comments

abdelghafourzguindou picture abdelghafourzguindou  路  4Comments

scarlac picture scarlac  路  4Comments

abdelghafourzguindou picture abdelghafourzguindou  路  4Comments