最近有不少前端同窗都抱怨说,登录表单都不能记录本身的帐号。这对于用单页面(single-page applications)和使用ajax比较多的网页来讲,仍是一个蛮广泛的问题。javascript
UserApp是一个使用angularjs构建的WebApp,可是他一直未能支持浏览器的"save password"特性。
下面就列出了一些发现的问题:html
Firefox相对来讲简单一点,只要表单元素有name属性,触发提交事件以后,它就会自动提醒用户是否记录数据。前端
<form name="login-form" ng-submit="login()"> <input id="login" name="login" type="text" ng-model="user.login"> <input id="password" name="password" type="password" ng-model="user.password"> </form>
可是firefox有一个问题,在自动填表以后,$scope里的数据并不会更新。因此我google了一下,发现了一些针对此问题的hacks。可是总感受这些解决方案不必,由于我须要的只是在提交表单的时候将数据带上,而不是一些很溜逼的数据双向绑定技术。因此我就采用了很简单的办法:在提交表单的时候获取表单元素的值。java
$scope.login = function() { $scope.user = { login: $("#login").val(), password: $("#password").val() }; ... return false; };
OK,如今firefox没问题了,可是chrome怎么办呢?angularjs
chrome只有在form表单真正发起POST请求的时候才会提示用户是否储存密码,但这样的话就不能用Ajax操做了。ajax
下面是解决办法:chrome
这会让页面刷新一次,但也就是登陆的时候须要刷新而已,确保页面返回时是同一个地址就好了。
但若是表单是被动态添加进DOM的时候,这个方法仍然不行。解决方案就是在index.html
中添加一个隐藏的表单,须要提交数据的时候就将其它表单携带的数据复制到隐藏表单里。segmentfault
我将它打包成了一个directive:浏览器
app.directive("ngLoginSubmit", function(){ return { restrict: "A", scope: { onSubmit: "=ngLoginSubmit" }, link: function(scope, element, attrs) { $(element)[0].onsubmit = function() { $("#login-login").val($("#login", element).val()); $("#login-password").val($("#password", element).val()); scope.onSubmit(function() { $("#login-form")[0].submit(); }); return false; }; } }; });
在index.html
里隐藏的表单:cookie
<form name="login-form" id="login-form" method="post" action="" style="display: none;"> <input name="login" id="login-login" type="text"> <input name="password" id="login-password" type="password"> </form>
临时登陆表单
<form name="login-form" autocomplete="on" ng-login-submit="login"> <input id="login" name="login" type="text" autocomplete="on"> <input id="password" name="password" type="password" autocomplete="on"> </form>
登陆用的controller:
$scope.login = function(submit) { $scope.user = { login: $("#login").val(), password: $("#password").val() }; function ajaxCallback() { submit(); } return false; };
如今这个问题解决了,可是每当你按下f5的时候,浏览器都会提醒你要不要从新提交表单。这确实有点蛋疼,因此我添加了一个pre-login.html
文件,隐藏的表单会提交数据到这里,而后再重定向到index.html
。
如今OK了~