Sunday 21 May 2017

How to preselect a radio option based on user votes?

SITUATION:

I am trying to prevent my users from voting more than once in a poll.

For that, I store their votes inside their User object and check wether they already voted for the loaded polls.

user model

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');

var schema = new Schema({
    firstName: {type: String, required: true},
    lastName: {type: String, required: true},
    password: {type: String, required: true},
    email: {type: String, required: true, unique: true},
    polls: [{type: Schema.Types.ObjectId, ref: 'Poll'}],
    votes: [{
      poll: {type: Schema.Types.ObjectId, ref: 'Poll'},
      choice: {type: Number},
    }],
});

schema.plugin(mongooseUniqueValidator);

module.exports = mongoose.model('User', schema);

If yes, I load their last vote to preselect the correct radio option and I disable the form.

That's what should happen at least. But currently, the user can vote as many times as he wished and I am getting no errors in the console.

Currently, when I choose an option, the choice is correctly saved in the votes array of the User. But it doesn't seem to affect pre-selection of the radio options and the disabling of the form as it normally should.

Please find here the relevant code:


CODE:

poll.component.html

<article class="panel panel-default">
    <div class="panel-body">
      
      <br>
      <br>
      <form #form="ngForm">
        <fieldset [disabled]="alreadyVotedFor(-1)">
           votes <input type="radio" id="" name="my_radio" value="" (click)="onChoice1(form)" [checked]="alreadyVotedFor(1)">  
          <br>
           votes <input type="radio" id="" name="my_radio" value="" (click)="onChoice2(form)" [checked]="alreadyVotedFor(2)">  
        </fieldset>
      </form>

    </div>
    <footer class="panel-footer">
        <div class="author">
            
        </div>
        <div class="config" *ngIf="belongsToUser()">
            <a (click)="onEdit()">Edit</a>
            <a (click)="onDelete()">Delete</a>
        </div>
    </footer>
</article>

poll.component.ts

export class PollComponent {
    @Input() poll: Poll;

    constructor(private pollService: PollService) {}

    votes: any;

    ngOnInit() {
        this.pollService.voted(this.poll, localStorage.getItem('userId')).subscribe(
            data => {
                console.log("DATA:" + data);
                this.votes = data.votes;
                console.log("NGONINIT this.votes: "+ this.votes);
            },
            err => { console.log("NGONINIT ERROR: "+ err) },
            () => { console.log("SUBSCRIBE COMPLETE this.votes: "+ this.votes); }
        );
    }

    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();
    }

    onChoice2() {
      this.pollService.increaseCounter2(this.poll);
      this.onVote2();
    }

    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) {
      let result = "";
      if (this.votes) {
          console.log("THIS.VOTES: "+this.votes);
          for (var i = 0; i < this.votes.length; i ++) {
              if (this.votes[i].poll == this.poll.pollId) {
                  result = "disabled";
                  if (this.votes[i].choice == choice) {
                      result =  "selected";
                  }
              }
          }
      }
      return result;
    }

}

poll.service.ts

voteOn(pollID: string, userID: string, choice: number) {
      var user;
      this.http.get('http://localhost:3000/user/'+userID)
      .map(response => response.json())
      .subscribe(
            json => {
              user = JSON.parse(json),
              console.log("USER :"+user);
              if (user.votes == undefined) {
                user.votes = [{pollID, choice}];
              } else {
                user.votes.push({pollID, choice});
              }
              const body = user;
              const headers = new Headers({'Content-Type': 'application/json'});
              const token = localStorage.getItem('token')
                  ? '?token=' + localStorage.getItem('token')
                  : '';
              return this.http.patch('http://localhost:3000/user/'+token, body, {headers: headers})
                  .map((response: Response) => response.json())
                  .catch((error: Response) => {
                      this.errorService.handleError(error);
                      return Observable.throw(error);
                  })
                  .subscribe();
            }
       )
    }

    voted(poll: Poll, userID: string) {
        const headers = new Headers({'Content-Type': 'application/json'});
        return this.http.get('http://localhost:3000/user/'+userID,{headers: headers})
                        .map(response => response.json());
    }

routes/user.js

router.patch('/', function (req, res, next) {
    var decoded = jwt.decode(req.query.token);
    User.findById(decoded.user._id, function (err, user) {
      user.votes = req.body.votes;
      user.save(function(err, result) {
          if (err) {
              console.log("ERROR: "+err);
              return res.status(500).json({
                  title: 'An error occurred',
                  error: err
              });
          }
          res.status(201).json({
              poll: 'Vote Saved',
              obj: result
          });
      });
   });
});



via Coder1000

No comments:

Post a Comment