4

I'm currently experimenting with Angular and I have an issue, I have a set of questions from my API, some of them rely on other ones to be checked as yes when its a radio button question and will have a value in the property called ReliesOnID.

Once I check yes, the question which relies on the current one being checked needs to show.

I come from a jQuery background so I would do a function passing in the reliesonid as that will be the question number and do something like $('#question' + reliesonid').show().

How can I make the radio buttons show the other question when I click yes as they are in a repeat? Been stuck on this for ages so help is greatly appreciated. Here is my code below:

<div id="question{{question.Number}}" ng-repeat="question in questions" ng-class="question.ReliesOnID == null ? 'here' : 'hidden'">
    <div ng-if="question.QuestionTypeID == 3" >
        <div class="row">
            <div class="col-xs-12">
                <h5>{{question.Question}}</h5>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-2">
                <div class="col-xs-4"></div>
                <div class="col-xs-8">
                    <input type="radio" value="yes" name="{{question.Number}}"  /><label>Yes</label>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-2">
                <div class="col-xs-4"></div>
                <div class="col-xs-8">
                    <input type="radio" value="no" name="{{question.Number}}" /><label>No</label>
                </div>
            </div>
        </div>
    </div>
    <div ng-if="question.QuestionTypeID == 1">
        <div class="row">
            <div class="col-xs-12">
                <h5>{{question.Question}}</h5>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-4">
                <input type="text" class="form-control" />
            </div>
        </div>
    </div>
</div>


EDIT: Data structure is:
{
    "Active": true,
    "Comments": false,
    "DecimalPlaces": 0,
    "F": false,
    "FP": false,
    "Grouped": null,
    "ID": 20500,
    "Length": false,
    "MP": true,
    "Multiline": false,
    "Number": 45,
    "NumericOnly": false,
    "Optional": false,
    "Question": "How long ago was the treatment?",
    "QuestionID": 45,
    "QuestionSectionID": 2,
    "QuestionTypeID": 2,
    "QuestionnaireID": 298,
    "ReliesOnAnswer": true,
    "ReliesOnID": 44,
    "Weight": false
}
RPichioli
  • 3,245
  • 2
  • 25
  • 29
Will2070
  • 41
  • 1
  • 4
  • More explanation of the problem please. The question is not clear. – Rishul Matta Sep 13 '16 at 11:30
  • The problem is that i cannot show a question when i click on the yes radio button. So this question would have an id of question42 so i need to do find that element and show it on click of the radio button. In jquery i would have done something like function test(reliesonid) { $('#question' + reliesonid).show();} – Will2070 Sep 13 '16 at 11:33
  • @Will2070 Can you show us your jsfiddle to see the dependency of your questions, if possible show us your json object. – Mohit Tanwani Sep 13 '16 at 12:16
  • @Loading.. i've added the JSON object of a question above. THe relies on questionid is the number of the question that it relies on which is the Number property – Will2070 Sep 13 '16 at 12:33
  • @Will2070 I consider this json will be in ng-repeat as questions, and there will be each radio for each question, and once I check it yes, it will show the question with 44, is it ? – Mohit Tanwani Sep 13 '16 at 12:43
  • @Loading.. Correct thats what i want to happen i just dont know how to do it – Will2070 Sep 13 '16 at 12:50
  • please share your controller code. – Tavitos Sep 13 '16 at 13:44

4 Answers4

1

You need to use ng-model for your answers like:
<input type="radio" value="yes" ng-model="question.Answer" name="{{question.Number}}"/><label>Yes</label>

And then inside that question you could have sub questions and would just use ng-repeat.

ng-if="question.subQuestions && question.Answer !== undefined" ng-repeat="subquestion in question.subQuestions"

This will all depends on your question structure of course

EDIT
Based on your structure I would say you need an ng-if in your ng-repeat that could go something like this:
ng-if="!question.ReliesOnID || wasAnswered(question.ReliesOnID)"

In wasAnswered function you would need access to the questions array and filter for that ID and check if it was answered and return true or false

taguenizy
  • 2,140
  • 1
  • 8
  • 26
1

Try this snippet.

Is it something, you're looking for?

I tried to understand your question, and created an example based on your JSON data structure.

Based on the selection of particular question, it will show it's answer only.

Edit-1 : Applied Angular Element

If jQuery is available, angular.element is an alias for the jQuery function. If jQuery is not available, angular.element delegates to Angular's built-in subset of jQuery, called "jQuery lite" or jqLite.

More information angular.element

You can do eliminate jQuery from code, if you want.

You can do the set / get class in Angular by using angular.element as shown over here.

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

myApp.controller('GreetingController', ['$scope', function($scope) {
  $scope.questions = [
    {
    "Active": true,
    "Comments": false,
    "DecimalPlaces": 0,
    "F": false,
    "FP": false,
    "Grouped": null,
    "ID": 20500,
    "Length": false,
    "MP": true,
    "Multiline": false,
    "Number": 45,
    "NumericOnly": false,
    "Optional": false,
    "Question": "How long ago was the treatment?",
    "QuestionID": 45,
    "QuestionSectionID": 2,
    "QuestionTypeID": 2,
    "QuestionnaireID": 298,
    "ReliesOnAnswer": true,
    "ReliesOnID": 10,
    "Weight": false,
    "Answer": '2 years ago'
    },
    {
    "Active": true,
    "Comments": false,
    "DecimalPlaces": 0,
    "F": false,
    "FP": false,
    "Grouped": null,
    "ID": 20500,
    "Length": false,
    "MP": true,
    "Multiline": false,
    "Number": 45,
    "NumericOnly": false,
    "Optional": false,
    "Question": "Who is God of cricket?",
    "QuestionID": 45,
    "QuestionSectionID": 2,
    "QuestionTypeID": 2,
    "QuestionnaireID": 298,
    "ReliesOnAnswer": true,
    "ReliesOnID": 20,
    "Weight": false,
    "Answer": 'Sachin Tendulkar'
    }
  ]
  
  //Function when radio button clicked
  $scope.flagChange = function(){
    var reliesId = angular.element(event.target).attr('data-reli-id');
    var value = angular.element(event.target).attr('data-value');
    //Based on the condition it will show / hide the respective element
    if(value == "yes")
    {
      $('#'+reliesId).removeClass('hide').addClass('show');
    }
    else
    {
      $('#'+reliesId).removeClass('show').addClass('hide');
    }
  }
}]);
.show
{
  display: block; 
}
.hide
{
  display: none; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="GreetingController">
  <div ng-repeat="question in questions track by $index">
        {{question.Question}}
        <input type="radio" name="Flag_{{$index}}" ng-click="flagChange($event)" data-value="yes" data-reli-id='{{question.ReliesOnID}}' />Yes
        <input type="radio" name="Flag_{{$index}}" ng-click="flagChange($event)" data-value="no" data-reli-id='{{question.ReliesOnID}}' />No
        <span ng-show="custom_$index">{{question.Answer}}</span>
    <br/>
        <div id="{{question.ReliesOnID}}" class="hide">
            Question based on ReliesOnID : {{question.ReliesOnID}}
        </div>
    <br/>
  </div> 
</div>
Community
  • 1
  • 1
Mohit Tanwani
  • 6,608
  • 2
  • 14
  • 32
  • This is good and is on the right line but not what im looking for. For exmaple you have two radio buttons. One is yes and the other is no. If yes is checked it needs to check if the current question has a reliesonid and if it does it needs to find the question and show it. For example in jquery i would do function toggleQuestion(reliesonid){ $('#question' + reliesonid').show();} They also need to be radio buttons not checkboxes – Will2070 Sep 13 '16 at 12:55
  • @Will2070 I've edited my answer, please check now. based on the selection of Radio button it will show the div of relies id.. This is just an example, You can make changes as per your need. – Mohit Tanwani Sep 13 '16 at 13:13
  • Interesting way how to do it @Loading.. it's a bit more JQUERY style of work but you got my thumbup – Andurit Sep 13 '16 at 13:26
  • @Andurit : Thanks for thumb-up, angular.element is quite useful when you're looking to have more dynamic elements with complex HTML structure, and other option is you can apply multiple dynamic ng-models. – Mohit Tanwani Sep 13 '16 at 13:28
  • @Loading.. Thanks for this however its still not quite there, when you click on yes it needs to show the actual question element, so questions with a reliedonid are hidden on load and then when i click yes it needs to show that question below which may be another radio button question with a yes or no etc. – Will2070 Sep 13 '16 at 13:37
  • Thanks for your message @Will2070 Please try to understand the concept what we're trying to make you understand. Don't go and wait for the exact answer what you're looking for. I tried to explain you the each scenario to achieve that. So now please try it your self with the help of answers and understanding I've made for you :) – Mohit Tanwani Sep 13 '16 at 13:38
  • @Will2070 As it seems that you're already knowing how the jQuery is working, and now I got you idea how we can use jQuery method in Angular and shown in respected example. So you can do the necessary changes in the code / manipulation in element based on your need. Create a jsfiddle and share with me if you still find any problem with it. – Mohit Tanwani Sep 13 '16 at 13:42
0

Edit: based on comments below and provided data structure:

If assumed that you want to iterate just that questions which are parent and doesn't related on anything at start. Related should be display only when ratio is set on true:

So replace yourng-repeat with ng-repeat-start which will make you able iterate multiple divs not just on where ng-repeat is on.

In your <div> element add :

 <input type="radio" ng-model="question.subQuestion" value="true"> <br/>
 <input type="radio" ng-model="question.subQuestion" value="false"> <br/>

After that make another <div> below which will display your related questions. It can looks like:

// ng-if here to display only when radio was set to true
<div class="relatedQuestion" ng-repeat-end ng-if="question.subQuestion">
  <div ng-repeat="relatedQ in getRelatedQuestion(question.Number)">
    // Here you display your related questions
  </div>
</div>

So in your controller you need to add a function:

function getRelatedQuestion(number) {
  // logic comes here which filter question
  // which have property relatedOnId === number;
  // it should be an array of objects to iteratee over it.
}


What you present as an option from JQUERY is possible in angular as well. However there is prolly even easier solution.

In your ng-repeat solution you replace your radio input with something like:

 <input type="radio" ng-model="question.subQuestion" value="true"> <br/>
 <input type="radio" ng-model="question.subQuestion" value="false"> <br/>

And then below you add this:

 <div ng-if="question.subQuestion">
     // Your subQuestion code comes here
 </div>

Everything will be inside of your ng-repeat and should work correctly without additional logic in controller.

Andurit
  • 5,612
  • 14
  • 69
  • 121
  • so does this mean i need to attach a property to the question scope called subquestion? – Will2070 Sep 13 '16 at 11:34
  • I will answer on this with another question. How does you know that your question have subquestion? – Andurit Sep 13 '16 at 11:35
  • The question has a property called reliesonid and if that is not equal to null then it relies on another. – Will2070 Sep 13 '16 at 11:43
  • Okey I have something in my head but just to make sure can you provide example data structure for questions? I will edit my answer afterr – Andurit Sep 13 '16 at 11:48
  • A question consists of this: Active : true Comments : false DecimalPlaces : 0 F : false FP : false Grouped : null ID : 20500 Length : false MP : true Multiline : false Number : 45 NumericOnly : false Optional : false Question : "How long ago was the treatment? " QuestionID : 45 QuestionSectionID : 2 QuestionTypeID : 2 QuestionnaireID : 298 ReliesOnAnswer : true ReliesOnID : 44 Weight : false – Will2070 Sep 13 '16 at 11:50
  • cool, thank you. I edited your question to add that data structure in JSON there. My last question is: Is ReliesOnID the UNIQUE QUESTION ID to which it relies? – Andurit Sep 13 '16 at 12:21
  • ReliesOnID is the QUESTION NUMBER not the question id that it relies on :) – Will2070 Sep 13 '16 at 12:30
  • I edited my answer :), please have a look. It doen't contains working snippet but logic how you should do something like this. – Andurit Sep 13 '16 at 13:11
0

I dont like to use ng-if as that adds and removes the elements to the DOM. Below is a link to the ng-show/hide and a tutorial on how to use it on scotch.io.

https://docs.angularjs.org/api/ng/directive/ngShow

https://scotch.io/tutorials/how-to-use-ngshow-and-nghide

So a quick example would be below where the div element will only show when the variable is_active is true(this check can work with booleans or a text check). And this variable can be set in the controller or in the view. You dont need to toggle this. The div will automaticall hide when the evaluation is not true; so no need for a ng-hide and ng-show on the same element unless you are checking against multiple conditions.

<input type="radio" ng-model="question.subQuestion" value="true"> <br/>
 <input type="radio" ng-model="question.subQuestion" value="false"> <br/>

 <div ng-show="question.subQuestion">
     // Your subQuestion code comes here
 </div>
Ross Rawlins
  • 603
  • 8
  • 22