SeleM
SeleM

Reputation: 9638

Check only one checkbox (radio buttons behavior) within an *ngFor loop

I have a Quizz module developed in Angular2, so merely some questions with proposed answers and you have to check only one answer , I know radio buttons can handle the situation but i want it to be checkboxes with a radio button behavior, the issue is that i did a part of the job but since it is more complicated within an *ngFor loop , once i check a B-Question answer the A-Question checked answer will be unchecked and so on. Here is my HTML :

<div *ngFor="#qt of listQuestion"><h3 class="uk-accordion-title" >{{qt.wordingQ}}</h3>

           <div class="uk-accordion-content">

    <input type="checkbox" class="cb"  id="0" [(ngModel)]="qt.chp[0]" onchange="cbChange(this)" />

    <label for="0" class="inline-label" > <b>{{qt.lpo[0]}}</b></label><br><br>

    <input type="checkbox" class="cb"   id="1" [(ngModel)]="qt.chp[1]" onchange="cbChange(this)" />

    <label for="1" class="inline-label"><b>{{qt.lpo[1]}}</b></label><br><br>

    <input type="checkbox" class="cb"   id="2" [(ngModel)]="qt.chp[2]" onchange="cbChange(this)"/>

    <label for="2" class="inline-label"> <b>{{qt.lpo[2]}}</b></label><br><br>

    <input type="checkbox" class="cb"  id="3" [(ngModel)]="qt.chp[3]" onchange="cbChange(this)"/>

    <label for="3" class="inline-label"><b>{{qt.lpo[3]}}</b></label>

                               </div></div>

And here is the Script making the solo-checking way :

<script>
  function cbChange(obj) {
    var cbs = document.getElementsByClassName("cb");
    for (var i = 0; i < cbs.length; i++) {
      cbs[i].checked = false;
    }
    obj.checked = true;
  }
</script>

As you can see it is an *ngFor loop to load a list of questions ; every question has a list of propositions (lpo[i]) and the [(ngModel)]="qt.chp[i]" is for taking the status of every proposition (checked proposition) , I think i have to refer every onchange function to every unique ngModel (as it is in indexing) but i do not know how. Any help Please ? (Here is a real image of the situation)

enter image description here

Upvotes: 2

Views: 2275

Answers (1)

Harry Ninh
Harry Ninh

Reputation: 16728

In your situation, because only one answer should be selected for each question, I suggest you to not use boolean field in answer-level to indicate selection. Rather, you should store the selected answer in question-level. Something like this:

class Question {
    wording: string;
    answers: string[];

    selectedAnswer: string;

    selectAnswer(ans: string) {
        this.selectedAnswer = ans;
    }
}

In future, you can easily change the selectedAnswer property and selectAnswer function implementation to cater multiple selections if needed. The question template then needs to be modified a little bit to accommodate the change:

<div *ngFor="let question of questions">
  <p>{{question.wording}}</p>
  <div *ngFor="let answer of question.answers; let aIndex = index">
    <input type="checkbox" class="cb" id="{{aIndex}}" [ngModel]="answer === question.selectedAnswer" (ngModelChange)="question.selectAnswer(answer)" />
    <label for="{{aIndex}}" class="inline-label" > <b>{{answer}}</b></label><br><br>
  </div>
</div>

Here is the runnable plunker: http://plnkr.co/edit/xMTtFp31rU2ZqCtV8JO1?p=preview

Upvotes: 2

Related Questions