Serial Number using nested NG-Repeat - angularjs

I want to add serial number in each question
ng-repeat = "Table in Paper"
Display table
ng-repeat = "question in question"
(1) Display question
(2) Display question
I can use $index in Question. But for each Table, it is started from 1.
E.g.
Table 1
Question 1
Question 2
Table 2
Question 1
Question 2
But I want
Table 1
Question 1
Question 2
Table 2
Question 3
Question 4
I use $parent & $index. But not working.
<div ng-repeat="section in Table">
<div ng-repeat="question in section.question">
<span >{{(Section[$parent.$index-1].question.length + $index + 1 )+
'. ' +
question
.Description}}</span>
</div>

try this.
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', ["$scope",function MyCtrl($scope) {
$scope.lastIndex = 0;
$scope.lastIndexes = [];
$scope.Table ={
"table1":
{
"question":["questionA","questionB","questionC","questionD"]
},
"table2":
{
"question":["questionA","questionB","questionC","questionD"]
},
"table3":
{
"question":["questionC","questionD","questionF"]
},
"table4":
{
"question":["questionC","questionD","questionE"]
}
};
$scope.setLastIndex = function(len){
$scope.lastIndex = $scope.lastIndex + len*1;
$scope.lastIndexes.push($scope.lastIndex);
}
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<div ng-repeat="(key,value) in Table"
ng-init="setLastIndex(value.question.length)">
{{key}}
<div ng-repeat="question in value.question" >
<span>{{($index+1 +lastIndexes[$parent.$index-1])}} :{{question}}</span>
</div>
</div>

use
<div ng-repeat = "Table in Paper">
<div ng-repeat="q in Table.questions">
{{q}}
</div>
</div>
Here questions is array and present in your json

This may not the perfect solution what I want, But It can be a temporary solution,
Create watch or function in controller to traverse all question
var index=1;
Section.forEach(function (section) {
section.question.forEach(function (question) {
question.Number= index;
index++;
})
})
Then Print this number in ng-repeat
<div ng-repeat="section in Table">
<div ng-repeat="question in section.question">
<span >{{question.Number +'. ' +question.Description}}</span>
</div>
</div>

Related

in Angularjs {{$index}} loop only once insted of loop everytime

