JQuery проверить ошибку textarea maxlength

Я использую jQuery.validate v 1.6.0 для проверки моих форм.

Одно из моих полей базы данных ограничено 1000 символами. Я добавил подтверждение в соответствующую текстовую область следующим образом:

В заголовке моей страницы я добавляю

$('form.validate').validate();

Внутри моей страницы я заявляю:

<form method="post" class="validate" action="Save">
    <textarea name="description" minlength="15" maxlength="1000" id="description" class="required"></textarea>
    <input type="submit" value="Save">    
</form>

Проблема, с которой я сталкиваюсь, заключается в том, что jQuery, по-видимому, подсчитывает количество символов, связанных с "новой строкой", по-разному, как моя база данных.

Когда я печатаю точно 1000 символов без новых строк, все идет хорошо, и валидация работает. Если я набираю 1000 символов с некоторыми новыми строками, jQuery разрешает POST, но моя база данных отказывается от вставки/обновления, потому что данные слишком большие.

Любые подсказки будут оценены.

Ответы

Ответ 1

Я столкнулся с этой проблемой, используя jQuery Validate 1.9. Поскольку я использую ASP.NET MVC 3 и С# на разрыве строки сервера, это "\ r\n" на сервере, но "\n" на клиенте. Когда я подтвердил свое текстовое поле на клиенте, проверка не завершилась неудачей, потому что "\n" считается только одним символом, но когда текст перешел к проверке на сервере, где строки являются "\ r\n" , проверка не удалась.

Мое отношение к этой проблеме состояло в том, чтобы переопределить метод проверки jQuery "rangelengt", потому что у меня также определена минимальная длина:

$.validator.addMethod('rangelength', function (value, element) {
        var maxlen = parseInt($(element).attr('data-val-length-max'));
        if (maxlen > 0) {
            var remaining = (maxlen - (parseInt($(element).val().replace(/(\r\n|\n|\r)/gm, '\r\n').length)));
            if (remaining < 0) {
                return false;
            }
        }

        return true;
    });

Итак, что этот код на самом деле делает, это получить значение maxlength, а затем получить значение из этого элемента, а затем заменить все символы "\n" на "\ r\n" , чтобы получить одинаковое количество символов, чем сервер будет.

Ответ 2

Хотя это не клиентское решение, мне удалось обработать серверную проблему.

Я в основном выделяю "лишние" символы, которые являются символами "\ r". Я думаю, что они не учитывают длину строки в браузере или объединяются как с символами "\n".

В моем случае ASP.NET MVC с С#:

[HttpPost]
public ActionResult SetComment(int id, string comment)
{
    // Yep, the browser can insert newlines as "\r\n" which overflows the allowed number of characters!
    comment = comment.Replace("\r", "");

    // More code...
}

Ответ 3

Я расширяю решение Robin Ridderholt, теперь мы можем ссылаться на maxlen на валидатор

$.validator.addMethod('extMaxLength', function (value, element, maxlen){
            if (maxlen > 0) {
                var remaining = (maxlen - (parseInt($(element).val().replace(/(\r\n|\n|\r)/gm, '\n').length, 10)));
                if (remaining < 0) {
                    return false;
                }
            }
            return true;
        });

Ответ 4

Я столкнулся с такой же проблемой. это связано с тем, что в javascript field.length возвращает количество символов, но один символ может использовать 2 байта для хранения информации.

Моя проблема заключалась в том, что поле VARCHAR2 в БД может хранить только 4000 бит информации или 2000 символов. Мы легко смущаемся и думаем, что можем хранить 4000 символов в таких полях.

Я думаю, что в вашем случае это поле не ограничивается 1000chars, но 1000 байт, которые, как оказалось, будут одинаковыми, вы используете только "стандартные символы", которые используют один байт информации, поэтому я бы восстановил предел до 2000 бит и сохраните проверку javascript до 1000chars. Тогда, конечно, я бы пошел против предыдущего ответа и проверил проверку на стороне сервера на количество символов.

Конечно, у вас есть другие решения, например, в моем случае (я не использовал JQuery), я настраивал счетчик персонажей, чтобы считать дважды каждого специального символа (эти проблемы влияют на символы новой строки, но также и акценты.... )

Ответ 5

Я также использовал подход на стороне сервера, как это сделал Джон Бубриски, но реализовал его в ASP.NET MVC в качестве расширения для DefaultModelBinder, так что все действия с контроллером принесут пользу сразу:

public class NewlinesNormalizingModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
    {
        base.BindProperty(controllerContext, bindingContext, propertyDescriptor);

        // Note: if desired, one could restrict the conversion to properties decorated with [StringLength]:
        // && propertyDescriptor.Attributes.OfType<StringLengthAttribute>().Any()
        if (propertyDescriptor.PropertyType == typeof(string))
        {
            var originalString = propertyDescriptor.GetValue(bindingContext.Model) as string;
            if (!string.IsNullOrEmpty(originalString))
            {
                var stringWithNormalizedNewlines = originalString.Replace("\r\n", "\n");
                propertyDescriptor.SetValue(bindingContext.Model, stringWithNormalizedNewlines);
            }
        }
    }
}

Затем при запуске приложения:

ModelBinders.Binders.DefaultBinder = new NewlinesNormalizingModelBinder();

Ответ 6

Я бы предложил только улучшение решения Якуба Березанского.

Я лично считаю, что его идея (обработка этого вообще на стороне сервера) очень хорошая.

Только одна проблема с его примером кода может заключаться в том, что в конечном итоге модель уже недействительна во время переопределения метода BindProperty - если это вызвано только той длиной поля, которую мы исправляем там.

Поэтому мое предложение по улучшению его решения состоит в том, чтобы применить ту же логику уже в переопределении GetPropertyValue, который выполняется до проверки:

public class NewlinesNormalizingModelBinder : DefaultModelBinder
{
    protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
    {
        // Note: if desired, one could restrict the conversion to properties decorated with [StringLength]:
        // && propertyDescriptor.Attributes.OfType<StringLengthAttribute>().Any()
        if (propertyDescriptor.PropertyType == typeof(string))
        {
            string originalString = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;

            if (!string.IsNullOrEmpty(originalString)) return originalString.Replace("\r\n", "\n");
        }

        return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
    }
}

Ответ 7

Если это происходит только в случае <textarea>, то используйте следующий код:

    $(document).ready(function () {
            $("input[type=submit]").live("click", function (e) {
                if ($(textarea).val().length > 1000) {
                    e.preventDefault();
                    return false;
                }
            });
        });

Это определенно будет работать.

Ответ 8

Откажитесь от проверки сервера и сохраните только проверку на стороне клиента. В html новая строка = 3 char В базе данных новая строка = 1 char Так что вам нужно держать только один. или Изменить настройку db char