Modal with back button: Data are double posted, bug?


#1

Hi everyone!

I have a modal (add/formPage) with a back button and submit button at the top. If I click the submit button (reactive form) I can see the data on my listPage, that’s good. But if I press the back button I see also the post on the listPage (emty object). The back button shouldn’t post data just go back. For the back button I use the navCtrl pop method. So I don’t call the viewCtrl dismiss method twice. Does anyone have an idea what I did wrong in my code or is that a bug?

Kind regards,
Thomas

listPage.ts

import { Component, OnInit } from '@angular/core';
import { NavController, ModalController } from 'ionic-angular';

import { CVideoAddPage } from '../c-video-add/c-video-add';
import { ConsumerVideoModel } from '../c-video.model';
import { ConsumerVideoHttp } from '../c-video.http';

@Component({
    selector: 'c-video-list',
    templateUrl: 'c-video-list.html',
})

export class CVideoListPage implements OnInit {

    videos: ConsumerVideoModel[ ];

    constructor(public navCtrl: NavController, public navParams: NavParams, public modalCrtl: ModalController, private consumerVideoHttp: ConsumerVideoHttp) {

    }

    ngOnInit() {
        this.getVideos();
    }

    getVideos(): void {
        this.consumerVideoHttp.getVideos().subscribe(videos => this.videos = videos);
    }

    addVideo() {
        let videoModal = this.modalCrtl.create(CVideoAddPage);

        videoModal.onDidDismiss(video => {
            this.consumerVideoHttp.addVideo(video).subscribe(video => this.videos.push(video));
        });

        videoModal.present();
    }

}

listPage.html

<ion-content>
    <ion-card *ngFor="let video of videos">
        <button ion-item>
            <ion-thumbnail item-start>
                <img [src]="video.file">
            </ion-thumbnail>
            <h2 ion-text text-wrap color="black" class="text-bolder">{{video.id}} {{video.title}}</h2>
            <p>{{video.publisher}}</p>
            <p text-wrap>
                <ion-icon name="eye"></ion-icon>
                {{video.views | number}} •
                 <ion-icon name="thumbs-up"></ion-icon>
                 {{video.likesPercentage | percent}} •
                 <ion-icon name="time"></ion-icon>
                 {{myDate | amTimeAgo: true}}
             </p>
            <button ion-button small clear icon-only item-end (click)="deleteVideo(video)">
                <ion-icon name="trash" color="dark"></ion-icon>
            </button>
        </button>
    </ion-card>

    <ion-fab right bottom #fab>
        <button ion-fab color="primary" (click)="addVideo()">
            <ion-icon name="videocam"></ion-icon>
        </button>
    </ion-fab>
</ion-content>

addPage.ts

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { NavController ViewController } from 'ionic-angular';

import { ConsumerVideoModel } from '../c-video.model';

@Component({
  selector: 'c-video-add',
  templateUrl: 'c-video-add.html',
})

export class CVideoAddPage {

    video = new ConsumerVideoModel();

    videoForm: FormGroup;

    constructor(public navCtrl: NavController, public viewCtrl: ViewController, private formBuilder: FormBuilder) {

    }

    ngOnInit() {
        this.videoForm = this.formBuilder.group({
            title: ["", Validators.required],
            description: [""]
        });
    }

    back() {
        this.navCtrl.pop();
   }

   addVideo() {
       this.video = this.videoForm.value;
       this.viewCtrl.dismiss(this.video);
   }

}

addPage.html

<ion-header>
    <ion-toolbar color="light">
        <ion-buttons left>
            <button ion-button icon-only color="dark" (click)="back()">
                <ion-icon name="arrow-round-back"></ion-icon>
            </button>
        </ion-buttons>
        <ion-title>Post Video</ion-title>
        <ion-buttons end>
            <button ion-button icon-only color="dark">
                <ion-icon name="more"></ion-icon>
            </button>
        </ion-buttons>
        <ion-buttons end>
            <button ion-button icon-only color="primary" type="submit" form="submit" [disabled]="!videoForm.valid">
                <ion-icon name="send"></ion-icon>
            </button>
        </ion-buttons>
    </ion-toolbar>
</ion-header>

<ion-content>
    <form id="submit" [formGroup]="videoForm" (ngSubmit)="addVideo(); clearForm.resetForm()" #clearForm="ngForm">
        <ion-card>
            <ion-item>
                <ion-label floating>Title</ion-label>
                <ion-input type="text" formControlName="title"></ion-input>
            </ion-item>
        </ion-card>

        <ion-card>
            <ion-item>
                <ion-label floating>Description</ion-label>
                <ion-textarea textarea-dynamic rows="1" formControlName="description"></ion-textarea>
            </ion-item>
        </ion-card>
    </form>
</ion-content>


#2

Hi , on listPage.ts delete :

 ngOnInit() {
        this.getVideos();
    }

and set this.getVideos(); on the constructor


#3

I tried it out, but the problem is not solved. According to the Angular style guide, you should call things like http request in the ngOnInit method and not in the constructor. Do you have any other idea?

Here are an image of my problem:

Problem

The item with the title “Test” is the item which is correct (submit button). The item/post below the Test post has no title and occurs when I click the back button.


#4

try with push don’t use pop , this.navCtrl.push(NameClass);


#5

You should not pop (or push) but dismiss the modal too in your back method I would say

export class CVideoAddPage {
  back() {
    this.viewCtrl.dismiss(null); // dismiss with null to catch it
  }
}

Grab the null result and do nothing in such a case

export class CVideoListPage implements OnInit {
    addVideo() {
    let videoModal = this.modalCrtl.create(CVideoAddPage);

    videoModal.onDidDismiss(video => {
           if (video !== null) {
                         this.consumerVideoHttp.addVideo(video).subscribe(video => this.videos.push(video)); 
          }
    });

    videoModal.present();
    }
}

#6

Thanks a lot, it works! It’s a bit strange that Ionic doesn’t add a back button automatically to the Modal Component. That’s a common thing that a user has always the possibility to click a back button…


#7

Cool to hear it worked out.

Maybe there is no back button on modal component per default because on bigger devices like iPad modals don’t fit the all screen respectively you could close modal by just clicking outside of it…don’t know just a thought