3

I need to create a carousel that shows pictures from a variable in the .ts. I planned using ngFor.

I have a static Bootstrap 4 carousel:

 <div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel">
    <ol class="carousel-indicators">
        <li data-target="#carouselExampleIndicators" data-slide-to="0" class="active"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
    </ol>
    <div class="carousel-inner">
        <div class="carousel-item active">
            <img src="assets/fortress.jpg" class="d-block w-100 carousel-pic" alt="...">
        </div>
        <div class="carousel-item">
            <img src="assets/fortress.jpg" class="d-block w-100 carousel-pic" alt="...">
        </div>
    </div>
</div>

And I have a variable in the .ts file called pics: enter image description here

Now I tried putting the ngFor the carousel, and the active carousel just the first picture. Problem:

  • The carousel are off. Just showing three. When I try setting the ngFor there, it doesn't work.
  • Slide shows first picture (active) okay but the second slide show the same picture (because the loop starts again) and then it stops, doesn't show the third picture.

When I tried just setting the ngFor as carousel-item, it doesn't work because it requires active class. Also, the item?[0].pin_photos.url just gets the first picture.

   <div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel">
        <ol class="carousel-indicators">
            <li data-target="#carouselExampleIndicators" data-slide-to="0" class="active"></li>
            <li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
            <li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
        </ol>
        <div class="carousel-inner">
            <div class="carousel-item active">
                <img src="http://MYURL/public/PinPhotos/{{item?.pin_photos[0].url}}"
                    class="d-block w-100 carousel-pic" alt="...">
            </div>
            <div *ngFor="let pic of pics">
                <div class="carousel-item">
                    <img src="http://MYURL/public/PinPhotos/{{pic.url}}" class="d-block w-100 carousel-pic" alt="...">
                </div>
            </div>
        </div>
    </div>

What am I missing ?

5 Answers 5

4

I use ngFor first variable to set the class for the first item

template

<div id="carouselExampleCaptions" class="carousel slide" data-ride="carousel">
  <ol class="carousel-indicators">
    <li data-target="#carouselExampleCaptions"  *ngFor="let item of items;let index = index" [attr.data-slide-to]="index"></li>
  </ol>
  <div class="carousel-inner">
    <div class="carousel-item" *ngFor="let item of items;let index = index;let isFirst = first" [ngClass]="{active:isFirst}">
      <img [src]="item.url" class="d-block w-100" [alt]="item.title">
      <div class="carousel-caption d-none d-md-block">
        <h5 [textContent]="item.title"></h5>
        <p [textContent]="item.symmery"></p>
      </div>
    </div>
  </div>
  <a class="carousel-control-prev" href="#carouselExampleCaptions" role="button" data-slide="prev">
    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
    <span class="sr-only">Previous</span>
  </a>
  <a class="carousel-control-next" href="#carouselExampleCaptions" role="button" data-slide="next">
    <span class="carousel-control-next-icon" aria-hidden="true"></span>
    <span class="sr-only">Next</span>
  </a>
</div>

trigger carousel manualy like this

  ngAfterViewInit(){
    $('#carouselExampleCaptions').carousel()
  }

demo 🚀

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

Comments

3

I think ngFor will modify you html tree.

try to use:

<ng-container *ngFor="let pic of pics">

instead:

<div *ngFor="let pic of pics">

Comments

3

Could you try this , it uses ngClass to set only first item in the list to active.

<div id="carouselExampleIndicators" #mycarouselControls class="carousel slide" data-ride="carousel" data-interval="2000">
    <div class="carousel-inner">                
            <ul *ngFor="let pic of pics;let i=index; first as isFirst">
                <div [ngClass]="isFirst ? 'carousel-item active' : 'carousel-item' ">
                    <li><img src={{pic}} class="d-block w-100 carousel-pic" alt="..."></li>
                </div>                                     
            </ul>
    </div>
</div>

1 Comment

This is the easiest approach :)
1

You may use OnPush change detection, so create a dumb component.

@Component({
    selector: 'app-carousel-items',
    changeDetection: ChangeDetectionStrategy.OnPush,
    template: `<div *ngFor="let pic of pics">
                 <div class="carousel-item">
                   <img src="http://MYURL/public/PinPhotos/{{pic.url}}" class="d-block w-100 carousel-pic" alt="...">
                 </div>
               </div>`,
})
export class CarouselItemsComponent  {
  @Input('pictures') pictures; // pass your pictures from this input  
}

Now your loop will not start again.

1 Comment

I think mention onPush her is a great tip 👍 but app-carousel-items will create a new wrapper item I don't know if this will work so far this is a jquery world now 🤔🤔 or we may need to trigger carousel manual
0

There are a couple of issues with your code.

First, you are applying the active class on every carousel-item. To remedy that, we need to remove the hard-coded class from the template and add it dynamically to the first item. Luckily we can get the index with the help of ngFor and apply it to the first item using ngClass.

Next, for your carousel-indicators you have it left static with three indicators, hence only three navigator buttons shown and the issues with carousel getting stuck. To fix that we can use ngFor again on indicator items, bind the index to data-slide-to, and like we did before, set the active class to the first item using ngClass.

I use Bootstrap 5 but adapted the code to Bootstrap 4 so this should work.

<div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel">

    <ol class="carousel-indicators">
        <li *ngFor="let pic of pics; let i = index" data-target="#carouselExampleIndicators" [attr.data-slide-to]="i" [ngClass]="{'active': i == 0}"></li>
    </ol>

    <div class="carousel-inner">
        <div *ngFor="let pic of pics; let i = index" class="carousel-item" [ngClass]="{'active': i == 0}">
            <img src="http://MYURL/public/PinPhotos/{{pic.url}}" class="d-block w-100 carousel-pic" alt="...">
        </div>
    </div>

    <button class="carousel-control-prev" type="button" data-target="#carouselExampleCaptions" data-slide="prev">
        <span class="carousel-control-prev-icon" aria-hidden="true"></span>
        <span class="visually-hidden">Previous</span>
    </button>
    <button class="carousel-control-next" type="button" data-target="#carouselExampleCaptions" data-slide="next">
        <span class="carousel-control-next-icon" aria-hidden="true"></span>
        <span class="visually-hidden">Next</span>
    </button>

</div>

For anyone looking for Bootstrap 5 solution, it is very similar:

<div id="carouselExampleCaptions" class="carousel slide" data-bs-ride="carousel">

    <div class="carousel-indicators">
        <button *ngFor="let url of picUrls; let i = index" type="button" data-bs-target="#carouselExampleCaptions" [attr.data-bs-slide-to]="i" aria-current="true" aria-label="..." [ngClass]="{'active': i == 0}">
        </button>
    </div>

    <div class="carousel-inner">
        <div *ngFor="let url of picUrls; let i = index" class="carousel-item" [ngClass]="{'active': i == 0}">
            <img src="{{url}}" class="d-block w-100" alt="...">
            <div class="carousel-caption d-none d-md-block">
                <h5>First slide label</h5>
                <p>Some representative placeholder content for the first slide.</p>
            </div>
        </div>
    </div>

    <button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide="prev">
        <span class="carousel-control-prev-icon" aria-hidden="true"></span>
      <span class="visually-hidden">Previous</span>
    </button>
    <button class="carousel-control-next" type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide="next">
        <span class="carousel-control-next-icon" aria-hidden="true"></span>
        <span class="visually-hidden">Next</span>
    </button>

</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.