Нокаут-валидация и Qtip

В настоящее время я использую Jquery Validation и Qtip вместе, чтобы иметь дело с фактической проверкой и отображением информации на экране, используя красивые уведомления в стиле всплывающей подсказки при ошибках проверки с использованием компонента errorPlacement параметров проверки.

В настоящее время каждая модель представления имеет свой собственный метод для настройки и запуска проверки и обратных вызовов, однако я пытался найти более удобный способ сделать это, будь то добавление пользовательской привязки для настройки моих правил проверки через привязки данных или альтернативный способ, но по-прежнему дающий те же результаты (т. е. errorPlacement запускается, когда возникает ошибка проверки, и указывает Qtip отображать ошибку для данного элемента).

Теперь, прежде чем я начал делать это самостоятельно, я просто проверил в Интернете и нашел Knockout Validation, который я сначала подумал, что отличная идея, я мог бы применить свою логику проверки непосредственно к данным в моей модели представления, а затем просто найти какой-то обратный вызов, чтобы запустить Qtip, однако, похоже, нет никакого обратного вызова, который я могу найти задокументированным. Библиотека, кажется, делает все, что я хочу, для проверки, но не для отображения. Я просмотрел исходный код и примеры, но не увидел ничего, кроме ko.validation.group(viewModel), который дал бы мне наблюдаемое, содержащее ошибки, но я не уверен, смогу ли я использовать это так же, как я ожидание.

Вот пример того, как происходит моя текущая проверка:

/*globals $ ko */
function SomeViewModel() {

    this.SetupValidation = function () {
        var formValidationOptions = {
            submitHandler: self.DoSomethingWhenValid,
            success: $.noop,
            errorPlacement: function (error, element) {
                if (!error.is(':empty'))
                { qtip.DoSomethingToDisplayValidationErrorForElement(element, error); }
                else
                { qtip.DoSomethingToHideValidationErrorForElement(element); }
            }
        };

        $(someForm).validate(formValidationOptions);
        this.SetupValidationRules();
    };

    this.SetupValidationRules = function() {
        $(someFormElement1).rules("add", { required: true, minlength: 6, maxlength: 20, alphaNumeric: true });
        $(someFormElement2).rules("add", { required: true, minlength: 6, maxlength: 20 });
        $(someFormElement3).rules("add", { required: true, email: true, });
    };
}

В настоящее время я уверен, что могу устранить необходимость в методе правил проверки, добавив пользовательскую привязку, чтобы я мог установить проверку в привязке данных, однако, если возможно, я хотел бы использовать такой же подход обратного вызова с существующим Knockout- Привязка валидации.


person Grofit    schedule 17.02.2012    source источник


Ответы (2)


Я специально не использовал Knockout-Validation, но в прошлом писал что-то подобное. Беглый взгляд на исходный код показывает, что каждый расширенный наблюдаемый объект получает вспомогательный наблюдаемый объект isValid. Это может быть использовано для скрытия сообщений show в вашей разметке с помощью обычных видимых привязок нокаута.

Чтобы заставить QTip работать, пользовательская привязка может подписаться на это свойство isValid и выполнить необходимую инициализацию для отображения/скрытия QTip при срабатывании.

ИЗМЕНИТЬ

Вот пример для начала

http://jsfiddle.net/madcapnmckay/hfcj7/

HTML:

<!-- Note that you have to reference the "qtipValMessage" binding -->
<!-- using the "value" binding alone is not enough                -->
<input data-bind="value: emailAddress, qtipValMessage : emailAddress" />

JS:

ko.bindingHandlers.qtipValMessage = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var observable = valueAccessor(), $element = $(element);
       if (observable.isValid) {
            observable.isValid.subscribe(function(valid) {
                if (!valid) {
                    $element.qtip({
                        overwrite: true,
                        content: {
                            text: observable.error
                        }
                     });
                 } else {
                     $element.qtip("destroy");
                 }
           });
       }
    }
};
person madcapnmckay    schedule 24.02.2012
comment
Свойство isValid может указывать на то, что что-то пошло не так, но мне нужен элемент, к которому привязаны данные с ошибками, чтобы я мог отображать всплывающие подсказки, без элементов я мало что могу сделать. - person Grofit; 27.02.2012
comment
Отсюда необходимость пользовательской привязки, вы можете разместить ее на элементе, к которому хотите применить QTip, и тогда он сможет обрабатывать подписку на свойство isValid. - person madcapnmckay; 28.02.2012
comment
Мне не нравится подход с использованием пользовательских привязок к любой проблеме, но это кажется достойным способом решения проблемы. В настоящее время я только что изменил библиотеку проверки нокаута, чтобы добавить наблюдаемый к выходу метода group(), а также прикрепил к нему каждый связанный элемент наблюдаемых при его проверке, чтобы дать мне доступ, НО я могу изменить его, чтобы использовать подход, аналогичный вашему своя. Большое спасибо за пример! - person Grofit; 28.02.2012
comment
Я пробовал что-то подобное, но при определенных сценариях я получаю дополнительные подсказки по моей странице. У меня есть список, и я проверяю выбранный элемент, если я отменяю и повторно выбираю этот элемент, я получаю повторяющиеся всплывающие подсказки, случайно разбросанные по странице при повторной проверке. - person Nick; 05.06.2012
comment
это не работает в случае проверки VM.isValid() до того, как что-либо будет введено, поскольку подписка никогда не запускается, TT не будет отображаться. например, обязательное поле не заполнено, и пользователь нажимает кнопку «Сохранить». Проверка KO применит класс ошибки CSS, но если пользователь наведет курсор на поле, TT не отображается - person Morgan T.; 21.11.2012
comment
я получаю всплывающую подсказку qtip и браузера - person wilsonrufus; 08.08.2013
comment
Как изменить экспресс-привязку и обработчик привязки, если я хочу добавить некоторые параметры для qtip? Пример: иногда я хочу перезаписать: false. - person thangcao; 31.03.2014

Я редактировал сообщение madcapnmckay, но различия стали достаточно значительными, и я думаю, что нужен новый ответ.

Он в значительной степени основан на сообщении madcapnmckay, но исправляет ошибку, на которую указал MorganTiley. Оригинал работает только в том случае, если пользователь изменил наблюдаемое. Если они этого не сделали, код никогда не сработает. Итак, я изменил его так, чтобы он запускал код всплывающей подсказки при создании, в дополнение к тому, когда он изменяется.

ko.bindingHandlers.qtipValMessage = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var observable = valueAccessor(), $element = $(element);
        if (observable.isValid) {
            var updateTooltip = function (valid) {
                if (!valid) {
                    $element.qtip({
                        overwrite: true,
                        content: {
                            text: observable.error
                        }
                    });
                } else {
                    $element.qtip("destroy");
                }
            }
            updateTooltip();
            observable.isValid.subscribe(updateTooltip);
        }
    }
};

Единственным недостатком является то, что всплывающая подсказка будет отображаться при наведении курсора до того, как будет запущена проверка нокаута (например, у вас есть «обязательная» проверка в поле, прежде чем вы нажмете «Отправить», появится всплывающая подсказка с сообщением, что поле является обязательным, но поле не будет выделить розовым цветом). Однако, как только вы измените поле, всплывающая подсказка исчезнет, ​​если поле допустимо.

Мое приложение использовало не qtip, а всплывающую подсказку Twitter Bootstrap, так что вот код и для этого.

ko.bindingHandlers.invalidTooltip = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var observable = valueAccessor(), $element = $(element);
        if (observable.isValid) {
            var updateTooltip = function (valid) {
                if (!valid) {
                    $element.attr("data-original-title", observable.error);
                    $element.tooltip();

                } else {
                    $element.tooltip("destroy");
                }
            }
            updateTooltip();
            observable.isValid.subscribe(updateTooltip);
        }
    }
};
person viggity    schedule 12.03.2013