Question

Question:

How can you use ng-repeat but remove items nested inside the ng-repeat item based upon conditions but NOT the ng-repeat item itself? Hiding the item is not enough. It needs to be removed. I'm not too great at Angular.

In depth background/what I've tried:

I'm working on a project where we're switching to Angular. Previously, it was a hodgepodge of several different technologies.

There is a form that is generated based on the response from a REST service. This service has a response like:

{
   "questions": [{
       "type": "multiplechoice",
       "question": "how are you?",
       "answers": [{
          "text": "bad",
          "value": 0
       }, {
          "text": "good",
          "value": 1
       }]
   }, {
       "type": "text",
       "question": "write a word"
   }, {
       "type": "date",
       "question": "pick a date"
   }]
}

Depending on question type, some HTML is written in JS and appended to the DOM. Since our workflow involves an authorable solution wherein others can modify the HTML without worrying about anything else, I thought it would be better NOT to write HTML in the JS (among other reasons). I thought it would be better to have a static HTML template which is populated with the response at runtime, but still on the page without the service running so that it can be authored.

<div class="multiplechoice">
    <label><input type="checkbox" value="{{question.value}}"> {{question.text}}</label>
</div>

<div class="text">
    <input type="text">
</div>

<div class="date">
    <input type="date">
</div>

this would let somebody author the HTML template since it's there on the actual page. then the JS can clone the appropriate div and populate the appropriate content, either by cloning and repeating the combination or just setting a value, etc.

My question is, what is the best way to do this in Angular? I've tried a few things and have settled on:

<li ng-repeat="question in questions" class="{{question.type}}">
    <div class="multiplechoice">
        <label ng-repeat="q in question.answers><input type="checkbox" value="{{value}}"> {{text}}</label>
    </div>
    <div class="text">
        <input type="text">
    </div>
    <div class="date">
        <input type="date">
    </div>
</li>

and in the CSS, i can show/hide it based upon the class name. so like:

.date .date { display: block; }

what i would ultimately like to wind up with is not have unused templates/partials laying around inside the LIs when the ng-repeat is finished. so if it's a date question, i want:

<li><input type="date"></li>

and nothing else so that we can cleanly iterate over the DOM.

Was it helpful?

Solution

with that said i suggest you to use ng-if or ng-show

but instead of writing

<div class='text' ng-if="question.type == 'text'">

do something like this:

<div class='text' ng-if="isText(question)">

and then in your scope:

 $scope.isText = function(question){
       if(question.type == 'text'){
           return true;
       }else{
          return false;
       }
 }

is a bit easier to read in your html

EDIT:

but if you have more than two type use ng-switcht.

REFERENCE:

ng-switch : http://docs-angularjs-org-dev.appspot.com/api/ng.directive:ngSwitch

ng-if: http://docs.angularjs.org/api/ng.directive:ngIf

ng-show : http://docs.angularjs.org/api/ng.directive:ngShow

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top