knockout.js и Firefox Сохраняет пароли в форме входа в систему

#firefox #knockout.js

#firefox #knockout.js

Вопрос:

Firefox заполняет форму моим именем пользователя / паролем. Это использование knockout.js чтобы привязать входные данные, но это не приведет к обновлению значений при таком заполнении. Я что-то упускаю при загрузке страницы? Когда он заполняется и пользователь нажимает submits, значения остаются пустыми.

 (function (app, $, undefined) {

    app.viewModel = app.viewModel || {};
    app.login = {};

    app.viewModel.login = {
        userName: ko.observable(''),
        password: ko.observable(''),
        returnUrl: ''
    };

    app.viewModel.login.submit = function () {
        sso.login(app.viewModel.login.userName(), app.viewModel.login.password(), app.viewModel.login.returnUrl);
    };

    app.login.init = function (returnUrl) {

        app.viewModel.login.returnUrl = returnUrl;

        ko.applyBindings(app.viewModel);
    };

})(window.app = window.app || {}, jQuery);
  

Комментарии:

1. Knouckout.js необходимо обработать input событие.

Ответ №1:

Способ, которым я занимался этим в прошлом, — использовать оболочку для value привязки, которая инициализирует значение из текущего значения элемента.

Это выглядело бы так (этот упрощен для работы только с наблюдаемыми):

 ko.bindingHandlers.valueWithInit = {
    init: function(element, valueAccessor, allBindingsAccessor, context) {
        var observable = valueAccessor();
        var value = element.value;

        observable(value);   

        ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, context);
    },
    update: ko.bindingHandlers.value.update
};
  

Итак, вы бы использовали valueWithInit вместо value . Вам просто нужно убедиться, что ko.applyBindings не вызывается до того, как автозаполнение сможет выполнить свою работу.

http://jsfiddle.net/rniemeyer/TeFAX/

Комментарии:

1. Интересно, но это сработало, спасибо! setTimeout(функция () { ko.applyBindings(app.ViewModel); }, 1000);

2. Я хотел основываться на этом. Если у вас есть два сохраненных учетных данных для одной и той же формы, то это не сработает. Когда вы выбираете имя пользователя, оно вводит пароль, но пароль не отражается в viewmodel. Вы должны вручную удалить его и ввести.

3. Я заставил его работать с этим ниже, просто повторно привязав его. app.ViewModel.login.userName.subscribe(function () { ko.applyBindings(app.ViewModel); });

4. Когда вы вводите его вручную, пароль заполняется в текстовом поле, но наблюдаемое значение не обновляется. Я думал, что привязки приложений будут работать, но на самом деле они дважды привязывают страницу. Не могу ли я обновить текстовое поле только для пароля?

5. Я попробовал скрипку, и она не работает, если вы сохраняете пароли для нескольких пользователей и пытаетесь переключаться между ними. Протестировано в Chrome 25.0.1354.0 (канал разработчиков)

Ответ №2:

Я нашел решение здесь не совсем удовлетворительным. Хотя подход довольно интересный, он терпит неудачу, когда пользователь выбирает учетную запись позже, и браузер позволяет использовать сохраненные учетные данные (например, если сохранено более одной учетной записи). Это также не удалось, когда вы начали вводить пароль и удалили, чтобы вернуться к исходному паролю (по крайней мере, в Firefox). Кроме того, мне не очень понравился тайм-аут, чтобы дать браузеру время — просто не так приятно.

Мое решение:
на самом деле это не так, но я подумал, что, тем не менее, поделюсь

Просто обновите нашу модель вручную, прежде чем выполнять вход в систему при отправке обратного вызова. Используя jQuery, что-то вроде self.password($("#password").val()) должно это сделать.

В качестве альтернативы, используя существующие привязки, запуск события изменения, похоже, также работает — например $("#password").change() .

Плюсы:

  • только для полей учетных данных, так что, вероятно, это одноразовая вещь для вашего сайта
  • просто и понятно — одна или две строки в нужном месте
  • кажется, всегда работает надежно, независимо от того, какой браузер, настройка учетных данных или шаблон использования

Минусы:

  • снова нарушает приятное разделение Knockout.js обеспечивает
  • это не решение, а скорее обходной путь

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

Просто подумайте немного вперед — та же проблема должна возникнуть, когда браузер автоматически завершает любую форму (например, например, адрес), что означает, что какая-то общая функция, выполняющая вышеуказанное, была бы приятной (вероятно, вызывая триггер изменения в каждом поле ввода формы)

Редактировать: некоторый быстрый код, демонстрирующий идею

HTML:

 <form id="myForm" data-bind="submit: login">
    Email: <input type="text" data-bind="value: email" /><br/>
    Password: <input type="password" data-bind="value: password" /><br/>
    <button type="submit">Login</button>
</form>
  

И Javascript:

 function ViewModel() {
    var self = this;

    self.email = ko.observable("");
    self.password = ko.observable("");

    self.login = function() {
        $("#myForm").find("input").change();

        //Now the observables contain the recent data
        alert(ko.mapping.toJSON(self));
    };
}