Angularjs - Unexpected space after last ng-repeat li - angularjs

I am having a very strange layout issue with list-items generated using ng-repeat.
Plunker here
If you look at the view, you will see that the li in green (not generated using ng-repeat) goes to the next line because of the unexpected space. Also, if you change the width of li to 33%, you will see that the last li (Add User) is not aligned correctly.
I can work around this with some css tricks, but I want to understand why this is happening and if there is any way to avoid this. Has anyone encountered this before and figured out why this is happening?
Adding code below only because plunker link needs to be accompanied with some code
.users * {
box-sizing: border-box;
}
.users ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.users ul li {
width: 49%;
margin: 5px 1% 0 0;
padding: 0;
display: inline-block;
}
.users ul li.user {
background: yellow;
}
.users ul li.add-user {
background: lightgreen;
}

It's because you have a blank space (created by the carriage return) beetween the closing </li> and the <li class="add-user">
Write your html like this and the last li will be displayed correctly :
...
<li class="user" data-ng-repeat="user in vm.users track by $index">
<div>{{ user.name }}</div>
</li><li class="add-user">
<div>
<a>Add Child</a>
</div>
</li>
...

Related

How to hide css border-right using loop for even number in angular js

I am devolping app using angular js and ionic framework. I want to show border right only for odd numbers.
Here is my code:
<div class="media-body" style="padding-bottom:25px;">
<h2 class="align_center">{{services.name}}</h2>
<a href="#job/{{services.id}}">
<h2 class="align_center_des">{{services.description}}</h2>
</div>
</div></div>
Here is the Css
.col-32-custom {
width: 32%;
float: left;
margin-left: 1%;
border-right: 1px solid #E4E4E4;
margin-bottom: 31px;
height: 144px;
}
Here is fiddle:
https://jsfiddle.net/asetkL0n/
CSS also allows you to target specific odd or even elements. An example to that could be:
.col-32-custom {
width: 32%;
float: left;
margin-left: 1%;
margin-bottom: 31px;
height: 144px;
}
.col-32-custom:nth-child(odd) {
border-right: 1px solid #E4E4E4;
}
wherein, inside that nth-child, you can pass, "odd","even","2n","2n+1", or any expression in n.
I think the best solution is to use ng-class, so you have to create a class that will only add the border right.
I presume you are in an ng-repeat loop so the code will look like
<div data-ng-class="{border-right: ($index%2)===0}" class="col-32-custom">
Here you have the condition for the even number ($index%2)===0 so the div will have border-right class on event number.
you can use ng-class-odd / ng-class-even within ng-repeat to add specific classes to this items.
example here : ng-class-odd

List items not correctly aligning with an ng-repeat