in Angularjs {{$index}} loop only once insted of loop everytime
<div ng-repeat="(key, value) in reports" class="all_report_admin">
<div class="name">{{key}}</div>
<div ng-repeat="data in value" class="all_report">
<div class="date">{{$index+1}}</div>
<div class="status">{{data.status}}</div>
</div>
</div>
How to restrict that
try ng-repeat="data in value[0]" instead of your ng-repeat
There is no easy combination that will give you such index (also known as a counter). It might look similar to how a one-dimensional array can be indexed with two-dimensional rows and columns, with [column + row * columns] formula (potentially {{$index + $parent.$index * reports[key].length}}). However, your reports can have an arbitrary number of object properties and arrays. So you need a manual counter in your controller.
I came up with this simple thing:
$scope.array = [];
var counter = 0;
for(key in $scope.reports){ // for every object
var temp = []; // row array
for(var j=0; j<$scope.reports[key].length; j++){
counter++;
temp.push(counter); // column element (counter)
}
$scope.array.push(temp);
}
Then it's enough to display it with {{array[$parent.$index][$index]}} in your inner ng-repeat
Here is a demo:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.reports = {
"My reports 1":[
{"status":"status1"},
{"status":"status2"},
{"status":"status3"}
],
"My reports 2":[
{"status":"status1"},
{"status":"status2"},
{"status":"status3"},
{"status":"status4"},
],
"My reports 3":[
{"status":"status1"},
{"status":"status2"},
],
"My reports 4":[
{"status":"status1"},
{"status":"status2"},
{"status":"status3"},
]
};
$scope.array = [];
var counter = 0;
for (key in $scope.reports) { // for every object
var temp = [];
for (var j = 0; j < $scope.reports[key].length; j++) {
counter++;
temp.push(counter);
}
$scope.array.push(temp);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="(key, value) in reports">
<div>{{key}}</div>
<div ng-repeat="data in value">
<strong>INDEX: {{array[$parent.$index][$index]}}</strong>
<div>{{data.status}}</div>
</div>
<hr>
</div>
</div>

Nested ng-repeat and radio or checkbox inputs not working

I am trying to show list of questions and their choices by nested ng-repeat, I have seen plenty of similar questions but still could not fix my issue. My issue here is I could see the list of questions but the choices are not getting displayed and in the developer tools I could only see the commented ng-repeat line in place of choices.
Here is my View
<div ng-repeat ="question in questions track by $index" class="panel panel-default" ng-show="showQuestions">
<div class="panel-heading">
<div class="panel-title">
<a href="div#{{$index}}" class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" >
{{question.QuestionTxt}}
</a>
<div class="row height"></div>
<div class="row" ng-show="question.QuestionTypeTxt == 'RadioButton'">
<div class="col-xs-3" ng-repeat ="answer in questions.QuestionAnswers track by $index">
<input type="radio" ng-model="selectedChoice.choice" ng-value="{{answer.AnswerTxt}}" name="{{question.QuestionTxt}}"/>{{answer.AnswerTxt}}
</div>
</div>
<div class="row" ng-show="question.QuestionTypeTxt == 'Checkbox'">
<div class="col-xs-3" ng-repeat ="answer in questions.QuestionAnswers track by $index">
<input type="checkbox" ng-model="selectedChoice.choice" ng-value="{{answer.AnswerTxt}}" name="{{question.QuestionTxt}}"/>{{answer.AnswerTxt}}
</div>
</div>
</div>
</div>
</div>
Here is my Controller
$scope.questions = [];
$scope.selectedChoice = { choice:"" };
$scope.addQuestions = function () {
$scope.showQuestions = true;
rmat3Service.getQuestionsForSection().then(function (data) {
angular.forEach(data,function(a) {
$scope.questions.push(a);
});
});
}
This is my Json data:
var questions = new List<Question>();
var answers = new List<QuestionAnswer>();
answers.Add(new QuestionAnswer()
{
AnswerTxt = "Yes",
});
answers.Add(new QuestionAnswer()
{
AnswerTxt = "No"
});
answers.Add(new QuestionAnswer()
{
AnswerTxt = "Yes Verified"
});
answers.Add(new QuestionAnswer()
{
AnswerTxt = "Not Applicable"
});
questions.Add(new Question()
{
QuestionId = 1,
QuestionTxt = "Are aisles clear of product on the floor?",
QuestionTypeTxt = "RadioButton",
QuestionAnswers = answers
});
questions.Add(new Question()
{
QuestionId = 2,
QuestionTxt = "Automated Car Wash",
QuestionTypeTxt = "Checkbox",
QuestionAnswers = answers
});
return Json(questions, JsonRequestBehavior.AllowGet);
The issue is that you're attempting to loop questions.QuestionAnswers which doesn't exist. It should be question.QuestionAnswers:
<div class="col-xs-3" ng-repeat ="answer in question.QuestionAnswers track by $index">

Creating parent div inside ng-repeat

I have 25 items from JSON string. Each item comes with a key called "InRowPlcement" and the value is assigned as "0" or "1" or "2" so on.
{"ItemID":"516","ItemName":"Newzeland Lake Tysonno","InRowPlcement":0},
{"ItemID":"514","ItemName":"Newzeland Lake Tysonno","InRowPlcement":0},
{"ItemID":"546","ItemName":"Underworld Lives","InRowPlcement":0},
{"ItemID":"527","ItemName":"In a holiday beach","InRowPlcement":1},
{"ItemID":"542","ItemName":"Underworld Lives","InRowPlcement":1},
{"ItemID":"525","ItemName":"Lake somewhere","InRowPlcement":1},
{"ItemID":"540","ItemName":"Coral Structure at Andaman","InRowPlcement":1},
{"ItemID":"569","ItemName":"Ice Rock, Ireland","InRowPlcement":2}
The intention is, placed the "0" "InRowPlacement" items in the first row, "1" in the second row, "2" in the third row and so on. The number of items may vary in each row. It may possible from 1 to 5 in a single row.
I started the ng-repeat
<div class="ROW" ng-repeat="item in items">
<div class="COLUMN">{{item.ItemName}}<div>
</div>
I need the result should be like
<div class="ROW">
<div class="COLUMN">Newzeland Lake Tysonno<div>
<div class="COLUMN">Newzeland Lake Tysonno<div>
<div class="COLUMN">Underworld Lives<div>
</div>
<div class="ROW">
<div class="COLUMN">In a holiday beach<div>
<div class="COLUMN">Underworld Lives<div>
<div class="COLUMN">Lake somewhere<div>
<div class="COLUMN">Coral Structure at Andaman<div>
</div>
Thanks in advance for your help.
SOLUTION UPDATE:
Based on the logic provided by #vp_arth, here is the actual code, which works for me
var view_rows = {};
angular.forEach(response.data, function(InRowPlcement,index){
if (!view_rows[response.data[index].InRowPlcement]) view_rows[response.data[index].InRowPlcement] = [];
view_rows[response.data[index].InRowPlcement].push(response.data[index]);
});
groups = view_rows;
This can be done with bunch of filters, but much better just prepare your data structure for view layer in the controller.
In your controller:
let data = [
{"ItemID":"516","ItemName":"Newzeland Lake Tysonno","InRowPlcement":0},
{"ItemID":"514","ItemName":"Newzeland Lake Tysonno","InRowPlcement":0},
{"ItemID":"546","ItemName":"Underworld Lives","InRowPlcement":0},
{"ItemID":"527","ItemName":"In a holiday beach","InRowPlcement":1},
{"ItemID":"542","ItemName":"Underworld Lives","InRowPlcement":1},
{"ItemID":"525","ItemName":"Lake somewhere","InRowPlcement":1},
{"ItemID":"540","ItemName":"Coral Structure at Andaman","InRowPlcement":1},
{"ItemID":"569","ItemName":"Ice Rock, Ireland","InRowPlcement":2}
];
let view_rows = {};
data.forEach(row => {
if (!view_rows[row.InRowPlcment]) view_rows[row.InRowPlcment] = [];
view_rows[row.InRowPlcment].push(row);
});
$scope.groups = view_rows;
Then, in view:
<div class="ROW" ng-repeat="(i, rows) in groups">
<div class="COLUMN" ng-repeat="row in rows">{{row.ItemName}}<div>
</div>
You could add the expression in DOM using ng-if to breakdown the items.
<div class="ROW" ng-repeat="item in items">
<div ng-if ="item.InRowPlcement == 0">
<div class="COLUMN">{{item.ItemName}}<div>
</div>
<div ng-if ="item.InRowPlcement == 1">
<div class="COLUMN">{{item.ItemName}}<div>
</div>
<div ng-if ="item.InRowPlcement == 2">
<div class="COLUMN">{{item.ItemName}}<div>
</div>
</div>
Working Plunker: https://plnkr.co/edit/vFR6NUIu6Uyl8XSOTiax?p=preview
I have written the below code as per your requirement and believe that it would work as per your requirement.
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.8/angular-filter.js"></script>
<script>
var mainModule = angular.module('mainModule', ['angular.filter']);
mainModule.controller('mainCntrl', function($scope) {
$scope.items = [
{"ItemID":"516","ItemName":"Newzeland Lake Tysonno","InRowPlcement":0},
{"ItemID":"514","ItemName":"Newzeland Lake Tysonno","InRowPlcement":0},
{"ItemID":"546","ItemName":"Underworld Lives","InRowPlcement":0},
{"ItemID":"527","ItemName":"In a holiday beach","InRowPlcement":1},
{"ItemID":"542","ItemName":"Underworld Lives","InRowPlcement":1},
{"ItemID":"525","ItemName":"Lake somewhere","InRowPlcement":1},
{"ItemID":"540","ItemName":"Coral Structure at Andaman","InRowPlcement":1},
{"ItemID":"569","ItemName":"Ice Rock, Ireland","InRowPlcement":2}
];
});
</script>
</head>
<body ng-app="mainModule">
<div ng-controller="mainCntrl">
<ul ng-repeat="(key, value) in items | groupBy: 'InRowPlcement'">
<div class="ROW">
<div class="COLUMN" ng-repeat="item in value">
{{ item.ItemName }}
</li>
</div>
</ul>
</div>
</body>
</html>

Conditional Content with ng-repeat in AngularJS

I'm trying to build a list of people with dividers for each letter (similar to a phone's address book).
people = ['Angela','Annie','Bob','Chris'];
Result:
A
Angela
Annie
B
Bob
C
Chris
I want to do something similar to this pseudocode using Angular:
<div id="container" ng-init="lastCharacter = ''">
#foreach(person in people)
#if(firstCharacter(person.name) != lastCharacter)
<div class="divider-item">{{firstCharacter(person.name)}}</div>
{{lastCharacter = firstCharacter(person.name)}}
#endif
<div class="person-item">{{person.name}}</div>
#endforeach
</div>
What is the easiest way to achieve this? I couldn't come up with an elegant solution using ng-repeat.
You should create a custom filter and move the grouping logic inside that:
app.filter('groupByFirstLetter',function(){
return function(input){
var result = [];
for(var i = 0;i < input.length; i++){
var currentLetter = input[i][0]
var current = _.find(result, function(value){
return value.key == currentLetter;
});
if(!current){
current = {key: currentLetter, items: []}
result.push(current);
}
current.items.push(input[i]);
}
return result;
};
});
Then the view gets simple:
<div ng-repeat="personGroup in people | groupByFirstLetter">
<div class="divider-item">{{personGroup.key}}</div>
<div class="person-item" ng-repeat="person in personGroup.items">
{{person}}
</div>
</div>
Here's a little working example in plunker : http://plnkr.co/edit/W2qnTw0PVgcQWS6VbyM0?p=preview
It's working but it throws some exceptions, you will get the idea.
try (use sorted list)
<div id="container" ng-repeat="person in people">
<div class="divider-item"
ng-if="$index == 0 || ($index > 0 && firstCharacter(person.name) != firstCharacter(people[$index-1].name))">{{firstCharacter(person.name)}}</div>
<div class="person-item">{{person.name}}</div>
</div>
hope, you have firstCharacter function defined in scope. Or you can simpley use person.name.charAt(0).
edit: as this will contain id container for all person. so best would be using an inner div inside container and run ng-repeat on there
<div id="container" >
<div ng-repeat="person in people">
<div class="divider-item"
ng-if="$index == 0 || ($index > 0 && firstCharacter(person.name) != firstCharacter(people[$index-1].name))">{{firstCharacter(person.name)}}</div>
<div class="person-item">{{person.name}}</div>
</div>
</div>

