AngularJS – Radio Buttons – Three Scenarios

Introduction

This post will detail how to AngularJS can enhance the usage and functionality of Radio Buttons.

Three scenarios are covered.

  1. Each radio button represents an object. For example, there may be a radio button for each element of an array. When one of the radio buttons is selected, a variable is assigned the corresponding array element. So, a variable called $scope.selectedPerson can be automatically assigned to the selected ‘person’ in an array of ‘person’ objects.
  2. Similar to ‘1’ except instead of selecting a complete object, it’s possible to select just a property of an object. E.g. instead of $scope.selectedPerson, the variable can be $scope.selectedPersonName. This is a simple elaboration on the first scenario purely for emphasis.
  3. This scenario is considerably different. Take elements being added to an array dynamically through a UI, the user adding the elements needs to assign one of them as the default element. This is achieved by setting a property (isDefault = true for example) in the array element object. The other array elements have their isDefault property set to false. Unlike the previous two examples, an external variable is not being set, the elements of the array themselves are being manipulated.

Scenario one: Selecting an array element

HTML

 

AngularJS

 

JSFiddle

http://jsfiddle.net/jralston/yg9xnqr6/

Explanation

An array is created in the controller and rendered in the HTML via the ng-repeat.

There are five important points here.

  1. The ng-value attribute of the checkbox is distinct from the native html value attribute. It recognizes angular objects rather than taking on a simple string value. For example, the value “true” would be interpreted as a boolean true rather than a string “t r u e”. Similarly in this example, the actual person object is taken as the value rather than a string with characters p, e, r, s, o and n.
  2. The ng-model refers to the variable that will take on the selected value. Put simply, the array element selected by the radio button is bound to the variable $scope.selectedPerson.
  3. Note the $parent in the ng-model. The reason for this is because an ng-repeat repeater creates a local or child scope. That scope is isolated. The variable selectedPerson exists in the parent scope (i.e. the controller) so it’s necessary to explicitly specify the $parent scope.
  4. The name attribute for the radio buttons is not required. The presence of the ng-model attribute causes the same end result. i.e. only one can be selected at a time.
  5. Programmatically Selecting

  • In addition to that, when $scope.selectedElement is programmatically assigned, the radio buttons update to reflect the new value. Check out the JsFiddle here: http://jsfiddle.net/jralston/jcmqcmvh/
  • The Select Mary button ng-click handler assigns the array element to $scope.selectedElement. This assignment is reflected in the UI, i.e. the radio button is automatically selected. This is no different to how personArray[0] is assigned as the initial value.

 

Scenario two: Selecting a property of the selected array element

This is virtually identical to the previous scenario. It is simply to compound the point further. Rather than selecting the array element the ng-value attribute allows any property of that array element to be selected.

HTML

 

AngularJS

 

JSFiddle

http://jsfiddle.net/jralston/kjcygr8n/

Explanation

As with scenario one, the ng-repeat causes an iteration over the array items. This time however, the ng-value attribute specifies the ‘name’ property of the ‘person’ array element. So $scope.selectedElement will now take on the value “joe”, “john” or “mary” rather than the whole object. (To that end $scope.selectedElement would be better names as $scope.selectedElementName).

 

Scenario three: Setting a property of the selected array element, un-setting the non-selected array elements

For example, consider an administrator dynamically adding products to a list. When the administrator hits save, the entire list of products is saved. However, the list of products requires that one be the default product. So a purchaser of the products will automatically get the default product unless they choose a different one. E.g. with a laptop, they get 4Mb of RAM by default but can choose 6Mb or 8Mb if they so wish.

To facilitate this Angular loses the concept of selecting an object associated with a radio button. Instead it must set an isDefault property to only the selected element.

HTML

 

AngularJS

 

jsFiddle

http://jsfiddle.net/jralston/czLkf4xu/

Explanation

Here, the notion of value, ng-value and ng-model are dispensed with. A slightly more crude technique is required. An ng-click attribute is applied to each radio button. The corresponding function accepts the array element as a parameter. It then goes about iterating over the array setting the isDefault property to false on all array elements, the finally setting the isDefault property on the selected element to true.

Note the use of ng-class. This is incidental to the example, purely for presentation purposes. The class name is specified on the left of the : It is applied as a class only if the condition on the right of the : evaluates true.

 

Conclusion

AngularJS handles radio buttons at a high level. Instead of selecting primitive form string values as is the way with HTML, AngularJS treats them as object level components, entire objects or array elements can be selected with a radio button. Radio buttons are bound to a model. I.e. the value of whichever radio button is selected is assigned to the model. Therefore, by programmatically setting the model, the radio button selection on the UI will automatically reflect that change, i.e. be programmatically selected.

This point has been compounded by demonstrating that the ng-value attribute is flexible in that it allows a property of an object to be selected rather than the whole object. This is a minor point but it ratifies the awareness of angular’s flexibility.

A third scenario has also been demonstrated. A scenario quite different from the previous, radio buttons in this usage are not bound to a model. Control over what happens when the radio button is clicked is handed over to the programmer. This in our example enabled the manipulation of the array that is bound to the radio buttons. This satisfied the example situation where a default status was assigned to the selected array element and revoked from the other elements.

The examples also provide a brief insight into a phenomenon with regard ng-repeat, how it creates a scope of its own isolated from the parent scope. Accessing variables within the parent are done via the $parent variable.

JSFiddles for each of the three scenarios have been provided.

Comments and questions always welcome.

 

7 Comments

  • This was great. How would one save a radio box entry when going to another view and then returning to the view with the previous radio box entry selected?

    • Hi John

      Are you using a single page application using ngRoute (or alternative) or are you actually going to a different page by traditional means i.e. browser page loading?

  • I have a little bit of complex solution to handle and I solved it partially, but not to an acceptable level. Herewith, I am attaching the code segment and would prefer your input to solve this accurately.

    This is the model

    “questions”: [
    {
    “question_num”: “Q1”,
    “answersList”: [
    {
    “is_correct”: “0”,
    “answer_text”: “Answer 1”,
    “feedback”: “Feedback 1”
    },
    {
    “is_correct”: “0”,
    “answer_text”: “Answer 2”,
    “feedback”: “Feedback 2”
    },
    {
    “is_correct”: “0”,
    “answer_text”: “Answer 3”,
    “feedback”: “Feedback 3”
    },
    {
    “is_correct”: “1”,
    “answer_text”: “Answer 4”,
    “feedback”: “Feedback 4”
    }
    ],
    “question_text”: “Sample Question”
    }
    ]

    This is the solution I concluded.

    However, this is not correctly pre-selecting the correct answer based on the model value.
    Can you advise what needs to be done to solve this.

      • Hi Aviro

        Good to know you found a solution. Sorry for the delayed response.

        Couple of observations with your solution:

        As demonstrated here: http://jsfiddle.net/jralston/vzLqju3y/ the concept of a correct answer and the selected/chosen answer are merged. I don’t think this is a good idea. If you look at the printed ‘question’ object in the example, the ‘is_correct’ property changes to “1” in each item radio clicked so eventually they all become the correct answer which may not be good.

        I think introducing the notion of a “correctAnswer” property to each question along with a “chosenAnswer” is good practice. In this example, things work better: http://jsfiddle.net/jralston/q093jczu/ but that’s just my opinion…..

        John