您需要通过身份验证才能对投票进行投票。当您在投票方式行使表决权,有2个问题:为什么投票选项未正确预选?
当你重新加载页面你可以直到你离开投的无数次或重新载入页面
,你终于从防止投票,而不是让您选择预选的选项,它始终是预选的第二个选项。
希望发生的事情:
注册/登录,然后在投票方式行使表决权。当您点击某个选项时,您所做的投票选择被锁定,您无法在该投票中投票。
HOW我的当前代码的流程WORKS:
当用户点击一个选项,该计数器被增加,然后表决被保存在该被推到用户对象的阵列在数据库中。
当部件载荷,选票在当前登录用户的数据库中的数据通过ngOninit()
方法保存在本地votes
变量,然后将其用于检查其调查用户已经投票,他做了什么票里面。问题在于,如果事实并非如此,那么选择总是选择2。
我明白你为什么可以多次投票直到页面重新载入,但我不知道如何在用户投票后在客户端和后端立即锁定投票(防止更多投票被注册为if用户已投票投票)。
至于为什么它已经是预选的第二选择,我不知道。
CODE:
HTML
<div class="formWidth">
<form (ngSubmit)="onSubmit(f)" #f="ngForm">
<div class="form-group">
<label class="inputTitle" for="title">Poll Title</label>
<input
type="text"
id="title"
class="form-control"
[ngModel]="poll?.title"
name="title"
required maxlenth="30">
<label class="inputTitle" for="choice1">Choice1</label>
<input
type="text"
id="choice1"
class="form-control"
[ngModel]="poll?.choice1"
name="choice1"
required maxlenth="20">
<label class="inputTitle" for="choice2">Choice2</label>
<input
type="text"
id="choice2"
class="form-control"
[ngModel]="poll?.choice2"
name="choice2"
required maxlenth="20">
</div>
<button type="button" class="btn btn-danger" (click)="onClear(f)">Clear</button>
<button class="btn btn-primary" type="submit">Save</button>
</form>
</div>
COMPONENT
export class PollComponent {
@Input() poll: Poll;
constructor(private pollService: PollService) {}
votes: any;
// Pie
public pieChartLabels:string[] = [];
public pieChartData:number[] = [];
public pieChartType:string = 'pie';
public pieChartOptions:any = {};
ngOnInit() {
var result1 = parseFloat(((this.poll.counter1/(this.poll.counter2+this.poll.counter1))*100).toFixed(2));
var result2 = parseFloat(((this.poll.counter2/(this.poll.counter2+this.poll.counter1))*100).toFixed(2));
this.pieChartData = [result1, result2];
this.pieChartLabels = [this.poll.choice1, this.poll.choice2];
this.pieChartType = 'pie';
this.pieChartOptions = {
tooltips: {
enabled: true,
mode: 'single',
callbacks: {
label: function(tooltipItem, data) {
var allData = data.datasets[tooltipItem.datasetIndex].data;
var tooltipLabel = data.labels[tooltipItem.index];
var tooltipData = allData[tooltipItem.index];
return tooltipLabel + ": " + tooltipData + "%";
}
}
}
}
this.pollService.voted(localStorage.getItem('userId')).subscribe(
data => {
var result = JSON.parse(data);
this.votes = result.votes;
},
err => { console.log("NGONINIT ERROR: "+ err) },
() => { }
);
}
onEdit() {
this.pollService.editPoll(this.poll);
}
onDelete() {
this.pollService.deletePoll(this.poll)
.subscribe(
result => console.log(result)
);
}
onChoice1() {
this.pollService.increaseCounter1(this.poll);
this.onVote1();
var result1 = parseFloat(((this.poll.counter1/(this.poll.counter2+this.poll.counter1))*100).toFixed(2));
var result2 = parseFloat(((this.poll.counter2/(this.poll.counter2+this.poll.counter1))*100).toFixed(2));
this.pieChartData = [result1, result2];
}
onChoice2() {
this.pollService.increaseCounter2(this.poll);
this.onVote2();
var result1 = parseFloat(((this.poll.counter1/(this.poll.counter2+this.poll.counter1))*100).toFixed(2));
var result2 = parseFloat(((this.poll.counter2/(this.poll.counter2+this.poll.counter1))*100).toFixed(2));
this.pieChartData = [result1, result2];
}
onVote1() {
this.pollService.voteOn(this.poll.pollID, localStorage.getItem('userId'), 1);
}
onVote2() {
this.pollService.voteOn(this.poll.pollID, localStorage.getItem('userId'), 2);
}
belongsToUser() {
return localStorage.getItem('userId') == this.poll.userId;
}
alreadyVotedFor(choice: number) {
var result = "";
if (this.votes) {
for (var i = 0; i < this.votes.length; i ++) {
if (this.votes[i].pollID == this.poll.pollID) {
result = "disabled";
if (this.votes[i].choice == choice) {
result = "selected";
}
}
}
}
return result;
}
// events
public chartClicked(e:any):void {
}
public chartHovered(e:any):void {
}
}
SERVI CE
updatePoll(poll: Poll) {
const body = JSON.stringify(poll);
const token = localStorage.getItem('token')
? localStorage.getItem('token')
: '';
const headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'Bearer '+token
});
return this.http.patch('https://voting-app-10.herokuapp.com/poll/' + poll.pollID, body, {headers: headers})
.map((response: Response) => response.json())
.catch((error: Response) => {
this.errorService.handleError(error.json());
return Observable.throw(error);
});
}
increaseCounter1(poll: Poll) {
poll.counter1++;
const body = JSON.stringify(poll);
const token = localStorage.getItem('token')
? localStorage.getItem('token')
: '';
const headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'Bearer '+token
});
this.http.patch('https://voting-app-10.herokuapp.com/poll/vote/' + poll.pollID, body, {headers: headers})
.map((response: Response) => response.json())
.catch((error: Response) => {
this.errorService.handleError(error.json());
return Observable.throw(error);
})
.subscribe();
}
increaseCounter2(poll: Poll) {
poll.counter2++;
const body = JSON.stringify(poll);
const token = localStorage.getItem('token')
? localStorage.getItem('token')
: '';
const headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'Bearer '+token
});
return this.http.patch('https://voting-app-10.herokuapp.com/poll/vote/' + poll.pollID, body, {headers: headers})
.map((response: Response) => response.json())
.catch((error: Response) => {
this.errorService.handleError(error.json());
return Observable.throw(error);
})
.subscribe();
}
voteOn(pollID: string, userID: string, choice: number) {
var user;
this.http.get('https://voting-app-10.herokuapp.com/user/'+userID)
.map(response => response.json())
.subscribe(
json => {
user = JSON.parse(json);
if (user.votes == undefined) {
user.votes = [{pollID, choice}];
} else {
user.votes.push({pollID, choice});
}
const body = user;
const token = localStorage.getItem('token')
? localStorage.getItem('token')
: '';
const headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'Bearer '+token
});
return this.http.patch('https://voting-app-10.herokuapp.com/user/', body, {headers: headers})
.map((response: Response) => response.json())
.catch((error: Response) => {
this.errorService.handleError(error.json());
return Observable.throw(error);
})
.subscribe();
}
)
}
voted(userID: string) {
const headers = new Headers({'Content-Type': 'application/json'});
return this.http.get('https://voting-app-10.herokuapp.com/user/'+userID,{headers: headers})
.map(response => response.json())
.catch((error: Response) => {
this.errorService.handleError(error.json());
return Observable.throw(error);
});
}
ROUTE(BACKEND)
router.patch('/vote/:id', function (req, res, next) {
var decoded = jwt.decode(getToken(req));
Poll.findById(req.params.id, function (err, poll) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
if (!poll) {
return res.status(500).json({
title: 'No Poll Found!',
error: {poll: 'Poll not found'}
});
}
poll.title = req.body.title;
poll.choice1 = req.body.choice1;
poll.choice2 = req.body.choice2;
poll.counter1 = req.body.counter1;
poll.counter2 = req.body.counter2;
poll.save(function (err, result) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
res.status(200).json({
poll: 'Updated poll',
obj: result
});
});
});
});
router.patch('/:id', function (req, res, next) {
var decoded = jwt.decode(getToken(req));
Poll.findById(req.params.id, function (err, poll) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
if (!poll) {
return res.status(500).json({
title: 'No Poll Found!',
error: {poll: 'Poll not found'}
});
}
if (poll.user != decoded.user._id) {
return res.status(401).json({
title: 'Not Authenticated',
error: {poll: 'Users do not match'}
});
}
poll.title = req.body.title;
poll.choice1 = req.body.choice1;
poll.choice2 = req.body.choice2;
poll.counter1 = req.body.counter1;
poll.counter2 = req.body.counter2;
poll.save(function (err, result) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
res.status(200).json({
poll: 'Updated poll',
obj: result
});
});
});
});
请不要回滚有效更正的帖子。问题不应该包含任何meta cruft。如果你想把这个政策讨论到[meta]。 –