How to use a variable inside the ng-repeat?

I'm using the ng-repeat to list all the products, and I want to print out a star symbol x times depending on the product.rating. So, the code looks like following:
<p class="bs-rating"><i class="fa fa-star" ng-repeat="i in getRating({{ product.rating }}) track by $index"></i></p>
However, it parsed the product.rating as a String: Error: [$parse:syntax] http://errors.angularjs.org/1.3.0-beta.8/$parse/syntax?p0=product.rating&p1=is
I have tried to remove the curly brackets, {{ }}:
<p class="bs-rating"><i class="fa fa-star" ng-repeat="i in getRating(product.rating) track by $index"></i></p>
It gave me undefined. My getRating() is declared as following:
$scope.getRating = function(rating){
return new Array(parseInt(rating));
}
Could you help me figure it out how to pass a variable to ng tag?
The problem is on getRating function ie on generating the array.
I have developed an alternative solution on this link rating using ng-repeat #jsfiddle
<div ng-app="myApp" ng-controller="myCtrl">
<ol>
<li ng-repeat="product in products">
{{product.name}}
(
<span style="font-weight:bold" ng-repeat="i in
getRating(product.rating)">
x
</span>
)
</li>
</ol>
var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope){
$scope.products = [
{name : "product1", rating:3},
{name : "product2", rating:5},
{name : "product3", rating:1}
];
$scope.getRating = function(rating){
var ratingArray = [];
for (var i = 1; i <= rating; i++) {
ratingArray.push(i);
}
return ratingArray;
};
});
Hopefully it will help.
Cheers

Resources