Структура проверки формы Javascript: Запрос на проверку - PullRequest
14 голосов
/ 13 августа 2010

Я не был уверен, смогу ли я задать такой вопрос, но после просмотра этого на Meta Stackoverflow, похоже, что этот вопрос в порядке.Ну, на мой вопрос:

Несколько месяцев назад я написал платформу валидации в Javascript.Я знаю, что уже существуют рамки валидации, такие как jQuery Validation , но я хотел использовать другой подход к валидации.Современные подходы имеют дело с написанием кода Javascript для выполнения проверки элементов формы.Глядя на исходный код формы, не сразу видно, какая проверка происходит для каждого элемента.В некоторой степени это можно исправить с помощью CSS-классов, которые определяют различные виды проверки.Но я чувствовал, что даже это было ограничено, потому что вы не можете легко настроить поведение проверки (сообщения об ошибках и т. Д.).Я хотел сделать что-то вроде проверки на основе аннотаций в Java с использованием JSR-303 Bean Validation или Hibernate Validator .

Поскольку HTML5 позволяет добавлять пользовательские атрибуты вэлементы, я решил, что я мог бы использовать это, чтобы «аннотировать» элементы формы для проверки.Итак, по сути, я придумал следующее:

<input id = "myInput"
       name = "myInput"
       type = "text"
       class = "regula-validation"
       data-constraints = '@NotEmpty @IsNumeric @Between(min=1, max=5)' />

Имея в виду эту основную идею, я создал инфраструктуру Javascript, которая:

  • Исследует DOM для элементов, имеющих ограниченияОпределяет и связывает эти ограничения с элементами
  • Позволяет создавать пользовательские ограничения
  • Позволяет программно связывать ограничения
  • Проверяет связанные ограничения

ВКроме того, платформа имеет следующие функции:

  • Группы проверки, аналогичные указанным в JSR-303
  • Интерполяция для сообщений об ошибках

Однажды ясоздал мою структуру, я пытался получить отзыв и отзыв для него, но я не был уверен, куда идти, чтобы получить отзыв и обзор.Я написал об этом несколько постов в блоге и без особой удачи разместил их в Digg и Reddit (раздел программирования).Некоторым людям это показалось интересным, но я не получил ничего большего.

Недавно на моем рабочем месте мы модернизировали устаревшую кодовую базу (JSP и сервлеты) и перенесли ее в Spring MVC.Когда начался разговор о валидации, я передал свои рамки своему старшему архитектору.Я сделал небольшую интеграцию и проверку концепции, и они, казалось, заинтересовались и дали мне добро, чтобы добавить его в проект.До сих пор у меня было только мое собственное скромное мнение, что это был бы полезный способ проверки, так что это дало мне некоторую уверенность в том, что моя идея и структура могут иметь некоторые достоинства.Однако мне все еще нужно было больше участия и рамок.После того, как я выяснил, что Stackoverflow разрешает подобные вопросы, я решил опубликовать его здесь, чтобы получить конструктивную критику, комментарии и отзывы.

Так что без дальнейших задержек я хотел бы представить Регул .Ссылка, которую я предоставил, ведет на вики на GitHub, где есть вся документация для фреймворка.Вы можете скачать последнюю версию (v1.1.0) с здесь .

Ждем ваших комментариев.

Некоторая дополнительная информация, которая не имеет непосредственного отношения

Мне пришла в голову идея интеграции моей платформы с Spring, то есть перевод аннотаций проверки на bean-компоненты в проверку на стороне клиента.Недавно мне удалось заставить это работать, даже с группами проверки (хотя в настоящее время нет поддержки отношений наследования между группами на стороне клиента).Таким образом, вам просто нужно аннотировать свойства поля с помощью ограничений проверки, и код проверки на стороне клиента генерируется автоматически.Тем не менее, я новичок в Spring, и поэтому мой метод, вероятно, не так уж и чист.Я хотел бы также получить некоторую обратную связь по этому вопросу, поэтому, если кто-то заинтересован, пожалуйста, дайте мне знать.В идеале (и я надеюсь, что я не слишком претенциозен), я хотел бы связаться с людьми из Spring и посмотреть, заинтересованы ли они в этом.

Ответы [ 2 ]

7 голосов
/ 14 августа 2010

Мне это уже очень нравится, он поддерживает мой HTML в чистоте, а возможность создавать собственные валидаторы великолепна. Одна вещь, которую я добавил, была короткой рукой для привязки функций проверки и отправки, и обернула это как плагин jQuery:

if (jQuery) {
    (function($)
    {
        $.regula = function(formId, callback) 
        {
            regula.bind();

            $("#" + formId).submit(function() 
            {
                var validationResults = regula.validate();

                if (validationResults.length > 0)
                {
                    if (callback)
                        callback(validationResults);

                    return false;
                }

                return true;
            });
        };
    })(jQuery);
}

Infact, я только что написал в блоге об этом, поскольку я впечатлен тем, насколько он чист и прост. Я все еще собираюсь провести время, изучая ваш источник, чтобы увидеть, как вы достигли этого, но это отличное начало:)

Что касается интеграции вашей среды, я работаю в основном с ASP.NET MVC, и было бы интересно посмотреть, как она преобразует логику проверки на стороне сервера в ограничения на стороне клиента. Что-то, что я мог бы просмотреть в следующем месяце или около того.

0 голосов
/ 05 декабря 2018

Я делаю совершенно другой подход: в современных средах, таких как React или Angular, у вас всегда есть состояние формы где-то в javascript, а не во входных состояниях DOM (DOM - это просто слой данных).И я думаю, что так должно быть, потому что независимо от того, какие модные компоненты вы используете для создания своей формы, всегда есть под объектом, который содержит все состояния.С этой точки зрения для меня естественным подходом является просто использование необработанного JSR-303 (без аннотаций) для проверки этого объекта (поскольку JSR-303 обеспечивает такую ​​гибкость) и заполнения ошибок обратно в DOM.Позвольте мне показать вам пример:

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 (
      <form onSubmit={this.onSubmit}>
        <label>
          name:
          <input
            value={s.data.name}
            onChange={e => this.onChange("name", e.target.value)}
          />
        </label>
        {s.validate && s.errors.name && (
          <div className="error">{s.errors.name}</div>
        )}
        <br />
        <label>
          email:
          <input
            value={s.data.email}
            onChange={e => this.onChange("email", e.target.value)}
          />
        </label>
        {s.validate && s.errors.email && (
          <div className="error">{s.errors.email}</div>
        )}
        <div>
          comments:{" "}
          <a onClick={this.addComment} href="javascript:void(0)">
            add
          </a>
          {s.data.comments.map((m, i) => (
            <div style={{ border: "1px solid red" }} key={i}>
              <textarea
                rows="2"
                value={m}
                onChange={e => this.editComment(i, e.target.value)}
              />
              <a
                onClick={() => this.deleteComment(i)}
                href="javascript:void(0)"
              >
                delete
              </a>
              {s.validate && s.errors.comments && s.errors.comments[i] && (
                <div className="error">{s.errors.comments[i]}</div>
              )}
            </div>
          ))}
        </div>
        <br />
        <input type="submit" value="submit" />
      </form>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

пример из жизни https://codesandbox.io/s/ymwky9603j

...