2017-05-28 5 views
-1

Vous devez être authentifié pour voter lors d'un sondage. Lorsque vous votez sur un sondage, il y a 2 questions:Pourquoi les options de vote ne sont-elles pas correctement présélectionnées?

  1. Vous pouvez voter un nombre infini de fois jusqu'à ce que vous ou recharger la page

  2. Lorsque vous rechargez la page, vous finalement empêché de vote, mais au lieu d'avoir l'option que vous avez votée sur pré-sélectionné, c'est toujours la deuxième option qui est présélectionnée.


CE QUI DEVRAIT ARRIVER:

Inscription/Connexion, puis voter lors d'un scrutin. Au moment où vous cliquez sur une option, le choix de vote par sondage que vous avez fait est verrouillé et vous ne pouvez pas voter davantage sur ce sondage.


COMMENT LE FLUX DE TRAVAUX MON CODE DE COURANT:

Lorsqu'un utilisateur clique sur une option, le compteur augmente et le vote est alors enregistré dans un tableau qui est poussé à l'objet utilisateur dans la base de données. Lorsque le composant est chargé, les données de la base de données pour les votes de l'utilisateur actuellement connecté sont enregistrées via la méthode ngOninit() dans la variable locale votes qui est ensuite utilisée pour vérifier quel sondage l'utilisateur a déjà voté et quel vote il a fait. Le problème est que le choix est fait toujours choice2 quand ce n'est pas le cas.

Je comprends pourquoi vous pouvez voter plusieurs fois jusqu'à ce que la page soit rechargée, mais je ne sais pas comment verrouiller immédiatement le sondage après le vote de l'utilisateur, sur le client et sur le backend (empêcher plus de votes si l'utilisateur a déjà voté sur le sondage).

Quant à savoir pourquoi c'est déjà le deuxième choix qui est présélectionné, je n'en ai aucune idée.


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> 

COMPOSANTE

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 après avoir sauvé 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 
      }); 
     }); 
    }); 
}); 
+1

Veuillez ne pas restaurer les corrections valides à la publication. Les questions ne doivent pas contenir de meta cruft. Si vous voulez discuter de cette politique, rendez-vous sur [meta]. –

Répondre

1

Ok, d'abord vos boutons radio ne reçoivent pas désactivé, parce que vous ne mettez pas à jour les votes-tableau dans votre poll.component.ts un vote.

Je ne suis pas sûr que ce soit une bonne solution ou non:

Dans votre poll.service.ts:

voteOn(pollID: string, userID: string, choice: number) { 
    var user; 
    return new Promise((resolve) => { //Create a new promise to wrap the Subscriptions 
    this.http.get('http://localhost:3000/user/' + userID) 
     .map(response => response.json()) 
     .subscribe(
     json => { 
      user = JSON.parse(json); 
      if (user.votes == undefined) { 

      ... 

       .catch((error: Response) => { 
        this.errorService.handleError(error.json()); 
        return Observable.throw(error); 
       }).subscribe(() => { 
        resolve(user.votes); // <- Resolve your promise 
       }) 
     } 
     ) 
     }); 
} 

Et dans votre poll.component.ts:

voteOn(...).then((votes) => { 
    this.votes = votes; // To update your votes array 
    this.updateVote(); 
}) 

Je ne recommande pas appeler des fonctions dans des liaisons, car il arrive que les fonctions s'appellent très souvent "pour détecter des changements", comme dans vos composants. donc je modifier le code de manière suivante:

Dans votre poll.component.ts:

vote:any //Added to your poll component 


updateVote() { 
    this.vote = this.votes.find((vote) => { 
     return vote.pollID === this.poll.pollID; 
    }); 
} 

Vous devez appeler cette méthode dans votre méthode ngOnInit:

this.pollService.voted(localStorage.getItem('userId')).subscribe(
     data => { 
      var result = JSON.parse(data); 
      this.votes = result.votes; 
      this.updateVote(); // <- To select the vote of this poll 
     }, 
     err => { console.log("NGONINIT ERROR: " + err) }, 
     () => { } 
    ); 

Et dans votre poll.component.html:

<fieldset [disabled]="vote"> 
     {{ poll.counter1 }} votes <input type="radio" id="{{ poll.choice1 }}" name="my_radio" value="{{ poll.choice1 }}" (click)="onChoice1(form)" [checked]="vote?.choice == 1"> {{ poll.choice1 }} 
     <br> 
     {{ poll.counter2 }} votes <input type="radio" id="{{ poll.choice2 }}" name="my_radio" value="{{ poll.choice2 }}" (click)="onChoice2(form)" [checked]="vote?.choice == 2"> {{ poll.choice2 }} 
    </fieldset> 

Mais si vous ne voulez pas changer votre code de cette manière, dites-le moi, donc je peux vous fournir une autre solution.

+0

Comme promis, je vais vous attribuer une prime de 50 rep quand le SO me le permet (en moins de 48 heures). Merci pour votre réponse! – Coder1000