2

I have an issue with Bootstrap panels with AngularJS. I'm not able align correctly my panels. I want to display my panels into 2 columns.

I have the following HTML code:

<div class="row">
  <div class="col-lg-3 col-sm-3 col-xs-3">
    <span>Some stuffs</span>
  </div>
  <div class="col-lg-9 col-sm-9 col-xs-9">
    <div class="row">
       <div class="col-lg-6 col-sm-6 col-xs-6"
            ng-repeat="i in items">
         <div  class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title">{{i.title}}</h3>
          </div>
          <div class="panel-body">
            {{i.content}}
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Basic case: Let's say, I have 3 items. The 2 first items will be displayed in the first row. - item1: row0/col0 - item2: row0/col1 The last item should be displayed in the 2nd row and first column - item3: row1/col0

It works fine when the height of the panels are the same.

My use case: My panel content can be different from each other. So, when my first panel content is bigger than the others, the third item goes to the col1. - item3: row1/col1

It leaves a big space and then if I want to add a 4th item...it becomes ugly :(

I've created a demo showing the issue: http://plnkr.co/edit/TZDck5b9G9Ap32KlPk4q?p=preview

1
  • If u don't have issue with making all columns of same height, then I would suggest you to use this directive: github.com/Sixthdim/angular-vertilize. It set's height of all container to the same (maximum of these) Commented May 11, 2015 at 10:04

3 Answers 3

1

The only solution I can think of to correctly display the 3rd div regardless of its size is to use one row for the first 2 divs and another for the next 2 (and so on and so forth). You can do this by putting the ng-repeat iteration outside the row div and assigning the row class conditionally when the iteration is on an add element.

<div ng-repeat="i in items">
    <div ng-if="$even" class="row">
      <div class="col-lg-6 col-sm-6 col-xs-6">
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title">{{i.title}}</h3>
          </div>
          <div class="panel-body">
            {{i.content}}
          </div>
        </div>
      </div>
      <div class="col-lg-6 col-sm-6 col-xs-6" ng-if="items[$index + 1]">
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title">{{items[$index + 1].title}}</h3>
          </div>
          <div class="panel-body">
            {{items[$index + 1].content}}
          </div>
        </div>
      </div>
    </div>
</div>

The downside is of course that you are duplicating the markup for the column (the one that shows the actual pannel), which can be avoided if you create a directive for this part. I get that Exlord's solution is simpler, however I have the feeling that this is closer to the Angular / Bootstrap way, since otherwise you are effectively overriding Bootstrap's row system by "forcing" the row's columns to break in more than one row (using clear:right).

See updated plunkr here: http://plnkr.co/edit/7KMZdzcpR7Ff2D6pExVB?p=preview

Sign up to request clarification or add additional context in comments.

2 Comments

that's not gana work, now each column is inside 2 divs with no float
@Exlord I get your point after reading your comment, however what is weird is that actually it is working. I am reviewing it to see if I can find a better way to do what I am proposing
0
<div ng-repeat="..." ng-class="{clear_right:$odd}">
    //your panel content here   
</div>

.clear_right{clear:right;}
.clear_right:after{content:" ";display:block;}

Comments

0

@Christina: Nice solution, but you lost your scope. In my complex template html I need access to the parent scope. I changed the directive to building a new scope that inherits from the parent, see the plunker fork http://plnkr.co/edit/CCwbnZCE7e8ej2fFBi2e?p=preview

app.directive('panelContent', function(){
 return {
  restrict: 'E',
  scope: true,
  templateUrl: 'panel-content.html',
  link: function(scope, element, attributes){
    scope.item = scope.$eval(attributes["item"]);
  }
 };
})

Update 03.06.15:

The {{$index +1}} solution will cause problems if you add or remove items. In this case anguluar gets problem with data-binding and does not update the view to the modified collection.

Now I solved the problem with a

   <div ng-if="$even" style="clear: both;"></div> 

in the ng-repeat block

 <div ng-repeat="item in myItems">
      <div ng-if="$even" style="clear: both;"></div>
      <item-content /> <!-- directive that adds the content for each item ( or direct html if you want)-->
 </div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.