Dynamic slide height

hey @ryanlogsdon, great way to solve it.

I am going to try the code out soon, but it looks good!

Glad you solved it!

This code isn’t work for me on ionic2 RC2. I solve that problem like this:

HTML:

<ion-slides #slider (ionWillChange)="slideWillChange()">
    <ion-slide *ngFor="let item of items; let itemIndex = index;" #slide>
        /// what you want
    </ion-slide>
</ion-slides>

TS:

@ViewChildren('slide') slides: QueryList<ElementRef>;
@ViewChild('slider') slider: Slides;

ionViewDidEnter() {
    this.slideWillChange();
}

slideWillChange() {
    this.slideElements = this.slides.toArray();
    let index = this.slider.getActiveIndex();

    this.slider._elementRef.nativeElement.style.height = this.slideElements[index].ele.children[0].clientHeight + 'px';
}

Hi @Vishin,

Can you share your updated code?

The slideWillChange() function does not compile in RC3. Specifically, this.slides.toArray(); cannot be turned into an array.

Thanks,
Ryan

Hi, I’ll share my code tomorrow when I try it on RC3, take a moment…

Hi All,

This will work in RC4:

HTML

<ion-slides #slider (ionDidChange)="SlideChanged()" [options]="_sliderOptions" id="ionSlider">
    <ion-slide #slide *ngFor="let robot of _robots">
        <ion-item *ngFor="let item of robot">
            <h3>{{ item }}</h3>
        </ion-item>
    </ion-slide>
</ion-slides>

Since there are a lot of things going on and extra packages needed, here’s the TS in its entirety:

TS

import { Component, ViewChild, ViewChildren, QueryList, ElementRef } from '@angular/core';
import { NavController, Slides } from 'ionic-angular';

@Component({
    selector: 'page-home',
    templateUrl: 'home.html'
})

export class HomePage {
    @ViewChildren('slide') slides: QueryList<ElementRef>;
    @ViewChild('slider') slider: Slides;

    public _robots: any[];
    public _sliderOptions: any;             // options for Ionic's native slider

    constructor(public navCtrl: NavController) {
        this._robots = [[],[],[]];           // 3 inner arrays
        var i;
        for(i = 1; i <= 5; i++)             // 1st element will have 5 items
            this._robots[0].push(i);
        for(i = 1; i <= 15; i++)             // 2nd element will have 15 items
            this._robots[1].push(i);
        for(i = 1; i <= 25; i++)             // 1st element will have 25 items
            this._robots[2].push(i);

        this._sliderOptions = {
            pager: false
        }
    }

    ionViewDidEnter() {
        this.SlideChanged();
    }

    SlideChanged() {
        let currentSlide = this.slider.getActiveIndex();
        let slideElements = this.slides.toArray();

        let targetSlide = slideElements[currentSlide];
        //console.log(targetSlide);
        let height = targetSlide['ele']['children'][0]['clientHeight'];
        //console.log('target slide height = ' + height);

        this.slider._elementRef.nativeElement.style.height = height + 'px';
    }
}

Many thanks to @Vishin!

2 Likes

Here is the RC5 solution.

HTML

    <div id="wrapper">
        <ion-slides #slider>
            <ion-slide *ngFor="let robot of _robots">
                your robots here
            </ion-slide>
        </ion-slides>
    </div>

You wil need the div wrapper for when the slides take up more than the length of the screen.

TS

  1. import ViewChild from @angular/core

  2. add this line to your class (anywhere is fine)

    @ViewChild('slider') slider: Slides;

  3. add this function to the class

     ngAfterViewInit() {
         this.slider.autoHeight = true;
     }
    

Thank you, Ionic Team, for making so many changes that the solution is this simple now!

4 Likes

I’ve not gotten this to work in my case - I don’t create the slider until the user selects an ion segment button.

Once the user selects this tab, this makes an api call and ngIf creates the slider underneath the tab.

Playing around with it, I’ve not gotten this.slider.autoHeight = true to adjust the slide height. Any thoughts on what I should try?

Remove the ngIf from the equation.

Try hard-coding a slider in place. Does it work? If the answer is still no, we know that the ngIf in not the problem.

