Recently, many front-end students have complained that they cannot record their account even if they log in to the login form. This is still a common problem for single-page applications and web pages that use more ajax.
UserApp is a WebApp built using angularjs, but it has not been able to support the browser's "save password" feature.
Here are some issues found:
The form cannot be dynamically inserted into the DOM using js.
The form must actually issue a POST request. (Cannot get form content and then make a request with ajax)
When the browser automatically fills in the form, $scope cannot obtain the updated data.
Firefox is relatively simple. As long as the form element has a name attribute, after triggering the submission event, it will automatically remind the user whether to record the data.
The code copy is as follows:
<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>
The requirement for firefox to record data is relatively simple
But firefox has a problem. After the form is automatically filled, the data in $scope will not be updated. So I googled and found some hacks for this issue. But I always feel that these solutions are unnecessary, because all I need is to bring the data with me when submitting the form, rather than some very frivolous data two-way binding technology. So I used a very simple method: get the value of the form element when submitting the form.
The code copy is as follows:
$scope.login = function() {
$scope.user = {
login: $("#login").val(),
password: $("#password").val()
};
...
return false;
};
OK, there is no problem with firefox now, but what should I do with Chrome?
Chrome will only prompt the user whether to store the password when the form form actually initiates a POST request, but in this way, it cannot be operated with Ajax.
Here is the solution:
When the form makes a Post request, intercept it with ng-submit, return false to block it, and submit data with ajax.
When ajax returns successfully, store the session in cookies and resubmit the form.
When the page is reloaded, you will find that it has been certified and redirect it to the home page.
This will refresh the page once, but it only needs to be refreshed when logging in. Just make sure that the page returns at the same address.
But if the form is dynamically added to the DOM, this method still doesn't work. The solution is to add a hidden form to index.html. When you need to submit data, copy the data carried by other forms to the hidden form.
I packaged it into a directive:
The code copy is as follows:
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;
};
}
};
});
The form hidden in index.html:
The code copy is as follows:
<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>
Temporary login form
The code copy is as follows:
<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 for login:
The code copy is as follows:
$scope.login = function(submit) {
$scope.user = {
login: $("#login").val(),
password: $("#password").val()
};
function ajaxCallback() {
submit();
}
return false;
};
When refreshing, it will prompt whether to resubmit the form
Now this problem is solved, but whenever you press f5, the browser will remind you whether to resubmit the form. This is really a bit fucking, so I added a pre-login.html file, and the hidden form submits the data to it, and then redirects to index.html.
It's OK now~