1

In an AngularJS app, whenever an ng-repeat produces something like this:

<div>
  <button>Alice</button>
</div>
<div>
  <button>Bob</button>
</div>
<div>
  <button>Jennifer</button>
</div>

I would like for all buttons to have the same width, which would be the width of whichever button is the widest, determined by the length of the caption it contains. Can this be done with pure AngularJS, and without importing jQuery just for this?

3
  • 1
    Well, how about CSS? Commented May 31, 2015 at 17:30
  • 1
    wouldn't that be CSS, and nothing at all to do with Angularjs? Commented May 31, 2015 at 17:31
  • It didn't occur to me to use CSS, since I'm not very familiar with it, but I'll look into that, thanks. Commented May 31, 2015 at 17:34

5 Answers 5

3

Making all your buttons same width as the one with longest caption, you don't need JavaScript nor AngularJS, just CSS.

html

<div class="container">
  <button type="button">Some button</button>
  <button type="button">Button here, too...</button>
  <button type="button">Yet another</button>
</div>

<!-- or using ng-repeat e.g. -->

<div class="container">
  <span ng-repeat="button in buttons">
    <button type="button" ng-bind="button"></button>
  </span>
</div>

css

.container {
  position: absolute;
} 

.container button {
  display: block;            
  width: 100%;
  margin: 2px;
  text-align: center;
}

screenshot

imgur


Related plunker here https://plnkr.co/edit/TNnWMD

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

Comments

2

We need to use one directive that would tell us that the rendering of all the element inside the ng-repeat is completed. On that completion we will check the each button, and the maximum width we will set to all button element.

Markup

<div ng-repeat="item in items" ng-repeat-finish>
  <button>{{item.name}}</button>
</div>

Directive

app.directive('ngRepeatFinish', function($timeout) {
  return {
    restrict: 'A',
    link: function(scope, element, attr) {
      var maxWidth = 0;
      if (scope.$last === true) {
        $timeout(function() {
          var allButtons = $(element).find('button');
          //check the maximum width of element
          angular.forEach(allButtons, function(ele, ind) {
            //below code will find maxWidth
            maxWidth = ele.innerWidth > maxWidth ? ele.innerWidth : maxWidth;
          });
          allButtons.css('width', maxWidth)
        });
      }
    }
  });

13 Comments

This works, sure, but it's like someone asking you how to eat soup with fork and we are kind enough to show how it's done instead of introducing spoon to the fella.
@MikkoViitala I don't get your point what you are saying? could you tell me what should have added in my answer
I mean one might be better off solving this issue using CSS and layout rather than JavaScript and/or AngularJS directive.
@pankajparkar, I learned something useful from your answer, despite not giving it the checkmark. I learned how to think in terms of directives when solving a problem, and that is going to be very useful to me in my future learning. Upvoted and many thanks for taking the time to formulate the answer.
NO NO !!!! You should never use a $timeout inside your directive. You can solve this easy task by emitting an event on the link function when the $last element of the ng-repeat is set to true.
|
1

No. Angular is not supposed to handle your style(css) or markup(html). Take a look at any responsive framework like bootstrap och skeleton. You can achieve what you want with any javascript but it will be just to apply the correct tags and css classes.

1 Comment

Of course AngularJS can handle markup! Why else would we have ng-style and ng-class? It is very handy when used correctly.
1

Yes it can be done with pure AngularJS and it's very simple. You can define a table and repeat each button inside each cell. Doing that way - you will get all buttons with the same size.

Just create an ng-repeat in the html and a function to define the array of names in the javascript file. That's it! JSbin example

HTML

<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
      <script src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.4.7/angular-filter.js"></script>

    <meta name="description" content="[groupBy example]"/>
      <meta charset="utf-8">
      <title>JS Bin</title>
    </head>
    <body>
      <div ng-controller="MainController"> 
          <table class="table table-bordered table-striped">
            <thead>
                <tr>
                    <th>Name</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="name in names">
                    <td>
                      <input 
                             type="Button" 
                             value="{{name}}"
                             style="width:100%"></td>
                </tr>
            </tbody>
        </table>
      </div>
    </body>
    </html>

JS

angular.module('app',['angular.filter'])
  .controller('MainController', function($scope) { 
    $scope.names = ["Alice", "Bob", "Jennifer"];
 });

View

enter image description here

1 Comment

The other solution is to wait until ng-repeat has finished and then manipulate the DOM. You can easily to that by using a directive and watch the $last property of the ng-repeat. Once the $last item is set to true, then you fire an event and modify the dom. Let me know if you need a demo.
0

You should use CSS instead of AngularJS binding. You should do something like this:

<div style="display:inline-block;">
<div style="width: 100%">
  <button style="width: 100%">Alice</button>
</div>
<div style="width: 100%">
  <button style="width: 100%">Bob</button>
</div>
<div style="width: 100%">
  <button style="width: 100%">Jennifer</button>
</div>
</div>

Off course you should pull out the inline CSS into some styling code and use classes.

1 Comment

width 100% will get the 100% of parent..this will never set maximum width of any button..did you understand OP question correctly

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.