I have a simple ng-repeat <li>. Each <li> consumes 33.33% of the width so 3 items per row.
However, for some reason the items in the second row do not line up. After a big of digging, if i apply a min-width of say, 400px, then it works. But, i can not do this as the description text length is dynamic.
HTML:
<ul class="grid-wrap">
<li class="grid-col one-third" ng-repeat="job in Jobs" ng-init="descriptionLimit = 20">
<div>{{ job.JobTitle }}</div>
<div>{{ job.Location }}</div>
<div>{{ job.JobDescription | limitTo:descriptionLimit }}
<span ng-click="descriptionLimit = job.JobDescription.length"> >> </span></div>
</li>
</ul>
CSS:
ul, ol {
list-style: none;
padding: 0;
margin: 0;
}
.grid-wrap {
margin-left: -3em; /* the same as your gutter */
overflow: hidden;
clear: both;
}
.grid-col {
float: left;
padding-left: 3em; /* this is your gutter between columns */
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.one-third {
width: 33.33%;
}
plunker: http://plnkr.co/edit/oWXrqoJpaYPDbe4TwT3c?p=preview
If you click on the >> the description will expand and you can see each <li> does not line up:
Might something like this be what you are looking for?
.one-third:nth-of-type(3n+1) {
clear: both;
}
I.e. if you want to have exactly a maximum of 3 lis per row, and you want to always align your rows vertically, you'll need to explicitly do so.
Edit: And of course you could do this also with Angular, for example like this, first define a clearing class:
.clear-li {
clear:both
}
and then apply it with ng-class:
<li class="grid-col one-third" ng-repeat="job in Jobs" ng-init="descriptionLimit = 20" ng-class="{'clear-li': ($index % 3 === 0)}">

Display several sequences of events with possible line break in middle [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am a HTML / CSS newbie.
I need to do something like this:
My web page is receiving sequences of events dynamically and I would like to visualize them on in the page.
I would like one sequence of events to be in a box, with lots of slots, and each slot has the event id.
So if I have several sequences, then I will have several such boxes.
However, the length of a sequence is dynamic. And the web page's window might be adjusted by the users, so even for a sequence, if it is too long or the window is too narrow, I have to break the box into several lines.
the above is my drawing of the design.
The A, B, etc, are the sequence title, then the numbers are the ids.
ideally, the space of all events / sequences should be as compact as possible.
And if a box has to change line, then it should be half-borded to indicate the continuous.
How can I do that? using CSS 3?
And also the framework I am using is AngularJS to control the data / UI binding, even if I manage to handle this case, how to dynamically bind the data to adjust this requirement?
Thanks
Doing this in CSS is tricky, because you want a border between elements only if those elements are on the same line. CSS doesn't know anything about wrapping.
I've solved the problem by:
Adding a left border on all boxes
Adding a right border on the last box only.
Adding a -1px left margin on all boxes except the first.
Placing the boxes in a container with overflow: hidden.
Having the right border on the last box only solves the right-hand issue.
The -1px left margin solves the left-hand issue.
Snippet:
.sequences {
overflow: hidden;
}
.sequence > div {
border: 1px solid black;
border-right: none;
height: 50px;
float: left;
margin-bottom: 10px;
}
.sequence > div:last-of-type {
border-right: 1px solid black;
margin-right: 20px;
}
.sequence > div:not(:first-of-type) {
margin-left: -1px;
}
.yellow div {background: yellow; width: 100px;}
.green div {background: lightgreen; width: 80px;}
.blue div {background: lightblue; width: 120px;}
<div class="sequences">
<div class="sequence yellow">
<div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div>
</div>
<div class="sequence green">
<div></div><div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div><div></div>
</div>
<div class="sequence blue">
<div></div><div></div><div></div>
<div></div><div></div><div></div>
</div>
</div>
You can solve this using CSS by doing something like this.
I've given each sequence element a top, left and bottom border. T
This will give the illusion of a right border when the elements are floated next to eachother but when they're the last on that line it will brake of as per your request.
I also added a right border to the last div element and the last div in each section.
Fiddle
div{
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
float:left;
background: #eee;
border: 1px solid #000;
border-width: 1px 0 1px 1px;
margin-bottom: 10px;
}
div.last{margin-right: 5px;}
div.last,
div:last-child{border-right-width: 1px;}
<div class="seq-1">1</div>
<div class="seq-1">2</div>
<div class="seq-1">3</div>
<div class="seq-1">4</div>
<div class="seq-1 last">5</div>
<div class="seq-2">1</div>
<div class="seq-2">2</div>
<div class="seq-2 last">3</div>
Edit:
I just noticed you wan't the border to be 0px/blank on the last element and the first element each row. Now that is a bit trickier.
I'm not positive there's a good solution to solving that using css since your sequences seem to be dynamic.
Please correct me if I'm wrong, but I think you need to use javascript to manage this.
Edit 2: CSS and JQuery solution
I made a quick jquery solution that utilies my previously provided CSS code.
The jQuery script removes the left border if the elements left offset(within it's parent) is 0 and if the element is not the first element in each sequenc(first class added).
Fiddle
var containerOffset = $('.container').offset().left;
setBorderWidth();
$(window).resize(function(){
setBorderWidth();
});
function setBorderWidth(){
$('.block').each(function() {
var childOffset = $(this).offset().left;
if(childOffset - containerOffset == 0 && !$(this).hasClass('first'))
$(this).css("border-left-width", "0px");
else
$(this).css("border-left-width", "1px");
});
}
.container{width: 100%;}
.block{
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
float:left;
background: #eee;
border: 1px solid #000;
border-width: 1px 0 1px 1px;
margin-bottom: 10px;
}
.block.last{margin-right: 5px;}
.block.last,
.block:last-child{border-right-width: 1px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<div class="container">
<div class="seq-1 block first">1</div>
<div class="seq-1 block">2</div>
<div class="seq-1 block">3</div>
<div class="seq-1 block">4</div>
<div class="seq-1 block last">5</div>
<div class="seq-2 block first">1</div>
<div class="seq-2 block">2</div>
<div class="seq-2 block last">3</div>
</div>
What I would recommend is to have 3 CSS classes
1) beginning of sequence
2) middle of sequence
3) end of sequence
then display different borders using:
.beginning-of-seq {
border-top-style: solid;
border-right-style: none;
border-bottom-style: solid;
border-left-style: solid;
}
for instance.
about the angular part just use ng-repeat="seq in sequences" for instance and then render the sequence with the classes you created so it will look good (of course you need the scope to have the sequences)
<span ng-repeat="seq in sequences">
<span class="beginning-of-seq"> {{seq.title}} </span>
<span class="middle-of-seq ng-repeat="elem in seq.otherElements">{{elem}}</span>
<span class="end-of-seq"> {{seq.lastElem}} </span>
</span>
</span>
this is a bit crude and i don't know how you implemented it but it should give you an idea where to start
This HTML/CSS should do the trick. As you mentioned about the user having different resolutions, I've used percentages for the widths (depending on your scenario, media queries may be needed).
.container {
width: 30%; /*Change this to fit your design*/
}
.seq {
display: inline;
border: 0.1em solid #000;
margin-right: 1em;
}
.seq .item {
display: inline-block;
width: 5%; /*Change this to fit your design*/
margin-bottom: 1em;
}
.seq .item:not(:last-child) {
border-right: 0.1em solid #000;
}
<div class="container">
<div class="seq">
<div class="item item-title">A</div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<div class="seq">
<div class="item item-title">B</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
<div class="seq">
<div class="item item-title">C</div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
<div class="seq">
<div class="item item-title">D</div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
</div>
About the AngularJS binding:
In your controller define your array of sequences and some functions to manipulate the sequences:
$scope.sequences = [];
$scope.addSequence = function(sequenceName){
var newSequence = { name : sequenceName, events: [] };
$scope.sequences.push(newSequence);
};
$scope.addEventToSequence = function(sequenceName, event){
var sequence = getSequence(sequenceName); // write this function to get the right sequence from the array
sequence.events.push(event);
}
Now in your html loop over the sequences and events using ng-repeat
<ul>
<li ng-repeat="sequence in sequences">
<ul>
<li>{{sequence.name}}</li>
<li ng-repeat="event in sequence.event">{{event.name}}</li>
</ul>
</li>
</ul>

Aligning divs horizontally using CSS display:

I am trying to align two divs horizontally. My list in the 2nd div is horizontally aligned, but the two divs fail to align horizontally as inline-blocks. Any help would be greatly appreciated.
Here is the CSS and HTML code:
CSS
#wrapper {
margin:0 auto;
width:100%;
position:relative;
}
.navit {
position:relative;
margin-left: auto;
margin-right: auto;
width: 100%;
height: 100%;
display:inline;
}
.container-logo {
display:inline-block;
}
.container-user {
display:inline-block;
}
#user-nav-container ul li {
display:inline;
}
#user-nav-container ul li a {
background-color:#000000;
color:#FFF;
font-size:14px;
}
#user-nav-container ul {
list-style-type:none;
background-color:#000000;
}
HTML
<html>
<body>
<div id="wrapper">
<header id="top">
<div id="navbar" class="navit">
<div id="logo-container" class="container-logo"><a href="http://www.site.com/" id="logo">
<h1>ServiceMyResume.com</h1>
</a></div>
<div id="user-nav-container" class="container-user">
<ul>
<li>Site 1</li>
<li>Site 2</li>
</ul>
</div>
</div>
</header>
</div>
</body>
</html>
Fiddle: http://jsfiddle.net/8TfzJ/
Get rid of:
#user-nav-container ul li {
display:inline;
}
This is what is causing your nav elements to be horizontal instead of vertical.
http://jsfiddle.net/8TfzJ/1/
Update
To vertiacaly align the two elements add vertial-align top to them, see: http://jsfiddle.net/8TfzJ/2/.
Note in the fiddle I've added a border so you can see the elements are vertially aligned. You may need to adjust margins and padding of the contained elements to fully achieve what you are looking for. Use Firebug for Firefox to help you here. You can inpect an experiment with the CSS in the borwser.
In a modern browser you should see:
See this article for some inf on the drawbacks of inline-block and how to over come them:http://robertnyman.com/2010/02/24/css-display-inline-block-why-it-rocks-and-why-it-sucks/
On a side note, you shouldn't put block elements e.g. h1 inside inline elements e.g. a. It should be the other way around. Try validating it here: http://validator.w3.org/#validate_by_input+with_options
I know it is not as inline-blocks, but you you mean something like this JSFiddle?
#navbar:after
{
display: table;
content: "";
clear: both;
}
#logo-container,
#user-nav-container
{
float: left;
}

