HTML div formatting not resulting in desired output - angularjs

I have two an array with two sets of data and I want to display each set in a separate column, in the following format:
Set1 Set 2
1 ABC
2 DEF
GEF
3 HIJ
JKL
4 MNO
PQR
Instead, my data appears as follows:
Set 1 Set 2
1 ABC
2 DEF
GEF 3
HIJ
JKL 4
MNO
PQR
How do I make my data appear correctly (ie, make sure all data from Set 2 falls in the right column) using the tag, assigning "class = col-xs-4" to the first set and "class= col-xs-8" to the second? Here's my code as it stands now:
<div ng-switch="hoursOfOp[0]">
<div ng-switch-when = "Not available"><class="col-xs-4 align-right">{{hoursOfOp[0]}}</div>
<div ng-switch-default>
<div ng-repeat="hours in hoursOfOp">
<div class="col-xs-4 align-left">{{hours.day}}</div>
<div class="col-xs-8 align-left no-padding" ng-repeat="time in hours.time">{{time}}</div>
</div>
</div>
</div>

As I said in the comment, that's because when a col does not fit on the same row, it goes to the next one. What you can do is to make another div inside the div with col-xs-8 and put the ng-repeat there, as a list or something.
Keep in mind that ng-repeat repeats the element it is put in. So in your case, the flow is the following:
creates the col-xs-4 with the 1 value on first row
creates the col-xs-8 with the ABC value on first row, since there is space
creates the col-xs-4 with the 2 value on the next row, because there isn't space above
creates the col-xs-8 with the DEF value on the same row, since there is space
creates the col-xs-8 with the GEF value on the NEXT ROW, since there isn't space above
from this point, everything gets messed up.
The below example is working :)
var app = angular.module("myApp", []);
app.controller('testCtrl', ['$scope', function ($scope) {
$scope.hoursOfOp = [
{id: 1, time: ["ABC"]},
{id: 2, time: ["DEF", "GEF"]},
{id: 3, time: ["HIJ", "JKL"]},
{id: 4, time: ["MNO", "PQR"]}]
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css" integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha384-3ceskX3iaEnIogmQchP8opvBy3Mi7Ce34nWjpBIwVTHfGYWQS9jwHDVRnpKKHJg7" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.3.7/js/tether.min.js" integrity="sha384-XTs3FgkjiBgo8qjEjBk0tGmf3wPrWtA6coPfQDfFEY8AnYJwjalXCiosYRBIBZX8" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js" integrity="sha384-BLiI7JTZm+JWlgKa0M0kGRpJbF2J8q+qreVrKBC47e3K6BW78kGLrCkeRX6I9RoK" crossorigin="anonymous"></script>
<div ng-app="myApp">
<div ng-controller="testCtrl">
<div ng-repeat="hours in hoursOfOp" class="row">
<div class="col-xs-4 col-md-4 stuff">{{ hours.id }}</div>
<div class="col-xs-8 col-md-8 stuff">
<div ng-repeat="v in hours.time">
{{ v }}
</div>
</div>
</div>
</div>
</div>

Related

Cannot print current value in ng-repeat

Here is my code:
codepen.io/bedtvapp/pen/NMoBby
<div ng-app="app">
<h1>AngularJS Directive Controllers</h1>
<div ng-init="count1 = 1"></div>
<div ng-repeat-start="a in [1, 2, 3, 4, 5]" ng-init="$parent.count1 = $parent.count1 + 1"></div>
<div>
abc {{ a }} - {{::$parent.count1}} </div>
<div ng-if="$parent.count1 % 2 == 0">breakline</div>
<div ng-repeat-end></div>
</div>
I want to count item in array into custom variable (count1) (not $index). Because I will add more condition to my counting later.
If you just want to print count then just do following changes in your code
<div ng-app="app">
<h1>AngularJS Directive Controllers</h1>
<div ng-repeat-start="a in [1, 2, 3, 4, 5]" ></div>
<div>
abc {{ a }} - {{$index + 1}} </div>
<div ng-repeat-end></div>
</div>
You no need to do any initalization thing
If you increment count1 in ng-repeat-start init, end of the repeat count1 have the same value. So you need to get the help of $index. You can use count1 for the set starting value.
You can simply achieve your target using bellow code
<div ng-init="count1 = 1"></div>
<div ng-repeat-start="a in [1,2,3,4,5]" >
abc{{a}}- {{count1+$index+1}}
</div>
<div ng-if="(count1+$index+1) % 2 == 0">breakline</div>
<div ng-repeat-end></div>
output like this,
abc1- 2
breakline
abc2- 3
abc3- 4
breakline
abc4- 5
abc5- 6
breakline
If you want to add more condition you need based on (count1+$index+1) value.

splitting ng-repeat into 2 rows and repeating the same for all the data (using bootstrap grids)

Need to create this pattern in html dynamically
ie.
if I repeat var a = [1,2,3,4,5,6,7,8,9,10,11,12];
I need to get this output using angularjs and bootstrap grid
1 2
3 4 5
6 7
8 9 10
11 12
basic structure i can think of is this, with some repeat logic.
<div class="container" ng-repeat="item in itemsList">
<div class="group">
<!-- need to repeat this pattern as long as there is data -->
<div class="row two-element-row">
<div class="col-md-6">
{{item}}
<!-- need 2 elements here -->
</div>
</div>
<div class="row three-element-row">
<div class="col-md-4">
{{item}}
<!-- need next 3 elements here -->
</div>
</div>
</div>
</div>
I dont want to model the data in JS preferably.
I have a simple logic to create chunks of data of the incoming data and divide it into this pattern and then render the data, but that isnt what i want to do.
Is there any pure angular way to do this?
If there is any quick fix too , it would be great!

AngularJS - Display Banner after 2 rows, followed by another 2 Rows

I'm trying to display a Banner <div> after 2 rows of 4 x "col-md-3", followed by another 2 Rows - so the resulting markup would look like:
<div class="col-md-3">1</div>
<div class="col-md-3">2</div>
<div class="col-md-3">3</div>
<div class="col-md-3">4</div>
<div class="col-md-3">5</div>
<div class="col-md-3">6</div>
<div class="col-md-3">7</div>
<div class="col-md-3">8</div>
<div class="col-md-12" id="Banner">Banner</div>
<div class="col-md-3">9</div>
<div class="col-md-3">10</div>
<div class="col-md-3">11</div>
<div class="col-md-3">12</div>
<div class="col-md-3">13</div>
<div class="col-md-3">14</div>
<div class="col-md-3">15</div>
<div class="col-md-3">16</div>
Trying to simulate this using AngularJS so would have to use ng-repeat - but cannot seem to get this working. Any help appreciated: My Plunker
<div ng-repeat="n in Numbers">
<div class="col-md-3">{{n}}</div>
</div>
There are just a couple of problems with your plunker. First maincontroller.js is missing the .js extension, so it is never loaded.
Next all of the references to load angular should start with https instead of just http.
To display the banner after a certain number of rows place it within the first div and use something like:
<div class="col-md-12" id="Banner" ng-if="$index==5">Banner</div>
Not sure if 5 is the number you want there or if you want to use some kind of expression to see if ng-if is divisible by a certain value, but using $index and ng-if should get you there.
You could use ng-repeat-start and ng-include with a ng-if to conditionally include the banner if it's at the correct index with n===8.
Please have a look at the code below or in this plunkr.
angular.module("app", [])
.controller("MainController", mainController);
function mainController($scope) {
$scope.Numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container" ng-controller="MainController" ng-app="app">
<h1>Demo</h1>
<div class="col-md-3" ng-repeat-start="n in Numbers">{{n}}</div>
<div ng-include="'banner.html'" ng-if="(n === 8)" ng-repeat-end></div>
<script type="text/ng-template" id="banner.html">
<div class="col-md-12" id="Banner">Banner</div>
</script>
</div>

ng-repeat + ng-switch: how to use correctly?

Premise: I've seen several similar questions. But I can't really figure out how to solve my doubt.
I have an array of objects:
$scope.messages = [obj1, obj2, ...];
where each object has the following structure:
{
id: <int>,
printOnlyFirst: <boolean>,
text1: <string>,
text2: <string>
}
where text1 / text2 are conditionally printed (in real time through track by) according to printOnlyFirst.
<div id="container">
<div ng-switch="printOnlyFirst" ng-repeat="message in messages track by message.id">
<div ng-switch-when="true" class="text1"> <!-- case 1 -->
{{message.text1}
</div>
<div ng-switch-when="false" class="text2"> <!-- case 2 -->
{{message.text2}
</div>
</div>
</div>
I think this code is fine.
However I noticed that
<div ng-switch="printOnlyFirst" ng-repeat="message in messages track by message.id">
is printed for each single element of the ng-repeat loop, together with it's content (either case 1 or 2).
Is this normal?
Is there a better solution to avoid such DOM overhead?
From https://docs.angularjs.org/api/ng/service/$compile#-priority-:
Directives with greater numerical priority are compiled first.
ngSwitch executes at priority 1200 while ngRepeat executes at priority 1000, which isn't the order you need.
You'll have to use a nested component (a div for example):
<div id="container">
<div ng-repeat="message in messages track by message.id">
<div ng-switch="message.printOnlyFirst">
<div ng-switch-when="true" class="text1"> <!-- case 1 -->
{{message.text1}
</div>
<div ng-switch-when="false" class="text2"> <!-- case 2 -->
{{message.text2}
</div>
</div>
</div>
</div>
Don't forget to switch on message.printOnlyFirst rather than printOnlyFirst.

Horizontal ng-repeat(er) with new row breaks

Working with Bootstrap and AngularJS, is there a way to ng-repeat horizontally with a new row for every set amount of elements?
I have been playing around with ng-class to accomplish this Fiddle, but the problem is that I can't get the float left divs within the initial row div... Any thoughts, am I not thinking of something or would this best be done with a Directive?
Here is my code (live example in the above fiddle link):
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<div ng-repeat="num in numbers"
ng-class="{'row': ($index)%2==0, 'col-md-6': ($index)%2!=0}">
<div ng-class="{'col-md-6': ($index)%2==0}">
{{num}}
</div>
</div>
</div>
</body>
var myApp = angular.module('myApp', [])
.controller('MyCtrl', function ($scope) {
$scope.numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
});
.row {
clear: both;
width: 100%;
border: 1px solid red;
}
.col-md-6 {
width: 50%;
float: left;
border: 1px solid blue;
}
If you are working with Bootstrap 3 and AngularJS you can declare a new filter that will return one array of sub array slices and then do two ng-repeat.
It will look like that:
<div class="row" ng-repeat="row in filtered = (arr | splitArrayFilter:3)">
<div class="col-md-4" ng-repeat="n in row">
<h3>{{n}}</h3>
</div>
</div>
app.filter('splitArrayFilter', function() {
return function(arr, lengthofsublist) {
if (!angular.isUndefined(arr) && arr.length > 0) {
var arrayToReturn = [];
var subArray=[];
var pushed=true;
for (var i=0; i<arr.length; i++){
if ((i+1)%lengthofsublist==0) {
subArray.push(arr[i]);
arrayToReturn.push(subArray);
subArray=[];
pushed=true;
} else {
subArray.push(arr[i]);
pushed=false;
}
}
if (!pushed)
arrayToReturn.push(subArray);
console.log(JSON.stringify(arrayToReturn));
return arrayToReturn;
}
}
});
You can Find it on Plunker here: http://plnkr.co/edit/rdyjRtZhzHjWiWDJ8FKJ?p=preview
for some reason the view in plunker does not support bootstrap 3 columns but if you open it in embedded view or in browsers you can see that it works.
It was clever what you were doing with ng-class. I hadn't ever thought of using %2 within the expression there.
But for future reference, there is a slightly easier way to accomplish that: ng-class-even and ng-class-odd. It does the same thing as what you were doing, but just a bit cleaner:
<div ng-repeat="num in numbers" ng-class-even="'md-col-6'" ng-class-odd="'row'">
{{num}}
</div>
But this doesn't resolve your problem. If I understand you correctly, you want a row, with two columns within that row. The easiest way I could think of is to split up the arrays. Put the repeat on the div, then have 2 span within the div. I think one of the issues that you had originally, is that you were repeating a single div, and trying to treat that block element as an inline
Controller
myApp.controller('MyCtrl', function ($scope) {
$scope.evens = ["2","4","6","8","10","12","14"];
$scope.odds = ["1","3","5","7","9","11","13"];
});
HTML
<div ng-controller="MyCtrl">
<div ng-repeat="odd in odds" class="row">
<span class="span3">{{odd}}</span>
<span class="span2">{{evens[$index]}}</span>
</div>
</div>
Fiddle
Being that you're using version 1.1.5, that also opens you up to a new directive: ng-if! You could also use ng-switch to do some conditional logic displays.
You didn't include bootstrap in your fiddle, and for some reason I can't get jsFiddle to display bootstrap. So I created some temp CSS classes that would somewhat resemble bootstraps class="span"
No need to add .row class .. I did this:
HTML:
<div ng-repeat="product in allProducts">
<div class="my-col-50">
<h1>{{product.title}}</h1>
</div>
</div>
CSS:
.my-col-50{float:left;width:50%;}
and it's work like a charm.
Although this isn't the "proper" way of doing this, there is a way to achieve this using CSS.
For example, this is for a 3 column layout:
HTML:
<div class="row">
<div ng-repeat="(key, pod) in stats.pods" class="pod-wrap">
<div ng-if="objectCheck(pod) == false" class="col-md-4 col-sm-4 pod">
<div>
<h2 ng-bind="key"></h2>
<p class="total" ng-bind="pod | number"></p>
</div>
</div>
<div ng-if="objectCheck(pod) == true" class="col-md-4 col-sm-4 pod">
<div>
<h2 ng-bind="key"></h2>
<div ng-repeat="(type, value) in pod track by $index">
<p class="status"><% type %> <small><% value %></small></p>
</div>
</div>
</div>
</div>
</div>
CSS:
.pod-wrap:nth-of-type(3n):after {
display: table;
content: '';
clear: both;
}
I tried two of the suggestions given here...
the one by yshaool works fine but like i commented on it give me that infinite loop error.
Then I tried something like below:
<div class="row" ng-repeat="row in split($index, 3, row.Attempts)">
<div class="col-md-4" ng-repeat="attempt in row">
<div>Attempt {{row.AttemptNumber}}</div>
<div>{{row.Result}}</div>
</div>
</div>
and the function:
$scope.split = function (index, length, attempts) {
var ret = attempts.slice(index * length, (index * length) + length);
console.log(JSON.stringify(ret));
return ret;
}
was going somewhere with that when i realized that it could be as simple as
<div ng-repeat="attempt in row.Attempts">
<div class="col-md-4">
<div>Attempt {{attempt.AttemptNumber}}</div>
<div>{{attempt.Result}}</div>
</div>
</div>
using "col-md-4" does the trick as I only need to split using three columns per row..
(let bootstrap do the work!)
anyway the other answers here were really useful...
Depending upon the number of columns that you need in your template, create chunks of the original data source in your controller.
$scope.categories = data //contains your original data source;
$scope.chunkedCategories = [] //will push chunked data into this;
//dividing into chunks of 3 for col-4. You can change this
while ($scope.categories.length > 0)
$scope.chunkedCategories.push($scope.categories.splice(0, 3));
In your template you can now do the following
<div class="row" ng-repeat="categories in chunkedCategories">
<div class="col-xs-4" ng-repeat="category in categories">
<h2>{{category.title}}</h2>
</div>
</div>
My approach was to use the $index variable, which is created and updated by AngularJS within an ng-repeat directive, to trigger a call to the CSS clearfix hack which, in turn, resets to a new row.
I am using the following versions: AngularJS 1.5.5 and Bootstrap 3.3.4
<!-- use bootstrap's grid structure to create a row -->
<div class="row">
<!-- Cycle through a list: -->
<!-- use angular's ng-repeat directive -->
<div ng-repeat="item in itemList">
<!-- Start a new row: -->
<!-- use the css clearfix hack to reset the row -->
<!-- for every item $index divisible by 3. -->
<!-- note that $index starts at 0. -->
<div ng-if="$index % 3 == 0" class="clearfix"></div>
<!-- Create a column: -->
<!-- since we want 3 "item columns"/row, -->
<!-- each "item column" corresponds to 4 "Bootstrap columns" -->
<!-- in Bootstrap's 12-column/row system -->
<div class="col-sm-4">
{{item.name}}
</div>
</div>
</div>
To keep solution bootstrap formated i solved this using ng-class
<div ng-repeat="item in items">
<div ng-class="{ 'row': ($index + 1) % 4 == 0 }">
<div class="col-md-3">
{{item.name}}
</div>
</div>
</div>

Resources