Sireini
Sireini

Reputation: 4262

ìonic 2 - How to dynamically set pages

I am working on a project where I have a set of exercises and when I click the exercise I navigate to an other page where you can play a video of this exercise. What I do now is the following:

this is my home.html:

<ion-card *ngIf="oefening1" (click)="navigate(oefening1, oefening2, oefening3, oefening4)">
<img src="assets/img/{{ oefening1 }}.jpg"/>
<ion-card-content>
  <ion-card-title>{{ oefening1 }}</ion-card-title>
  <p>Setjes: {{ set1 }}</p>
  <p>Herhalingen: {{ rep1 }}</p>
</ion-card-content>

<ion-card *ngIf="oefening2" (click)="navigate(oefening2, oefening1, oefening3, oefening4)">
    <img src="assets/img/{{ oefening2 }}.jpg"/>
    <ion-card-content>
      <ion-card-title>{{ oefening2 }}</ion-card-title>
      <p>Setjes: {{ set2 }}</p>
      <p>Herhalingen: {{ rep2 }}</p>
    </ion-card-content>
  </ion-card>

this is my navigate function in home.ts:

navigate(exercise, exercise2, exercise3, exercise4){
  this.navCtrl.push(ExercisePage, {
            clickedExercise: exercise,
            secondExercise: exercise2,
            thirdExercise: exercise3,
            fourthExercise: exercise4
    });
  }

This is my exercise.html:

<ion-content padding overflow-scroll="true">
  <ion-grid>
  <ion-row>
    <ion-col col-12>
      <div (click)="playVid()" padding-bottom>
        <img *ngIf="fullPath" [src]="fullPath"/>
      </div>
      <div text-center>
        <button ion-button block [disabled]="!disabledBtn">Block Button</button>
        <button ion-button round (click)="nextExercise()">Voltooi</button>
      </div>
    </ion-col>
  </ion-row>
  </ion-grid>
</ion-content>

And the exercise.ts:

export class ExercisePage {
  public clickedExercise: any;
  public secondExercise: any;
  public thirdExercise: any;
  public fourthExercise: any;
  public fullPath: string;
  public disabledBtn: boolean;

  constructor(public navCtrl: NavController, private streamingMedia: StreamingMedia, public params:NavParams) {
    this.clickedExercise = params.get("clickedExercise");
    this.secondExercise = params.get("secondExercise");
    this.thirdExercise =  params.get("thirdExercise");
    this.fourthExercise = params.get("fourthExercise");
    this.disabledBtn = false;
  }

  playVid(){
     console.log('video completed');

     setTimeout(() => {
      this.disabledBtn = true;
    }, 10000);

    // Playing a video.
    let options: StreamingVideoOptions = {
        successCallback: () => { console.log('Video played') },
        errorCallback: (e) => { console.log('Error streaming') },
        orientation: 'portrait'
    };

    this.streamingMedia.playVideo('http://www.sylvanreinieren.com/fysioWebapp/videos/'+ this.clickedExercise + '.mp4', options);
  }

  ionViewWillEnter() {
    this.fullPath = "assets/img/" + this.clickedExercise + ".jpg";
    // console.log('secondExercise:',this.secondExercise, 'ThirdExercise: ', this.thirdExercise, 'Fourth: ', this.fourthExercise);
  }

  nextExercise(){
    this.clickedExercise = this.secondExercise;
    this.secondExercise = this.thirdExercise;
    this.thirdExercise = this.fourthExercise;

    this.navCtrl.push(ExercisePage, {
        clickedExercise: this.secondExercise,
        secondExercise: this.thirdExercise,
        thirdExercise: this.fourthExercise
    });

    console.log('nextExercise', this.clickedExercise);
  }
}

So basically what I want to achieve is that when I click the button with the method nextExercise the next exercise has to show, but it seems that it skips the second exercise. And when it runs through all exercises it has to return to home.

Does anyone know how to achieve this properly?

Upvotes: 0

Views: 345

Answers (1)

