使用AngularJS完成登录表单示例
在上周,我创建了一个完整的示例web应用程序,以演示使用AngularJS的自定义登录表单实现。这对我来说并不太容易,因为我是一名Java开发人员,而且我在JavaScript方面没有太多经验。但最终我的代码运行良好。万岁:-) 我想和你们分享我的解决方案,如果你们能看一看并给我任何简化的建议,我会很高兴的。请随意批评我的JavaScript代码 在我的演示应用程序中,服务器端资源(图像、html页面和RESTFul api)受OpenAM保护 为了避免OpenAm中受保护URL的错误和复杂配置,我在web应用程序中创建了两个文件夹,一个用于公共内容,另一个用于受保护内容 我的war文件(web应用程序)的结构如下所示:使用AngularJS完成登录表单示例,angularjs,login,angular-ui,Angularjs,Login,Angular Ui,在上周,我创建了一个完整的示例web应用程序,以演示使用AngularJS的自定义登录表单实现。这对我来说并不太容易,因为我是一名Java开发人员,而且我在JavaScript方面没有太多经验。但最终我的代码运行良好。万岁:-) 我想和你们分享我的解决方案,如果你们能看一看并给我任何简化的建议,我会很高兴的。请随意批评我的JavaScript代码 在我的演示应用程序中,服务器端资源(图像、html页面和RESTFul api)受OpenAM保护 为了避免OpenAm中受保护URL的错误和复杂配置
web-ui.war
|-app
| |-components
| |-protected <-- protected web folder by OpenAM
| | |-welcome
| | |-welcome.html
| |-public
| | |-help
| | | |-help-general.html
| | | |-help-howItWorks.html
| | |-home
| | | |-home.html
| | |-log-in
| | | |-logIn.html
| | | |-logIn-controller.js
| | | |-logIn-factory.js
| | |-sign-up
| | | sign-up.html
| | |-app-directive.js
| | |-app-module.js
| | |-app-route.js
|- assets
| |-css
| | |-app.css
| |-img
| |-libs
| | |-angular
| | | |-1.4.7
| | | |...
| | |-angular-ui
| | | |-0.2.15
| | | |...
| | |-bootstrap
| | | |-3.3.5
| | | |...
| | |-ui-bootstrap
| | | |-0.14.2
| | | |...
|-WEB-INF
|-index.html
我创建了两个指令来处理文本框内的onEnter事件,并将焦点设置在文本元素上(显示闪烁的光标)
app-directive.js文件:
var app = angular.module("myApp", ['ui.bootstrap', 'ui.router']);
app.directive('myEnter', function () {
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if(event.which === 13) {
scope.$apply(function (){
scope.$eval(attrs.myEnter);
});
event.preventDefault();
}
});
};
});
app.directive('autoFocus', function($timeout) {
return {
restrict: 'AC',
link: function(_scope, _element) {
$timeout(function(){
_element[0].focus();
}, 0);
}
};
});
app-routes.js文件的重要部分是“数据:{requiresLogin:true}”。这一行告诉客户端的页面路由逻辑,用户希望访问受保护的内容。如果用户未登录,则需要显示登录页面,并且在成功登录过程后,需要显示原始请求页面
这个js文件中的另一个重要行与“$stateChangeStart”事件有关。它在url每次更改时激发(模板html路由开始工作)。在这种情况下,请求的url存储在loginFactory中,以防需要显示登录页面。登录过程后,需要显示原始请求页面,因此我们需要此信息以供进一步使用
app-routes.js文件:
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
// public pages
.state('home', {
url: '/home',
templateUrl: 'app/components/public/home/home.html'
})
.state('log-in', {
url: '/log-in',
templateUrl: 'app/components/public/log-in/logIn.html'
})
.state('sign-up', {
url: '/sign-up',
templateUrl: 'app/components/public/sign-up/signUp.html'//,
})
.state('help-general', {
url: '/help-general',
templateUrl: 'app/components/public/help/help-general.html'
})
.state('help-howItWorks', {
url: '/help-howItWorks',
templateUrl: 'app/components/public/help/help-howItWorks.html'
})
// private pages
.state('private/welcome', {
url: '/private/welcome',
templateUrl: 'app/components/protected/welcome/welcome.html',
data : { requiresLogin: true }
});
});
app.run(function($rootScope, $state, loginFactory) {
$rootScope.$on('$stateChangeStart', function(event, toState) {
var isAuthenticationRequired = toState.data && toState.data.requiresLogin && !loginFactory.isLoggedIn();
if (isAuthenticationRequired == true) {
loginFactory.setToState(toState);
event.preventDefault();
$state.go('log-in');
}
});
});
在my login.html文件中,自动聚焦指令用于用户名文本框,输入指令用于密码按钮。如果用户在输入密码后按enter键,则调用控制器中的login()方法。当用户单击登录按钮时,也会应用相同的行为
在显示login.html之前,我们调用控制器的reset()方法。它清除上一个密码文本框的值并隐藏“无效用户名或密码”标签
不含任何设计元素的login.html文件:
<div class="..." ng-controller="loginController" data-ng-init="reset()">
<h3>Login or <a ui-sref="user-registration">Sign up</a></h3>
<div class="...">
<div class="col-xs-12 col-sm-6">
<input type="text" class="..." placeholder="email address" ng-model="user.username" auto-focus>
<input type="password" class="..." placeholder="Password" ng-model="user.password" my-enter="login()">
<span class="..." ng-if="!firstAttempt">Invalid username or password</span>
<span class="..." ng-if="firstAttempt"></span>
<button class="..." ng-click="login()">Login</button>
</div>
</div>
login-controller.js文件:
app.controller('loginController', function($scope, loginFactory, $location) {
$scope.loggedIn = false;
$scope.user = {};
$scope.firstAttempt = true;
$scope.login = function() {
loginFactory.callAuthService($location, $scope);
$scope.firstAttempt = false;
};
$scope.reset = function() {
$scope.firstAttempt = true;
$scope.user.password = '';
}
});
就这样
我有一些问题:
读起来太长了。你能不能只添加相关的内容和代码。Plunkr会很好。是的,这不是一篇短文,因为它是一个完整的例子。我之所以发布它,是因为我想知道你对它的看法。这应该发布在codereview.stackexchange.com上。这是离题的。我投票以离题的方式结束这个问题,因为它要求进行代码审查,因此应该发布在codereview.stackexchange.com上。我还有一些问题。
app.factory('loginFactory', function($http) {
var loggedIn = false;
var toState;
return {
isLoggedIn: function() {
return loggedIn;
},
setToState: function(state) {
toState = state;
},
callAuthService: function($location, $scope) {
var formData = 'username=' + $scope.user.username + '&password=' + $scope.user.password;
var response = $http({
method: 'POST',
url: 'http://...:8080/loginservlet/public/auth',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: formData})
.success(function (data, status, headers, config) {
loggedIn = true;
if (toState) {
$location.path(toState.url);
toState = undefined;
} else
$location.path('private/welcome');
})
.error(function (data, status, headers, config) {
loggedIn = false;
});
}
};
});
app.controller('loginController', function($scope, loginFactory, $location) {
$scope.loggedIn = false;
$scope.user = {};
$scope.firstAttempt = true;
$scope.login = function() {
loginFactory.callAuthService($location, $scope);
$scope.firstAttempt = false;
};
$scope.reset = function() {
$scope.firstAttempt = true;
$scope.user.password = '';
}
});