NixxyStixx
NixxyStixx

Reputation: 43

MVC Looped RadioButtonList style with grouping

I'm looping through some questions to print out on the page, Each question needs 5 radio buttons numbered 0 to 5.

Currently they work as expected (if a little rough) Like so:

<table>
<tr>
@for (int i = 0; i < Model.Questions.Count; i++)
        { <td style="width:80px; padding-left: 10px;">
                    <label for="q1-0" class="rblBreq">@Html.RadioButtonFor(m => m.PatientQuestions[i].Answer, "0") 0</label>
                </td>
                @*middle*@
                <td style="width:80px; padding-left: 10px;">
                    <label for="q1-1" class="rblBreq">@Html.RadioButtonFor(m => m.PatientQuestions[i].Answer, "1") 1</label>
                </td>
                <td style="width:80px; padding-left: 10px;">
                    <label for="q1-2" class="rblBreq">@Html.RadioButtonFor(m => m.PatientQuestions[i].Answer, "2") 2</label>
                </td>
                <td style="width:80px; padding-left: 10px;">
                    <label for="q1-3" class="rblBreq">@Html.RadioButtonFor(m => m.PatientQuestions[i].Answer, "3") 3</label>
                </td>
                @*last*@
                <td style="width:80px; padding-left: 10px;">
                    <label for="q1-4" class="rblBreq">@Html.RadioButtonFor(m => m.PatientQuestions[i].Answer, "4") 4</label>
                </td>
            </tr>
        }
    </table>

What I'm trying to do is add some styling like the ones on cssCheckBox.com

However when i try this using the example the grouping no longer works e.g. pressing checkbox_2 , checkbox_3 or checkbox_1 always causes checkbox_0 to be checked...

I have tried using (mvc)LabelFor's but this doesn't work, assuming due the id's etc being the same across all check boxes.

<td style="width:80px; padding-left: 10px;">
@Html.RadioButtonFor(m => m.PatientQuestions[i].Answer, "1", new { @class = "css-checkbox" })
@Html.LabelFor(m => m.PatientQuestions[i].Answer, "1", new { @class = "css-label" })
</td>

Any idea's on how to get styling / grouping working with a list of radio buttons would be great.

Upvotes: 4

Views: 117

Answers (1)

adricadar
adricadar

Reputation: 10219

The problem is that all the answers, for a question, have same id, to solve this you need to generate unique ids for each answer. A solution based on your code will look like below.

<table>
    @for (int i = 0; i < Model.Questions.Count; i++)
    {
        <tr>
            @{
                int answersCount = 5;
                for (int answerIndex = 0; answerIndex < answersCount; answerIndex++)
                {
                    var answerId = String.Format("Question_{0}_{1}", i, answerIndex);
                    <td style="width: 80px; padding-left: 10px;">
                        @Html.RadioButtonFor(m => m.PatientQuestions[i].Answer, answerIndex.ToString(), new { @class = "css-checkbox", @id = answerId })
                        @Html.LabelFor(m => m.PatientQuestions[i].Answer, answerIndex.ToString(), new { @class = "css-label", @for = answerId })
                    </td>
                }
            }
        </tr>
    }
</table>

What is the difference?

Problem: Let's see the original html code resulting.

<td style="width:80px; padding-left: 10px;">
    <input class="css-checkbox" id="PatientQuestions_0__Answer" name="PatientQuestions[0].Answer" value="1" type="radio">
    <label class="css-label" for="PatientQuestions_0__Answer">1</label>
</td>

<td style="width:80px; padding-left: 10px;">
    <input class="css-checkbox" id="PatientQuestions_0__Answer" name="PatientQuestions[0].Answer" value="2" type="radio">
    <label class="css-label" for="PatientQuestions_0__Answer">2</label>
</td>
 ....