Gabriel Barreto
Gabriel Barreto

Reputation: 6421

So as i said, i think it's better for you having this in a Slider. Why?

  • You already know how many exercises there are, in this case 4.
  • Every navCtrl.push you do is a new page, it's not updating and existing page.
  • If one day you expand and have like 20 exercises per page, you don't want you user clicking back 20 times if he/she wants to leave the exercises.
  • It's easy to manipulate.

In this case i'll focus only on the exercises page, if you want to change the Home and let it be more dynamic, we can do something for that too.

Exercise.html

<ion-content overflow-scroll="true">
    <ion-slides>
        <ion-slide *ngFor="let ex of allExercises; let i = index">
            <ion-grid>
                <ion-row>
                    <ion-col col-12>
                        <div (click)="playVid(ex.exercise)" padding-bottom>
                            <img [src]="ex.path" />
                        </div>
                        <div text-center>
                            <!-- can't go back if it's the first exercise -->
                            <button *ngIf="i == 0" ion-button round (click)="previousExercise()">Previous</button>
                            <button ion-button block [disabled]="!disabledBtn">Block Button</button>
                            <!-- will not have a next exercise if it's the last one -->
                            <button *ngIf="i == ;" ion-button round (click)="nextExercise()">Voltooi</button>
                        </div>
                    </ion-col>
                </ion-row>
            </ion-grid>
        </ion-slide>
    </ion-slides>
</ion-content>

Exercises.ts

import { Slides } from 'ionic-angular';
export class ExercisePage {
    public fullPath: string;
    public disabledBtn: boolean;
    public allExercises: any[] = []; // INITIALIZE A VAR THAT'LL HOLD ALL EXERCISES

    constructor(
        public navCtrl: NavController,
        private streamingMedia: StreamingMedia,
        public params: NavParams,
        public slides: Slides
    ) {
        // GET ALL EXERCISES AND THE IMAGE PATH ON PAGE CONSTRUCRION
        this.allExercises.push({
            exercise: params.get("clickedExercise"),
            path: 'assets/img/' + params.get("clickedExercise") + '.jpg'
        });
        this.allExercises.push({
            exercise: params.get("secondExercise"),
            path: 'assets/img/' + params.get("secondExercise") + '.jpg'
        });
        this.allExercises.push({
            exercise: params.get("thirdExercise"),
            path: 'assets/img/' + params.get("thirdExercise") + '.jpg'
        });
        this.allExercises.push({
            exercise: params.get("fourthExercise"),
            path: 'assets/img/' + params.get("fourthExercise") + '.jpg' 
        });
        this.disabledBtn = false;

        // block the swipe to change page
        slides.lockSwipes(true);
    }

    playVid(exercise: string) {
        console.log('video completed');

        setTimeout(() => {
            this.disabledBtn = true;
        }, 10000);

        // Playing a video.
        let options: StreamingVideoOptions = {
            successCallback: () => { console.log('Video played') },
            errorCallback: (e) => { console.log('Error streaming') },
            orientation: 'portrait'
        };

        this.streamingMedia.playVideo('http://www.sylvanreinieren.com/fysioWebapp/videos/' + exercise + '.mp4', options);
    }

    nextExercise() {
        this.slides.lockSwipes(false);
        this.slides.slideNext();
        this.slides.lockSwipes(true);
    }

    // If you want to let the user go back to previous exercise
    previousExercise() {
        this.slides.lockSwipes(false);
        this.slides.slidePrev();
        this.slides.lockSwipes(true);
    }
}

So you create an object that'll hold all your exercises.

In this object you push the exercise and the image path (since i don't know what and exercise is, i'm assuming it's just it's name).

You'll import the Slides component and lock the swipe so the user can't change the slide with swipe (you can let him do this, if you want to).

In your HTML just use the ion-slides tag and a ion-slide with a *ngFor taking all you exercises.

In your playVid() you'll pass the exercise's name for the video to play.

Hope this helps

Upvotes: 1

Related Questions