IE7 (IE8 Compatability Mode) bug: crazy amound of width applied to a floated element that is parent to another float

Here's my problem. It looks perfect in Firefox, Safari, IE8, but in IE7 and IE8 comparability mode, it adds about 4000px of width to the div.team elements nested within the list item. the problem goes away if i remove the span.score elements.
The image attached shows the score in the first box in white number text. The top image is the way it's supposed to look. The bottom is IE7.
I've been trying to figure this out for hours. I even tried making the list a bunch of divs in case it was a weird IE7 list item bug, but I got the exact same results.
Here's my html:
<ul class="selected" data-league="ncaaf">
<li>
<div class="time">THU 12:30PM</div>
<div class="teams">
<div class="team">AUB (21) <span class="score">10</span></div>
<div class="team">MSST <span class="score">22</span></div>
</div>
</li>
...
Here's my CSS:
.boxList ul {
float:left;
margin:0 0 0 0;
heigth:40px;
width:5000px;
clear:left;
display:none;
}
.boxList ul.selected {
display:block;
}
.boxList li {
float:left;
height:40px;
padding:0 5px;
min-width:56px;
background:url(../images/scoreSchedBoxTile.png) repeat-x;
border:1px solid #000;
list-style-type:none;
margin:0;
font-size:9px;
line-height:13px;
font-weight:bold;
cursor:pointer;
position:relative;
}
.boxList li .time {
text-align:center;
}
.boxList li .teams {
}
.boxList li .team {
text-align:left;
color:#000;
clear:left;
line-height:13px;
height:13px;
}
.boxList li .score {
font-weight:bold;
text-align:right;
color:#fff;
float:right;
display:block;
}
try using:
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
The width on your divs is set to 100%, so the div is stretching to 100% width and filling all available horizontal space. You can fix this by applying a fixed width to your divs.

Resources