input[type=radio].css-checkbox {
  position: absolute;
  z-index: -1000;
  left: -1000px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  height: 1px;
  width: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
}
input[type=radio].css-checkbox + label.css-label {
  padding-left: 20px;
  height: 15px;
  display: inline-block;
  line-height: 15px;
  background-repeat: no-repeat;
  background-position: 0 0;
  font-size: 15px;
  vertical-align: middle;
  cursor: pointer;
}
input[type=radio].css-checkbox:checked + label.css-label {
  background-position: 0 -15px;
}
label.css-label {
  background-image: url(http://csscheckbox.com/checkboxes/u/csscheckbox_7d1e967c68c39221a9ad8a026a805769.png);
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
<table>
  <tr>
    <td style="width:80px; padding-left: 10px;">
      <input class="css-checkbox" id="PatientQuestions_0__Answer" name="PatientQuestions[0].Answer" value="1" type="radio">
      <label class="css-label" for="PatientQuestions_0__Answer">1</label>
    </td>

    <td style="width:80px; padding-left: 10px;">
      <input class="css-checkbox" id="PatientQuestions_0__Answer" name="PatientQuestions[0].Answer" value="2" type="radio">
      <label class="css-label" for="PatientQuestions_0__Answer">2</label>
    </td>
    <td style="width:80px; padding-left: 10px;">
      <input class="css-checkbox" id="PatientQuestions_0__Answer" name="PatientQuestions[0].Answer" value="3" type="radio">
      <label class="css-label" for="PatientQuestions_0__Answer">3</label>
    </td>
    <td style="width:80px; padding-left: 10px;">
      <input class="css-checkbox" id="PatientQuestions_0__Answer" name="PatientQuestions[0].Answer" value="4" type="radio">
      <label class="css-label" for="PatientQuestions_0__Answer">4</label>
    </td>

    <td style="width:80px; padding-left: 10px;">
      <input class="css-checkbox" id="PatientQuestions_0__Answer" name="PatientQuestions[0].Answer" value="5" type="radio">
      <label class="css-label" for="PatientQuestions_0__Answer">5</label>
    </td>
  </tr>
</table>

We notice here that all radio buttons from a group have id=PatientQuestions_0__Answer, the same. And the label is for=PatientQuestions_0__Answer the same id also. This means when you click a label the input with the respective id is selected, but all inputs have same id, that's why only the first one is selected.

Solution: The solution I propose make a unique id for each radio button.

<td style="width: 80px; padding-left: 10px;">
    <input class="css-checkbox" id="Question_0_0" name="PatientQuestions[0].Answer" value="0" type="radio">
    <label class="css-label" for="Question_0_0">0</label>
</td>
<td style="width: 80px; padding-left: 10px;">
    <input class="css-checkbox" id="Question_0_1" name="PatientQuestions[0].Answer" value="1" type="radio">
    <label class="css-label" for="Question_0_1">1</label>
</td>
....

input[type=radio].css-checkbox {
  position: absolute;
  z-index: -1000;
  left: -1000px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  height: 1px;
  width: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
}
input[type=radio].css-checkbox + label.css-label {
  padding-left: 20px;
  height: 15px;
  display: inline-block;
  line-height: 15px;
  background-repeat: no-repeat;
  background-position: 0 0;
  font-size: 15px;
  vertical-align: middle;
  cursor: pointer;
}
input[type=radio].css-checkbox:checked + label.css-label {
  background-position: 0 -15px;
}
label.css-label {
  background-image: url(http://csscheckbox.com/checkboxes/u/csscheckbox_7d1e967c68c39221a9ad8a026a805769.png);
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
<table>
  <tr>
                        <td style="width: 80px; padding-left: 10px;">
                        <input class="css-checkbox" id="Question_0_0" name="PatientQuestions[0].Answer" value="0" type="radio">
                        <label class="css-label" for="Question_0_0">0</label>
                    </td>
                    <td style="width: 80px; padding-left: 10px;">
                        <input class="css-checkbox" id="Question_0_1" name="PatientQuestions[0].Answer" value="1" type="radio">
                        <label class="css-label" for="Question_0_1">1</label>
                    </td>
                    <td style="width: 80px; padding-left: 10px;">
                        <input class="css-checkbox" id="Question_0_2" name="PatientQuestions[0].Answer" value="2" type="radio">
                        <label class="css-label" for="Question_0_2">2</label>
                    </td>
                    <td style="width: 80px; padding-left: 10px;">
                        <input class="css-checkbox" id="Question_0_3" name="PatientQuestions[0].Answer" value="3" type="radio">
                        <label class="css-label" for="Question_0_3">3</label>
                    </td>
                    <td style="width: 80px; padding-left: 10px;">
                        <input class="css-checkbox" id="Question_0_4" name="PatientQuestions[0].Answer" value="4" type="radio">
                        <label class="css-label" for="Question_0_4">4</label>
                    </td>
  </tr>
</table>

We can notice that every id is unique and the labels point to the correct radio button.

Why I need a unique id, normal version don't need it? If you look on css code for .css-checkbox you can see that he does everything to hide the radio circle. You end up to see only the label. (when you click the nice looking radio, you click on a label nice looking)

Upvotes: 1

Related Questions