1

I'm trying to display dynamically created buttons in rows of two and I'm a little unsure how to do so. So far I've got the following working, but it only works on my limited set of 4 buttons. What I want is for it to insert a linebreak after every second button. Here's my code:

HTML:

<div id="departmentButtonsDiv" *ngFor="let department of lstDepartments; let i 
= index">
   <span *ngIf="department.blnHiddenOnLandingPage == false">
     <button pButton type="button" class="departmentButton" 
           (click)="navigateToDepartment(department.strName)" label=
           {{department.strName}}></button>
   </span>
  <br *ngIf=" i == 3">
</div>

CSS:

.departmentButton {
 height: auto;
 width: 200px;
 margin-bottom: 2px;
}

#departmentButtonsDiv{
 position: relative;
 top: 10%;
 left: 45%;
 display: inline;
}

I initially thought that if I set ngIf to check if index is an even number it would do the trick, but some elements are not necessarily being displayed because their boolean values might exclude them meaning the index variable is incremented anyway. Is there any way to do this check on only the buttons that are being rendered, and if so, how would I go about that?

I'm not really a front-end developer so my HTML/CSS is a bit iffy and I've only been working in Angular for about a month so I'm rather inexperienced on that front too. I would appreciate any help or advice in this regard. I'm even open to better ways of doing this because I'm sure this is only one of many ways of doing it.

5 Answers 5

1

How dynamic is the value department.blnHiddenOnLandingPage? If it's something that doesn't change often, another approach can simply be to filter your list of departments in your component so that you don't have as much logic to deal with in your template.

So, for eg, you can have your component do something like:

ngOnInit() {
  .....
  this.filteredDepartments = this.lstDepartments.filter(dept => !dept. blnHiddenOnLandingPage);
}

And then, in your template:

 <div id="departmentButtonsDiv" *ngFor="let department of filteredDepartments; let i=index">
   <span>
     <button pButton type="button" class="departmentButton" 
          (click)="navigateToDepartment(department.strName)" label=
          {{department.strName}}></button>
   </span>
   <br *ngIf="i % 2 == 0">
</div>

If that hiddenOnLandingPage flag changes often, you can probably even move where you apply the filter to somewhere more appropriate. (For eg having the filtered list be the return value of a method on your class so that it responds to change detection)

Although, depending on the frequency of the changes, I might take a different approach at that point and try to use css (instead of the <br> tag) to get the wrapping effect that I want.

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

1 Comment

Thanks, I think this would be the best solution. department.blnHiddenOnLandingPage is highly unlikely to change and I don't expect it to happen within this product's lifespan. It's just there in the unlikely event that a department is archived for whatever reason. I feel rather silly because in my original question I was overlooking the fact that ngFor was looping over elements that are not necessarily being displayed.
1

In Angular2 and if you are using bootstrap, you could do so

<div *ngFor="let item of list; let i = index">
    <div class="col-md-6"><button type="button">Click me !</button></div>
    <div class="clearfix" *ngIf="(i+1)%2 == 0"></div>
</div>

It will basically append 2 cols and then apply clear:both to start a new row.

Comments

0

Try using the modulus operator.

<br ng-if="$index % 2 == 0">

This essentially makes a BR every time $index is a factor of 2.

1 Comment

I've updated my question with some new info, because I was overlooking a big mistake in my logic. I wasn't taking into account that ngFor is also looping over elements that are not being displayed because of this directive on the span: *ngIf="department.blnHiddenOnLandingPage == false". I'll hold off a little and see if there is another solution to doing it, otherwise I'm just going to filter the array to remove any elements where the boolean value is true and then use your solution.
0

You can use the new FlexBox. Tutorial

#departmentButtonsDiv {
  display: flex;
  flex-wrap: wrap;
  width: 200px;
}
#departmentButtonsDiv span {
  flex: 1 0 50%;
  box-sizing: border-box;
}

This would be more performant, as it is css.

Else you can try to work with modulo:

<br *ngIf="i % 2 == 0"/>

Comments

0

First, your way of checking for even or odd is wrong

 <br *ngIf=" i == 3">

It should be like this

For even

<div *ngIf="id%2 == 0">

For odd

<div *ngIf="id%2 == 1">

To have an inserted break for every even button try this

 <div *ngIf="department.blnHiddenOnLandingPage == false">
     <span>
         <button pButton type="button" class="departmentButton" 
               (click)="navigateToDepartment(department.strName)" label=
               {{department.strName}}></button>
       </span>
         <div *ngIf="id%2 == 0">
  </div>

I moved the *ngIf from the span to another div so that you can insert the br if there is a button.

Hope this helps

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.