Set class of DIV in ng-repeat - angularjs

I have next HTML code:
<div class="small-3 column cell"
ng-repeat="cell in line track by $index">
{{ cell }}
</div>
How can I add additional class for DIV element based on {{ cell }} value. For example, 'empty' for cell=0, and 'full' for cell != 0 ?

<div class="..." ng-repeat="cell in line" ng-class="{empty:(cell==0), full:(cell!=0)}">
...
</div>
which can be further reduced to
<div class="..." ng-repeat="cell in line" ng-class="(cell==0) ? 'empty' : 'full'">
...
</div>

You can use anything the angular expression supports. ng-class will be best for what you describe.
If the logic you require is more complicated than what you can do with ng-class you can always create a controller for this scenario.
<div class="small-3 column cell" ng-controller="MyCtrl"
ng-repeat="cell in line track by $index">
<div class="{{getClass()}}"></div>
</div>
function MyCtrl($scope) {
$scope.getClass = function() {
if($cell == whatever) return "whatever";
return "nothing";
}
}

Related

How to display the answer direction for a questionarie based on Direction

We are creating a quiz using angularjs.
We want to show the radiobutton list direction vertically or horizontally.
If it is horizontally we want do show in 2 columns.
Help me to show horizontally or vertically
Have provided the code in
var app = angular.module("quizApp", []);
app.controller("quizCtrl", function ($scope) {
$scope.questions = [
{
question: "Which is the largest country in the world by population?",
options: ["India", "USA", "China", "Russia"],
answer: 2,
direction:0
},
{
question: "When did the second world war end?",
options: ["1945", "1939", "1944", "1942"],
answer: 0,
direction: 1
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<body>
<div ng-app="quizApp" ng-controller="quizCtrl">
<div data-ng-repeat="quiz in questions track by $index" data-ng-init="quizIndex = $index" layout="column">
<div layout="row">
<span data-ng-bind="quiz.question"></span>
</div>
<div layout="row" data-ng-repeat="option in quiz.options track by $index" data-ng-init="optionIndex = $index">
<input type="radio" data-ng-value="{{option}}" style="margin-right: 5px;"
name="Options_{{quizIndex}}_Response_{{optionIndex}}" />
<span id="spnAnswer_{{quizIndex}}_{{optionIndex}}" data-ng-bind="option" />
</div>
</div>
</div>
</body>
You can use ng-class in the div of your repeater to show horizontal or vertical way.
Your HTML template might be look like following:
<div ng-class="'class-for-horizontal-display': !showVertical, 'class-for-vertical-display': showVertical" data-ng-repeat="quiz in questions track by $index" data-ng-init="quizIndex = $index" layout="column">
</div>
and in your controller you should have a $scope variable "showVertical" like:
$scope.showVertical = false

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>

Want to use subarray in ng-repeat

My two dimensional is like this
{
"MKey1": {
"v1": "2015-10-29 14:03:41",
"v2": "2016-01-04 15:36:13",
"v3": "2015-11-02 19:53:11",
"v4": "2015-12-09 19:15:04",
"v5": "2015-08-18 19:12:37",
"v6": "2015-09-20 17 :00:58"
},
"Mkey2": {
"v1": "2015-10-29 14:03:41",
".v2": "2016-01-04 15:36:13",
"v3": "2015-11-02 19:53:11",
"v4": "2015-12-09 19:15:04",
"v5": "2015-08-18 19:12:37",
"v6": "2015-09-20 17:00:58"
}
}
here almost everything is dynamic, even Key & values. Want to take first set of array and need to print inner array key values in table
Try like this
<div ng-repeat="(key, value) in obj" ng-if="$first">
<div ng-repeat="(subkey, subvalue) in value">
{{subvalue}}
</div>
</div>
DEMO
Try this
<div ng-repeat="value in object">
<!-- get all nested objects -->
<div ng-repeat="values in value">
<!--get values of all nested object -->
{{values}}
</div>
</div>
you can also use $index in parent loop
<div ng-app="myApp">
<div data-ng-controller="myCtrl">
<div ng-repeat="(key, value) in obj" ng-if="$index==0">
{{key}}
<div ng-repeat="(subkey, subvalue) in value">
{{subkey}} : {{subvalue}}
</div>
</div>
</div>
https://jsfiddle.net/Frangly/jpe1vyrb/2/

In ng-repeat how to get the $last item in a filter?

I define a collection of language objects like this:
$scope.languages = [
{'name':'English', value:'english', 'checked':true, 'available': true},
{'name':'German', value:'german', 'checked':false, 'available': true},
{'name':'Spanish', value:'spanish', 'checked':true, 'available': true}
];
Then I display them in checkboxes like this:
<div class="form-group">
<label for="description">Languages</label>
<div class="checkbox" data-ng-repeat="language in languages">
<label><input type="checkbox" ng-model="language.checked">{{language.name}}</label>
</div>
</div>
And as they are checked on and off, I display a list of them like this:
<div class="dataRow">
<div class="dataLabel">Languages:</div>
<div class="dataValue text-success" data-ng-repeat="language in languages">
<span ng-if="language.checked">{{language.name + ($last ? '' : ',')}}</span>
</div>
<div class="clear"></div>
</div>
And as long as the last language is selected, then the final comma will not be shown. But if the last language (Spanish) is not selected, then the final comma is erroneously shown.
Instead of $last I need something like $last(isChecked). How do I do that?
You could iterate only over the checked items by adding a filter in your ng-repeat like this:
<div class="dataRow">
<div class="dataLabel">Languages:</div>
<div class="dataValue text-success" data-ng-repeat="language in languages | filter: {checked: true}">
{{language.name + ($last ? '' : ',')}}
</div>
<div class="clear"></div>
</div>
That way you know the last element is checked.
Here's a working fiddle http://jsfiddle.net/q7ch1ysh/
Just specify that in the ternary:
language.name + ($last && language.checked ? '' : ',')
try this:
<div class="dataValue text-success" data-ng-repeat="language in languages track by $index">
<span ng-if="language.checked">{{language.name + (($index==languages.length && language.checked) ? '' : ',')}}</span>
</div>

Nested Angular directives not working as expected

I have been making a directive to display some HTML and handle events as it seemed sensible to keep this code reusable. This directive was placed inside a ng-repeat and worked as expected.
Now I come to add some more display logic to it: 2 modes 'grid' and 'list', and create 2 ng-repeat elements for each mode. At this point the whole thing seems to fall apart with rendering doing some unexpected stuff.
I have created a Plunkr to demonstrate: http://plnkr.co/edit/GjxOjxE7KOlvYjxCqVJj?p=preview
App.js
var app = angular.module('myApp', []);
app.directive('documentObject', [function() {
return {
restrict: 'E',
transclude: true,
scope: {
object: '=',
viewmode: '=',
},
templateUrl: 'storage-object.html',
link: function(scope, element, attrs) {
if (scope.viewMode === 'grid') {
scope.class = 'grid-view';
} else {
scope.class = 'list-view';
}
}
}
}]);
app.controller('DocumentsController', ['$scope', function($scope) {
$scope.browser = {
viewMode: 'grid',
files: [{name: 'First'}, {name: 'Second'}, {name: 'Third'}]
};
}]);
index.html
<div ng-switch="browser.viewMode" class="filebrowser">
<div ng-switch-when="grid">
<div ng-repeat="file in browser.files">
<document-object viewmode="browser.viewMode" object="file"></document-object>
</div>
</div>
<table ng-switch-when="list">
<tr ng-repeat="file in browser.files">
<document-object viewmode="browser.viewMode" object="file"></document-object>
</tr>
</table>
</div>
storage-object.html
<div ng-if="viewmode == 'grid'" class="filebrowser {{ viewmode }}">
Grid Mode: {{ viewmode }}
<span class="file-label {{ class }}">{{ object.name }}</span>
</div>
<td ng-if="viewmode == 'list'" class="filebrowser {{ viewmode }}">
List Mode: {{ viewmode }}
<span class="file-label {{ class }}">{{ object.name }}</span>
</td>
Grid mode should only display the items as a grid, and list mode as a table. What is happening is grid mode is displaying everything and list mode is just rendering one element.
What is going on here?
This happens because you are not allowed to have anything else as a direct child of a <tr> than a <td> or <th> element.
In your case you are having a <document-object> element, which causes the browser to move it around (as it is not allowed to be where it is), which in turn confuses ng-switch.
Wrapping <document-object> in <td></td> and chenging it's template (e.g. replacing <td> with <div>), solves the problem.
index.html:
...
<table ng-switch-when="list">
<tr ng-repeat="file in browser.files">
<td>
<document-object viewmode="browser.viewMode" object="file"></document-object>
</td>
</tr>
</table>
storage-object.html:
...
<div ng-if="viewmode == 'list'" class="filebrowser {{ viewmode }}">
List Mode: {{ viewmode }}
<span class="file-label {{ class }}">{{ object.name }}</span>
</div>
See, also, this updated plunkr.
Please see here http://plnkr.co/edit/aMOsKAATd4aBl0swPik1?p=preview
you missed <td> tag
<table ng-switch-when="list">
<tr ng-repeat="file in browser.files">
<td> <!--here -->
<document-object viewmode="browser.viewMode" object="file"></document-object>
</td>
</tr>
</table>

Resources