Skip to content Skip to sidebar Skip to footer

Ng-repeat Hiding Radio Button Based On Radio Answer Selected

I need some help trying to figure out how to hide answers if other answers are selected when items are in ng-repeat block. For instance in the below code. If a user selects answe

Solution 1:

A straight-forward way would be to augment your 'answer' data structures with two new arrays, 'hides' and 'removes', which upon selection would disable or by case remove the targeted answers of other questions. For example,

...
Answer: [{
  answertxt: "answer11",
  aId: 83493,
  hides: [{
    qid: 5678,
    aId: 67107
  }],
  removes: [{
    qid: 4321,
    aId: 32342
  }]
},
...

answer11 hides answer22 and removes answer31.
Your html would then boil down to the following display logic:

<div ng-repeat="answer in question.Answer">
  <div ng-if="!answer.isRemoved">
    <input type="radio"
           ng-change="select(question, answer)"
           ng-disabled="answer.isDisabled"
           ng-model="question.selectedAnswer" 
           ng-value="answer.answertxt" />
    <strike ng-if="answer.isDisabled">{{answer.answertxt}}</strike>
    <span ng-if="!answer.isDisabled">{{answer.answertxt}}</span>
  </div>
</div>

where the isRemoved and isDisabled flags are set on answer selection in select(question, answer).

Full working example:

var app = angular.module('plunker', []);


app.controller('MainCtrl', ['$scope',
  function($scope) {
    
    function getAnswer(qid, aid) {
        var qs = $scope.questions, q;
        for (var i = 0; i < qs.length; ++i) {
          if (qs[i].qid === qid) {
            q = qs[i];
            break;
          }
        }
        if (q) {
          var as = q.Answer;
          for (i = 0; as.length; ++i) {
            if (as[i].aId === aid) {
              return as[i];
            }
          }
        }
    }
    
    function doHide(q, a) {
      if (a.hides && a.hides.length) {
        for (var i = 0; i < a.hides.length; ++i) {
          var h = a.hides[i],
              answer = getAnswer(h.qid, h.aId);
          if (answer) {
            answer.isDisabled = (q.selectedAnswer == a.answertxt);
          }
        }
      }
    }
    
    function doRemove(q, a) {
      if (a.removes && a.removes.length) {
        for (var i = 0; i < a.removes.length; ++i) {
          var r = a.removes[i],
              answer = getAnswer(r.qid, r.aId);
          if (answer) {
            answer.isRemoved = (q.selectedAnswer == a.answertxt);
          }
        }
      }
    }
    
    $scope.select = function (q, a) {
      var as = q.Answer;
      
      for (var i = 0; i < as.length; ++i) {
        var answer = as[i];
        doHide(q, answer);
        doRemove(q, answer);
      }
    };

    $scope.questions = [{
        questiontxt: 'Please select your Age range',
        qid: 1234,
        Answer: [{
          answertxt: "answer11",
          aId: 83493,
          hides: [{
            qid: 5678,
            aId: 67107
          }],
          removes: [{
            qid: 4321,
            aId: 32342
          }]
        }, {
          answertxt: "answer12",
          aId: 1223,
          removes: [{
            qid: 4321,
            aId: 79130
          }]
        }, {
          answertxt: "answer13",
          aId: 1223
        }]
      },
      {
        questiontxt: 'Please select your favorite activity',
        qid: 5678,
        Answer: [{
          answertxt: "answer21",
          aId: 90886
        }, {
          answertxt: "answer22",
          aId: 67107
        }]
      },
      {
        questiontxt: 'Please select your favorite food',
        qid: 4321,
        Answer: [{
          answertxt: "answer31",
          aId: 32342
        }, {
          answertxt: "answer32",
          aId: 79130
        }]
      }
    ];
  }
]);
<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.14/angular.js" data-semver="1.3.14"></script>
  <script src="script.js"></script>
</head>

<body ng-controller="MainCtrl">
  <div ng-repeat="question in questions">
    <div class="row">
      <br/><span>Q{{$index+1}}. {{question.questiontxt}}</span>
    </div>
    <div ng-repeat="answer in question.Answer">
      <div ng-if="!answer.isRemoved">
        <input type="radio"
          ng-change="select(question, answer)"
          ng-disabled="answer.isDisabled"
          ng-model="question.selectedAnswer" 
          ng-value="answer.answertxt" />
          <strike ng-if="answer.isDisabled">{{answer.answertxt}}</strike>
          <span ng-if="!answer.isDisabled">{{answer.answertxt}}</span>
      </div>
    </div>
  </div>

</body>

</html>

Solution 2:

Could add a property like:

disables: [{ selectedAnswer: 83493,otherQ: 5678, otherAnswerId: 90886 }]

to each question along with ng-disbled and ng-change to each radio

The methodology is to look at all the disables above and then check the corresponding other question and other answer and see if the currently selected answer matches the selectedAnswer in the disable object

var app = angular.module('plunker', []);


app.controller('MainCtrl', ['$scope',
  function($scope) {

    $scope.disableMatches = function(question, answer) {
      let selectedId = question.selectedAnswer;
      question.disables.forEach(function(o) {
        let otherQ = $scope.questions.find(function(q) {
          return q.qid == o.otherQ
        });
        let otherAnswer = otherQ.Answer.find(function(ans) {
          return ans.aId === o.otherAnswerId
        })
        otherAnswer.disabled = selectedId == o.selectedAnswer;
      });
    }

    $scope.questions = [{
        questiontxt: 'Please select your Age range',
        qid: 1234,
        disables: [{
          selectedAnswer: 83493,
          otherQ: 5678,
          otherAnswerId: 90886
        }],
        Answer: [{
          answertxt: "answer11  Disables answer 21",
          aId: 83493
        }, {
          answertxt: "answer12",
          aId: 1223
        }, {
          answertxt: "answer13",
          aId: 1223
        }]
      },
      {
        questiontxt: 'Please select your favorite activity',
        qid: 5678,
        Answer: [{
          answertxt: "answer21",
          aId: 90886
        }, {
          answertxt: "answer22",
          aId: 67107
        }]
      },
      {
        questiontxt: 'Please select your favorite food',
        qid: 4321,
        Answer: [{
          answertxt: "answer31",
          aId: 32342
        }, {
          answertxt: "answer32",
          aId: 79130
        }]
      }
    ];
  }
]);
<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.14/angular.js" data-semver="1.3.14"></script>
  <script>
  </script>
</head>

<body ng-controller="MainCtrl">
  <div ng-repeat="question in questions">
    <div class="row">
      <br/><span>Q{{$index+1}}. {{question.questiontxt}}</span>
    </div>
    <div ng-repeat="answer in question.Answer">
      <label>
      <input type="radio"
      name="radio{{$parent.$index}}"
      ng-change="disableMatches(question)"
      ng-disabled="answer.disabled"
      ng-model="question.selectedAnswer" 
      ng-value="{{answer.aId}}" />{{answer.answertxt}}</label>
    </div>
  </div>

</body>

</html>

Post a Comment for "Ng-repeat Hiding Radio Button Based On Radio Answer Selected"