#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 не вызывается до того, как автозаполнение сможет выполнить свою работу.
Комментарии:
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));
};
}