I am at RC6. In my case if I load a 400x300 png sometimes it centers the images sometimes it does not?
If I load larger size images they may take the whole width of the available view area and thus no auto-height is taking place. I tried the div wrapper instead of , heh whatever you gurus say. Also tried, the sizing code you adjusted from @Vishin but I does not seem to work. The observer thingy does not seem to be available in ionic2 implementation, why not?

Here is the HTML

    <!--<section>-->
        <div id="wrapper">
        <ion-slides  #mySlider (ionSlideDidChange)="SlideChanged()">
            <ion-slide  #slides *ngFor="let s of Slides ;  let ii=index" class="AMSImage">
                <h1>Slide {{ii+1}} of {{AMSController.AMSData.Count}}</h1>
                <div id="AMSContent">
                    <img id="AMSImage" [src]="AMSController.GetImage(s)">

                    <div id="AMScontainer">
                        <div id="AMStemp">
                            <div id="AMStext" class=AMSText>
                                {{AMSController.AMSData.TextOfSlide(s)[0]}}
                            </div>
                        </div>
                    </div>
                </div>
                <div class="swiper-button-prev"></div>
                <div class="swiper-button-next"></div>
            </ion-slide>
            <!-- If we need navigation buttons -->
        </ion-slides>
        </div>
    <!--</section>-->

Here are the input props, (it took me a while to figure out what “input” meant, never heard such a thing)

 ngAfterViewInit() {
        console.log("Slider------------>>Input Props Set");
        // http://ionicframework.com/docs/v2/api/components/slides/Slides/
        // http://idangero.us/swiper/api/#.V6zJbPmU3RY for API, options, ...
        // 20160801 created
        // 20170202 breaking change -> changed to props at RC6
        this.slider.initialSlide = 0;
        this.slider.loop = false;
        this.slider.pager = true;
        this.slider.speed = 500;
        this.slider.centeredSlides = true;
        // this.slider.autoHeight = true;
        // this.slider.observer = true ; // not vailable
        // autoplay = 1000
        // effect = "cube"
    }

more code

// NOTE: this does NOT fire if the slider is already at the requested slide.
    // 20160808
    SlideChanged() {
        try {
            // this.AdjustHeight();
            var index = this.slider.getActiveIndex();
            console.log("slide CHANGED", index);
            // this.AudioPlayList.Play(this.AMSController.AMSData.Audio(index));
            this.AMSController.PlayIndex(index + 1);
        }
        catch (e) {
            console.log(<Error>e.message);
        }
    }

    // 20170203
    // https://forum.ionicframework.com/t/dynamic-slide-height/63891/15
    @ViewChildren('slides') slides: QueryList<ElementRef>;
    AdjustHeight(): void {
        let currentSlide = this.slider.getActiveIndex();
        let slideElements = this.slides.toArray();

        let targetSlide = slideElements[currentSlide];
        //console.log(targetSlide);
        let height = targetSlide['ele']['children'][0]['clientHeight'];
        //console.log('target slide height = ' + height);

        this.slider._elementRef.nativeElement.style.height = height + 'px';
    }

Is too much to expect the slider to auto-size? should I consider writing code to adjust height in landscape mode and width in portrait mode?

here is another snapshot in chrome, if the client area is small or I load large images like 1920x1080


What am I doing wrong?
Thank you.

Upgrade to Ionic v2.0.0 and report back with your issues.

There have been a lot of modifications to the back-end with respect to Swiper.js in v2.0.0.

I believe I am at 2.0.0, after RC6 there was no more upgrade instructions, it said enjoy!
I have to swipe on this dummy data in order to cause (ionSlideDidChange) to fire the event.

If I enable your AdjustHeight() code I get the following error

Cannot read property ‘children’ of undefined

let height = targetSlide['ele']['children'][0]['clientHeight'];

Right, the DOM changed a lot. “ele” has been replaced with “nativeElement”.

in a command prompt, type

ionic info

and paste that in here

ordova CLI: 6.4.0
Ionic Framework Version: 2.0.0-rc.6
Ionic CLI Version: 2.2.1
Ionic App Lib Version: 2.2.0
Ionic App Scripts Version: 1.0.0
ios-deploy version: Not installed
ios-sim version: Not installed
OS: Windows 7
Node Version: v7.2.0
Xcode version: Not installed

You’re on RC6. Upgrade to 2.0.0 Final, then follow post #16. It works perfectly.

2.0.0 shows no steps at this link?


