Express+Socket.io实时投票系统(二)
接上一节,这一节,介绍一下Angularjs的安装
这里前端,我们用bower来安装,先安装
npm install -g bower
在工程项目下创建一个.bowerrc文件
{
"directory": "public/lib"
}
这里以后所有通过bower命令安装的库都会放在public/lib目录下
好了,我们安装Angular吧
bower install angular
bower install angular-route
这里面安装了两个包,一个是angular的主包,一个是angular的路由,因为我们需要跳转,所以这里需要装一个angular-route的包
接下来,我们把bootstrap下的css文件拷贝到public的css文件夹下,什么?public下没有css文件夹?呵呵,因为express-generator创建的工程,public下只创建了stylesheets、javascripts、images三个文件夹,我们为了方便,把stylesheets改成css,javascripts改成js,再创建一个fonts的文件夹,是放bootstrap的fonts的,这里我们就把前端依赖库安装好了,
好,接下来,我们在public/js下创建一个app.js,这是我们angular的主文件
angular.module('pollsApp', ['ngRoute', 'controllers', 'pollServices'])
.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/polls', {
templateUrl: 'js/views/partials/list.html',
controller: 'PollListCtrl'
})
.when('/poll/:pollId', {
templateUrl: 'js/views/partials/item.html',
controller: 'PollItemCtrl'
})
.when('/new', {
templateUrl: 'js/views/partials/new.html',
controller: 'PollNewCtrl'
})
.otherwise({
redirectTo: '/polls'
});
}]);
这里代码不多,主要是用了angular的路由功能,对不同的url请求返回不同的页面和控制器。
接下来要写服务
在public/js/services下创建一个services.js
'use strict'
angular.module('pollServices', [])
.factory('Poll', function($http, $q){
return {
all: function(){
var delay = $q.defer();
$http.get('/polls').success(function(response){
delay.resolve(response);
}).error(function(){
delay.reject("Can't get polls data.");
})
return delay.promise;
},
get: function(pollId){
var delay = $q.defer();
$http.get('/poll/' + pollId).success(function(response){
delay.resolve(response);
}).error(function(){
delay.reject("Can't get pollId " + pollId + " data.");
})
return delay.promise;
},
save: function(poll){
var delay = $q.defer();
$http.post('/pollAdd', poll).success(function(){
delay.resolve();
}).error(function(){
delay.reject("Can't save the data.");
})
return delay.promise;
}
}
});
这里通过angular的工厂生成一个Poll的服务器,这里主要定义了三个方法,一个是获取全部投票信息的请求,一个是获取单一投票信息的请求,最后一个就是创建投票信息的请求,这三个请求对应的是后台创建的三个处理。
这里用了$q来进行promise的处理,当然你也可以不用$q来处理。
接下来在public/js/controllers下创建controllers.js
'use strict'
angular.module('controllers', [])
//投票列表
.controller('PollListCtrl', function($scope, Poll){
Poll.all().then(function(data){
$scope.polls = data;
});
})
//投票详情
.controller('PollItemCtrl', function($scope, $routeParams, socket, Poll){
Poll.get($routeParams.pollId).then(function(data){
$scope.poll = data;
})
//投票
$scope.vote = function(){
};
})
//创建新的投票
.controller('PollNewCtrl', function($scope, $location, Poll){
$scope.poll = {
question: '',
choices: [
{ text: '' },
{ text: '' },
{ text: '' }
]
};
//增加选项
$scope.addChoice = function(){
$scope.poll.choices.push({ text: '' });
};
//创建投票
$scope.createPoll = function(){
var poll = $scope.poll;
if(poll.question.length > 0){
var choiceCount = 0;
poll.choices.forEach(function(choice, index) {
if(choice.text.length > 0){
choiceCount++;
}
});
if(choiceCount > 1){
var newPoll = $scope.poll;
Poll.save(newPoll).then(function(){
$location.path('polls');
})
}else{
alert('请填写一个以上选项');
}
}else{
alert('请填写详细信息');
}
};
});
好了,差不多了,接下来我们在public/js/partials/views下创建三个html页面
list.html
<div class="page-header">
<h1>投票列表</h1>
</div>
<div class="row">
<div class="col-xs-5">
<a href="#/new" class="btn btn-default"><span class="glyphicon
glyphicon-plus"></span>创建</a>
</div>
<div class="col-xs-7">
<input type="text" class="form-control" ng-model="query" placeholder="查询投票信息">
</div>
</div>
<div class="row">
<div class="col-xs-12">
<hr>
</div>
</div>
<div class="row" ng-switch on="polls.length">
<ul ng-switch-when="0">
<li>
<em>没有投票信息, 是否要
<a href="#/new">创建</a>?
</li>
</ul>
<ul ng-switch-default>
<li ng-repeat="poll in polls | filter:query">
<a href="#/poll/{{poll._id}}">{{poll.question}}</a>
</li>
</ul>
</div>
<p> </p>
item.html
<div class="page-header">
<h1>投票信息</h1>
</div>
<div class="well well-lg">
<strong>详细信息</strong><br>{{poll.question}}
</div>
<div ng-hide="poll.userVoted">
<p class="lead">请选择以下一个选项</p>
<form role="form" ng-submit="vote()">
<div ng-repeat="choice in poll.choices" class="radio">
<label>
<input type="radio" name="choice" ng-model="poll.userVote" value="{{choice._id}}">{{choice.text}}
</label>
</div>
<p><hr></p>
<div class="row">
<div class="col-xs-6">
<a href="#/polls" class="btn btn-default" role="button"><span class="glyphicon glyphicon-arrow-left"></span> 返回</a>
</div>
<div class="col-xs-6">
<button class="btn btn-primary pull-right" type="submit">投票 »</button>
</div>
</div>
</form>
</div>
<div ng-show="poll.userVoted">
<table class="result-table">
<tbody>
<tr ng-repeat="choice in poll.choices">
<td>{{choice.text}}</td>
<td>
<table style="width: {{choice.votes.length/poll.totalVotes*100}}%;">
<tr><td>{{choice.votes.length}}</td></tr>
</table>
</td>
</tr>
</tbody>
</table>
<p>
<em>共投了{{poll.totalVotes}}票.
<span ng-show="poll.userChoice">你投了
<strong>{{poll.userChoice.text}}</strong>.
</span>
</em>
</p>
<p><hr></p>
<p><a href="#/polls" class="btn btn-default" role="button">
<span class="glyphicon glyphicon-arrow-left"></span> 返回列表</a></p>
</div>
<p> </p>
new.html
<div class="page-header">
<h1>创建新投票</h1>
</div>
<form role="form" ng-submit="createPoll()">
<div class="form-group">
<label for="pollQuestion">详细信息</label>
<input type="text" ng-model="poll.question" class="form-control" id="pollQuestion" placeholder="投票详细信息">
</div>
<div class="form-group">
<label>选项</label>
<div ng-repeat="choice in poll.choices">
<input type="text" ng-model="choice.text" class="form-control" placeholder="选项{{$index+1}}"><br>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<button type="button" class="btn btn-default" ng-click="addChoice()"><span class="glyphicon glyphicon-plus"></span> 增加选项</button>
</div>
</div>
<p><hr></p>
<div class="row">
<div class="col-xs-6">
<a href="#/polls" class="btn btn-default" role="button"><span class="glyphicon glyphicon-arrow-left"></span> 返回列表</a>
</div>
<div class="col-xs-6">
<button class="btn btn-primary pull-right" type="submit">创建 »</button>
</div>
</div>
<p> </p>
</form>
views/index.jade
html
head
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1, user-scalable=no')
title= title
link(rel='stylesheet', href='/css/bootstrap.min.css')
link(rel='stylesheet', href='/css/style.css')
script(src='lib/angular/angular.min.js')
script(src='lib/angular-route/angular-route.min.js')
script(src='/socket.io/socket.io.js')
script(src='js/app.js')
script(src='js/controllers/controllers.js')
script(src='js/services/services.js')
body(ng-app='pollsApp')
nav.navbar.navbar-inverse.navbar-fixed-top(role='navigation')
div.navbar-header
a.navbar-brand(href='#/polls')= title
div.container
div(ng-view)
创建完成后,我们现在运行一下
npm start
访问http://localhost:3000
如果没有报错的话,应该显示如下:
屏幕快照 2016-10-27 下午5.05.52.png 屏幕快照 2016-10-27 下午5.05.05.png
好了,第二节结束了,第三节,我们为投票系统加入socket.io来进行实时操作。