Javascript form-validation framework: Request for Review

前端 未结 2 947
离开以前
离开以前 2021-02-02 16:06

I wasn\'t sure if I could ask this kind of question, but after seeing this on Meta Stackoverflow, it looks like this kind of question is ok. Well, onto my question:

A fe

2条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-02-02 17:02

    I'm doing completely different approach: With modern framework like React or Angular you have always state of form somewhere in javascript not in DOM input states (DOM is just view layer of data). And I think it should be like this because no matter what kind of fancy components you use to build you form there is always underneath object that holds all states. From this point to me natural approach is to just use raw JSR-303 (without annotations) to validate this object (because JSR-303 provides you such flexibility) and populate errors back to DOM. Let me show you an example:

    import React, { Component } from "react";
    import ReactDOM from "react-dom";
    
    import validator, {
      Collection,
      All,
      Required,
      Optional,
      NotBlank,
      Length,
      Email
    } from "@stopsopa/validator";
    
    class App extends Component {
      constructor(...args) {
        super(...args);
        this.state = {
          data: {
            name: "",
            email: "",
            comments: []
          },
          errors: {},
          validate: false
        };
      }
      onSubmit = async e => {
        e.preventDefault();
    
        const errors = await validator(
          this.state.data,
          new Collection({
            name: new Required([new NotBlank(), new Length({ min: 3 })]),
            email: new Required([new NotBlank(), new Email()]),
            comments: new All([new NotBlank(), new Length({ min: 10 })])
          })
        );
        this.setState({
          errors: errors.getTree(),
          validate: true
        });
    
        if (!errors.count()) {
          console.log("send data to server", this.state.data);
        }
      };
      onChange = (name, value) => {
        console.log(name, value);
        this.setState(state => ({
          ...state,
          data: { ...state.data, ...{ [name]: value } }
        }));
      };
      addComment = () =>
        this.setState(state => {
          const comments = state.data.comments;
          comments.push("");
          const newState = { ...state };
          newState.data.comments = comments;
          return newState;
        });
      deleteComment = i =>
        this.setState(state => {
          const newState = { ...state };
          state.data.comments.splice(i, 1);
          return newState;
        });
      editComment = (i, value) => {
        this.setState(state => {
          const newState = { ...state };
          state.data.comments[i] = value;
          return newState;
        });
      };
      render() {
        const s = this.state;
        console.log("state", JSON.stringify(s, null, 4));
        return (
          
    {s.validate && s.errors.name && (
    {s.errors.name}
    )}
    {s.validate && s.errors.email && (
    {s.errors.email}
    )}
    comments:{" "} add {s.data.comments.map((m, i) => (