luc*_*ssp 110 javascript mvvm angularjs
在AngularJS中提交表单并使用浏览器记住密码功能时,在后续登录尝试中,您让浏览器使用用户名和密码填写登录表单,$scope不会根据自动填充更改模型.
我发现的唯一脏黑客是使用以下指令:
app.directive("xsInputSync", ["$timeout" , function($timeout) {
return {
restrict : "A",
require: "?ngModel",
link : function(scope, element, attrs, ngModel) {
$timeout(function() {
if (ngModel.$viewValue && ngModel.$viewValue !== element.val()) {
scope.apply(function() {
ngModel.$setViewValue(element.val());
});
}
console.log(scope);
console.log(ngModel.$name);
console.log(scope[ngModel.$name]);
}, 3000);
}
};
}]);
Run Code Online (Sandbox Code Playgroud)
问题是ngModel.$setViewValue(element.val());不会根据element.val()返回的值更改模型和视图.我怎么能做到这一点?
Ben*_*esh 45
我不知道你能在这里做什么,除了你尝试的某种类似的工作.看来你走在正确的轨道上.我无法让我的浏览器尝试记住你的插件的密码,所以我不确定这是否会起作用但看看:
app.directive('autoFillSync', function($timeout) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
var origVal = elem.val();
$timeout(function () {
var newVal = elem.val();
if(ngModel.$pristine && origVal !== newVal) {
ngModel.$setViewValue(newVal);
}
}, 500);
}
}
});
Run Code Online (Sandbox Code Playgroud)
<form name="myForm" ng-submit="login()">
<label for="username">Username</label>
<input type="text" id="username" name="username" ng-model="username" auto-fill-sync/><br/>
<label for="password">Password</label>
<input type="password" id="password" name="password" ng-model="password" auto-fill-sync/><br/>
<button type="submit">Login</button>
</form>
Run Code Online (Sandbox Code Playgroud)
我想你只需要简化一下你的方法.我绝对推荐的一件事是检查ngModel.$pristine并确保你没有覆盖一些不良用户的输入.此外,3秒可能太长.你不应该在$ timeout,BTW中调用$ apply(),它应该自动为你排队$摘要.
真正的问题:您的浏览器是否会将Angular击败执行?我的浏览器怎么样?
这可能是一场无法取胜的战争,这就是为什么Angular(或Knockout)无法轻易解决的原因.在指令初始执行时,无法保证输入中的数据状态.甚至在Angular初始化的时候......所以这是一个棘手的问题需要解决.
bek*_*kos 35
您不必使用$timeout或类似的任何东西.您可以使用事件系统.
我认为它更像是Angularish并且不依赖于jQuery或自定义事件捕获.
例如,在您的提交处理程序上:
$scope.doLogin = function() {
$scope.$broadcast("autofill:update");
// Continue with the login.....
};
Run Code Online (Sandbox Code Playgroud)
然后你可以得到这样的autofill指令:
.directive("autofill", function () {
return {
require: "ngModel",
link: function (scope, element, attrs, ngModel) {
scope.$on("autofill:update", function() {
ngModel.$setViewValue(element.val());
});
}
}
});
Run Code Online (Sandbox Code Playgroud)
最后,您的HTML将如下:
<input type="text" name="username" ng-model="user.id" autofill="autofill"/>
Run Code Online (Sandbox Code Playgroud)
Eze*_*tor 35
这是一个远比其他解决方案更难以解决的解决方案,并且在语义上是合理的AngularJS:http://victorblog.com/2014/01/12/fixing-autocomplete-autofill-on-angularjs-form-submit/
myApp.directive('formAutofillFix', function() {
return function(scope, elem, attrs) {
// Fixes Chrome bug: https://groups.google.com/forum/#!topic/angular/6NlucSskQjY
elem.prop('method', 'POST');
// Fix autofill issues where Angular doesn't know about autofilled inputs
if(attrs.ngSubmit) {
setTimeout(function() {
elem.unbind('submit').submit(function(e) {
e.preventDefault();
elem.find('input, textarea, select').trigger('input').trigger('change').trigger('keydown');
scope.$apply(attrs.ngSubmit);
});
}, 0);
}
};
});
Run Code Online (Sandbox Code Playgroud)
然后,您只需将指令附加到表单:
<form ng-submit="submitLoginForm()" form-autofill-fix>
<div>
<input type="email" ng-model="email" ng-required />
<input type="password" ng-model="password" ng-required />
<button type="submit">Log In</button>
</div>
</form>
Run Code Online (Sandbox Code Playgroud)
OZ_*_*OZ_ 10
脏代码,在使用此代码之前检查问题https://github.com/angular/angular.js/issues/1460#issuecomment-18572604是否已修复.该字段在字段填充时触发事件,不仅在提交之前触发(如果必须在提交之前处理输入,则必须执行此操作)
.directive('autoFillableField', function() {
return {
restrict: "A",
require: "?ngModel",
link: function(scope, element, attrs, ngModel) {
setInterval(function() {
var prev_val = '';
if (!angular.isUndefined(attrs.xAutoFillPrevVal)) {
prev_val = attrs.xAutoFillPrevVal;
}
if (element.val()!=prev_val) {
if (!angular.isUndefined(ngModel)) {
if (!(element.val()=='' && ngModel.$pristine)) {
attrs.xAutoFillPrevVal = element.val();
scope.$apply(function() {
ngModel.$setViewValue(element.val());
});
}
}
else {
element.trigger('input');
element.trigger('change');
element.trigger('keyup');
attrs.xAutoFillPrevVal = element.val();
}
}
}, 300);
}
};
});
Run Code Online (Sandbox Code Playgroud)
ors*_*zky 10
不需要再破解了!当浏览器更改表单字段而不触发更改事件时,Angular dev tbosch创建了一个触发更改事件的polyfill:
https://github.com/tbosch/autofill-event
目前他们不会将此构建到Angular代码中,因为这是浏览器的错误修复,也可以在没有Angular的情况下工作(例如,对于普通的jQuery应用程序).
"polyfill将检查文档加载的变化以及何时保留输入(仅以相同的形式).但是,如果需要,可以手动触发检查.
该项目具有单元测试和半自动测试,因此我们最终可以收集所有不同的用例以及所需的浏览器设置.
请注意:此polyfill适用于简单的AngularJS应用程序,使用AngularJS/jQuery应用程序,但也适用于不使用Angular的普通jQuery应用程序."
它可以安装:
bower install autofill-event --save
Run Code Online (Sandbox Code Playgroud)
在页面中的jQuery或Angular autofill-event.js 之后添加脚本.
这将执行以下操作:
API(手动触发检查):
$el.checkAndTriggerAutoFillEvent():对给定jQuery/jQLite元素中的所有DOM元素执行检查.记住用户对输入元素的所有更改(侦听更改事件)以及JavaScript(通过拦截jQuery/jQLite元素的$ el.val()).该更改的值存储在私有属性中的元素上.
检查元素是否为自动填充:将元素的当前值与记忆值进行比较.如果不同,则触发更改事件.
AngularJS或jQuery(与其中一个或两个一起工作)
github页面上的更多信息和来源.
可以在此处阅读 Github上的原始Angular问题#1460 .
似乎是明确的直接解决方案.不需要jQuery.
更新:
app.directive('autofillable', ['$timeout', function ($timeout) {
return {
scope: true,
require: 'ngModel',
link: function (scope, elem, attrs, ctrl) {
scope.check = function(){
var val = elem[0].value;
if(ctrl.$viewValue !== val){
ctrl.$setViewValue(val)
}
$timeout(scope.check, 300);
};
scope.check();
}
}
}]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
75469 次 |
| 最近记录: |