Creating Multi-template Modals (?)


#1

Hello!

I am building my second application on Ionic, the first in v3. Something that is bugging me is that I am not sure how to use a single Modal class to every need in the app. Or if that is even possible. Does Ionic require us to define a Modal class for every different html resource?

Today I have something like this:

@Component({
    templateUrl: 'my_modal.html'
})
export class MyModal {

    private title: any;
    private message: any;

    constructor(params: NavParams, public renderer: Renderer, public viewCtrl: ViewController) {
        // this.renderer.setElementClass(viewCtrl.pageRef().nativeElement, 'my-popup', true);
        // this.form = FormData;
        this.title = params.data.title;
        this.message = params.data.message;
    }

    dismiss() {
        this.viewCtrl.dismiss();
    }

}

Thanks for your help.

Ortiz


#2

Question, on what I’m not seeing it the code

where are the injectable calls

  • import { Injectable } from ‘@angular/core’;
  • @Injectable()

I have found the easist way to create a base for doing this is to use

ionic g provider [NAME]


#3

Hi

I don’t think Injectables are the answer nor an issue

As to the question: yes, you need a separate class per html template.

Unless of course you fill the html with ngSwitch, ngIf or ngFor directives to create various instances

Hope this helps

Tom


#4

Cool (Still newbie and learning)

what if he uses inline template


 @Component({
   template: `<ion-header>

  <ion-navbar>
    <ion-title></ion-title>
  </ion-navbar>

</ion-header>

<ion-content padding>

</ion-content>
`
})

This way he can easily work with directive and code in an encapulated form


#5

Hi

well no clear yes/no answer to this as I need to understand the objective of the exercise better. My take on it is:

If you are seeking to create a nice class hierarchy, then mind you that inheritance only takes the methods, not the template. So if that is what you are looking for (inheritance of controller logic), then your example may be a nice starting point for an abstract class. (although it lacks the class definition itself, so it is not complete).

If you are looking for different templates , then inheritance may not do the trick for you as I believe templates are not inherited in a way that you can enrich the parent.

Going back to the original question/comments from @fOrtiz :

how to use a single Modal class to every need in the app. Or if that is even possible. Does Ionic require us to define a Modal class for every different html resource?

I find the above difficult to understand, as I don’t think there is such a thing as a Modal class. What you typically do is: create an ordinary class, decorate with @Component (or @Page etc) and then use the ModalController to present it. And yes, you need to create a new class/Component definition for each different HTML template, unless, of course, you use data binding, template directives and all the nice goodies Angular gives you.

For that I suggest everyone starting with Ionic, first to go through the tutorial @ angular.io. Most of the questions new people ask on this forum are actually related to angular.io and a lack of understanding of its architecture. Including difference between @Component and @Injectable.

Regards

Tom


#6

I am not sure what you meant by that, but thanks for the answer.


#7

Hi Tom, thanks for your help.
I haven’t thought about filling all the templates inside ngSwitches/ngIfs, that could be a nice workaround.
To explain it better, if you are familiar with Android development, think of the AlertDialog class. You provide it with a layout resource id (reference to a xml layout file), and it inflates, or renders, that custom layout you chose. Thing is, there is not an AlertDialog class for every separate AlertDialog you need in your project, you just need one. This is the development approach I’m used to, and I am trying to find out if Ionic has that too.


#8

@Ben1nB1ack This is very useful, I do use it in quick alerts here or there. But I wanted to create a generic class which could receive any template as a parameter, when creating a Modal. Something that’d look like this:

    var pop = this.modalCtrl.create(GenericModal, 'sales_report.html');
    pop.present({
        ev: ev
    });

@Tommertom Thank you for this clarification. I am still a bit new to the concept of Ionic and Angular, and sometimes I yet cannot fully differentiate what’s Ionic and what’s Angular. From what I gather, seems what I’m calling a Modal class is actually a Component that is presented through a Modal controller. If that caused confusion, I apologize for that. The above example illustrates what I’m trying to accomplish. I am trying to create a utility where you supply a template (preferably the url) and the utility class would render that template in a Modal. This is so that I wouldn’t need to create a class for every Modal I’d have in my app, and thus have to declare every one of them in the modules.
From what you said, I figure this might be an Angular related question, so I’ll investigate the link you left here.

Thanks again for you all.

Ortiz


#9

Hi

This form of dynamic templating cannot be done by supplying a reference to a html in the @Conponent decorator nor as parameter to the ionic api.

You are not the first to explore on this forum and I cant find the forum discussion right now so you read all views.

If you really want this, with tons of ui flexibility ypu basically need to build your own rendering Conponent which is probably going to look awful in html and ts coding

Indeed it may be good to dive more into angular, template binding and its architecture and see what you really need. Angular.io is the best place to start learning before applying the UI sugar Ionic gives.

What is the flexibility you are looking for? If it is just a string, go for binding? Maybe if you share, I can give you my ideas

Regards

Tom


#10

And yes, you will find yourseld putting components declared in app.module. If you dont want that, then you can put them in a separate module which you load in app.module.

Again, all Angular stuff with a scent of Ionic


#11

The kind of flexibility I want…
Ok, it’s not just a string. Otherwise, I think I might have been able to figure out that I can send a value through the NavParams and assign it to a label through data binding.
one of the screens I plan on doing contains a couple input fields and a star rating feature (which in this case will be buttons, I didn’t like much the npm plugin that is out there). This is what it looks like:

<ion-header>
    <ion-navbar>
        <ion-buttons start>
            <button ion-button icon-only margin-right (click)="dismiss()">
                <ion-icon name='arrow-back'></ion-icon>
            </button>
        </ion-buttons>
        <ion-title>{{ title }}</ion-title>
        <ion-buttons end>
            <button ion-button icon-only margin-right>
                <ion-icon name='checkmark'></ion-icon>
            </button>
        </ion-buttons>
    </ion-navbar>
</ion-header>
<ion-content padding>
    <!-- content will be here :)  -->
</ion-content>

To make this component as versatile as I want is not that hard, because I could indeed use several ngSwitches as you suggested before. I just wanted to build a multipurpose component, so that I could use it easily in other projects.


#12

@fOrtiz

You do need a separate class for each modal, but you could definitely create a display service to call Alert, Toast, Loader, Modal, Popover, etc in a consistent fashion and reduce the code you put in your parent classes. You’re on the right track with your original code and yes, you would use @Injectable.

import { Injectable } from '@angular/core';
import { ModalController, Modal } from 'ionic-angular';

@Injectable()
export class DisplayUtils {
  constructor(private ModalController: ModalController) {}

  public Modal(component: any, params?: any): Modal {
    let modal = this.ModalController.create(component, params);
    modal.present();
    return modal;
  }

Depending on how you structure your services you might call it like this:

let modalInstance = this.Utilities.Display.Modal(SpecificModalComponent, {navParams});
modalInstance.onDidDismiss(data => {
  // do something
})

#13

@soundboard6 To generify the calling of those components is a great idea. Anyway, I think I will keep doing the modal as I first intended, one by one. Thank you all for your help!