0

https://jsbin.com/yikobayuqa/edit?html,js,output

I have two blocks of checkboxes buttons i need to toggle between based on what the value of a radio button reads.

The code i have written gets shows each block if the rel. radio has been selected, but it doesn't hide when the other radio button is selected which is what i am trying to get it to do..

The contents of the controller

$scope.choosenTopLevelReason = false;
$scope.reportTopLevelReasons = [{
    title: "I do not think this should be on this site.",
    subReasons:[{
        title: "It is pornography",
        on: false
    },{
        title: "It is distasteful",
        on: false
    },{
        title: "It is spam",
        on: false
    }]
},{
    title: "This does not interest me",
    subReasons:[{
        title: "Hide this",
        on: false
    }]
}];

The HTML partial

    <ul>
      <li ng-repeat="reportTopLevelReason in reportTopLevelReasons">
        <label><input type="radio" name="topLevelReason" value="{{reportTopLevelReason.title}}" ng-model="choosenTopLevelReason"> {{reportTopLevelReason.title}}</label>
        <ul ng-show="choosenTopLevelReason == reportTopLevelReason.title">
          <li ng-repeat="subReason in reportTopLevelReason.subReasons">
            <label>
              <input type="checkbox" ng-model="subReason.on" ng-checked="subReason.on">
              {{subReason.title}}
            </label>
          </li>
        </ul>
      </li>
   </ul>

Could anyone assist?

  • Are you only working with two radio selections? You can add an ng-hide to each of them referring to the other one's conditional. So when one shows the other must hide – vkuo Aug 23 '15 at 15:58
  • I tried adding an ng-hide on the child ul but that failed to work.. i don't understand why.. –  Aug 23 '15 at 16:04
  • $scope.chosenTopLevelReason as a bool i think is irrelevant here, i set as empty string just in case but now joy. Bascially, hide the child ul when the parent radio is not select is what i am trying to achieve. Check out the jsbin.. it makes little sense to me –  Aug 23 '15 at 16:05

1 Answers1

0

This is occurring due to the way that JavaScript Prototype Inheritance affects $scope.

Specifically, you are binding to a primitive object $scope.choosenTopLevelReason. Each iteration of ng-repeat creates a new inherited scope, and assigning to chosenTopLevelReason within the ng-repeat hides the parent primitive. Therefore, each radio button is viewing it's own copy of chosenTopLevelReason.

Changing this to an object instead of a primitive solves this issue.

$scope.choosenTopLevel = {};


<li ng-repeat="reportTopLevelReason in reportTopLevelReasons">
    <label><input type="radio" name="topLevelReason"
                  value="{{reportTopLevelReason.title}}" 
                  ng-model="choosenTopLevel.Reason">
        {{reportTopLevelReason.title}}</label>
    <ul ng-show="choosenTopLevel.Reason == reportTopLevelReason.title">
....

https://jsbin.com/sojolacumo/1/edit?html,js,output

Also, your <input> element in this example is malformed (missing </input>), though that isn't causing an issue here.

I recommend thoroughly reading What are the nuances of scope prototypal / prototypical inheritance in AngularJS? for a deep dive into exactly why the primitive is acting the way it is in this scenario.

Community
  • 1
  • 1
Claies
  • 22,124
  • 4
  • 53
  • 77
  • @John this is a case where the angular mantra "always use a dot in ng-model" is most appropriate; I try to go one step further and teach / encourage people to use the Controller As syntax, since that syntax automatically creates object scopes. – Claies Aug 23 '15 at 18:50