Also please what is post #16, I have become the dumbest programmer on the face of this planet :slight_smile:

post 16

:slight_smile:

So are there upgrade steps to go from RC6 to 2.0.0? I can’t see them in snapshot above.

I believe I am doing all what you specified in post 16, I have enabled autoHeight = true, ngAfterViewInit() is getting fired, I can’t see that in the console.

@ViewChild('mySlider') slider: Slides;
 ngAfterViewInit() {
        console.log("Slider------------>>Input Props Set");
        // http://ionicframework.com/docs/v2/api/components/slides/Slides/
        // http://idangero.us/swiper/api/#.V6zJbPmU3RY for API, options, ...
        // 20160801 created
        // 20170202 breaking change -> changed to props at RC6
        this.slider.initialSlide = 0;
        this.slider.loop = false;
        this.slider.pager = true;
        this.slider.speed = 500;
        this.slider.centeredSlides = true;
        this.slider.autoHeight = true;
        // this.slider.observer = true ; // not available
        // autoplay = 1000
        // effect = "cube"
    }

However, I do not get any auto sizing of the images.


Thank you.

I never upgrade. It takes only a few minutes to create a new app and drop in your existing code.

With all respects, I think that’s totally crazy :slight_smile: the ionic team might as well support my src/ and other configs and folders side-by-side, if “drop in your existing code” means replace the blank app with my src code. Blowing 30,000 files and creating news one is getting on my nerves :), while we keep creating hello programs I see no productivity.

Anyways, I did what you said Boss.
ionic start --v2 myApp tabs

$ ionic info

Your system information:

 ordova CLI: 6.4.0
Ionic Framework Version: 2.0.0
Ionic CLI Version: 2.2.1
Ionic App Lib Version: 2.2.0
Ionic App Scripts Version: 1.0.0
ios-deploy version: Not installed
ios-sim version: Not installed
OS: Windows 7
Node Version: v7.2.0
Xcode version: Not installed

Replace home.html with

<ion-header>
  <ion-navbar>
    <ion-title>Home</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <div id="wrapper">
    <ion-slides #mySlider (ionSlideDidChange)="SlideChanged()">
      <ion-slide  *ngFor="let s of Slides ;  let ii=index" class="AMSImage">
        
          <img id="AMSImage" src={{s.PIC}}> 

      </ion-slide>
    </ion-slides>
  </div>
</ion-content>

home.ts now looks like after some trimming…I kept just the image alone in ion-slide no slide titles or other divs…

import { Component } from '@angular/core';

import { NavController } from 'ionic-angular';
import { Slides } from 'ionic-angular'; // 20160807
import { ViewChild } from '@angular/core'; // 20160807

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController) {
  }

  @ViewChild('mySlider') slider: Slides;
  ngAfterViewInit() {
    console.log("Slider------------>>Input Props Set");
    this.slider.autoHeight = true;
  }
  Slides: any = [
    { PIC: "http://arabicrescue.com/ARABIC/NUMBERS.BMP/BY DIGITS/01 10/01 01.png" }
    , { PIC: "http://arabicrescue.com/ARABIC/NUMBERS.BMP/BY DIGITS/01 10/01 02.png" }
    , { PIC: "http://arabicrescue.com/ARABIC/NUMBERS.BMP/BY DIGITS/01 10/01 03.png" }
    , { PIC: "http://arabicrescue.com/ARABIC/NUMBERS.BMP/BY DIGITS/01 10/01 04.png" }
  ];

  SlideChanged() {
  }
}

still no resizing. Sometimes on launch only the top 20% of the 1st image is painted, until I swipe.

Let me know what I missed. Are you testing with tabs template?
Thanks
Here is what I see on ionic serve -w chrome or from vscode, and I expect the image to be shrunk height-wise to fit.

Don’t blow a gasket, & don’t get too far off track there. Drop your code, meaning just copy and paste. You asked a question on slides. I’ve been trying to help. If you need help upgrading, read the many topics that will tell you exactly what to do.

Ionic’s quite nice. It only takes a little code to do all you need to do. And upgrading this way will show you all the structural changes. Want to diff 2, 3, 4 or more changelogs? Go for it. It doesn’t give the same as you following the architecture changes, yourself. And there are a TON of changes. …you’d notice them all if you follow the steps listed above. Good luck.