Passing params to Modal - how to bind when sent?


#1

I’ve a function that passes an object from one page to a Modal with NavParams.

UPDATE: Solved below. See the last post. Thanks to everyone who gave input.

Hopefully those that follow will get some benefit from this.

This is it:

presentAboutModal(select) {
  	var modalText = [
			{
				title:	'What',
				text:	'This is...'
			},
			{
				title:	'Who',
				text:	'This is for anyone ...'
			},
			{
				title:	'Why',
				text:	'This makes it easy...'
			},
			{
				title:	'Contact',
				text:	'Contact us...'
			},
		];
  	var choice = modalText[select];
   	let aboutModal = this.modalCtrl.create(ModalPage, {choice});
   	aboutModal.present();

Once it gets there I check for it in modal.ts like this:

export class ModalPage {

constructor(public viewCtrl: ViewController, public params: NavParams) {
	var choice  = this.params.get('choice');
	console.log(choice);
}
	
 dismiss() {
   this.viewCtrl.dismiss();
 }
}

This all works fine.

But I want to change the text in the modal dependant upon which button was pressed.

If I use:
<ion-title>{{choice.title}}</ion-title>

I get an error.

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'title' of undefined
TypeError: Cannot read property 'title' of undefined

I don’t get it? The data is sent, the console.log works, but the data binding doesn’t work.


#2

That’s because you use var and the template doesn’t know how to bind to it. Declare choice in your class and change var into this.choice. That should work. I don’t know if I mentioned it to you before, but I advise you to use let instead of var because it behaves differently (and better) in typescript. You can do some reading up about that subject over here:

https://www.typescriptlang.org/docs/handbook/variable-declarations.html


#3

I do usually use let. I thought I’d use var so it would be less scope restrictive.

I’ve tried let, it doesn’t make any difference.


#4

You really should learn to read the answers you’re getting over here. I didn’t say you have to use let everywhere, I said the binding wasn’t working because you should use THIS to make the binding work. The template doesn’t know let/var/const/whatever because those are restricted. This ‘glues’ your variable to the template as well.[quote=“luukschoen, post:2, topic:88409”]
Declare choice in your class and change var into this.choice
[/quote]

So: under export class ModalPage {

add the following:

choice: { [title:string, text:string };

then change var choice = ... into this.choice = this.params.get etc


#5

If I use this.choice I get errors highlighting “this”.


#6

And you declared choice as I proposed? Post your full typescript here again then please.


#7
export class ModalPage {

	choice: { [title:string, text:string] };

	constructor(public viewCtrl: ViewController, public params: NavParams) {
		this.choice = this.params.get('choice');
		console.log(choice);
	/*	let this.content = {
			title:	'Title text',
			text:	'Text content'
		}
		console.log(content); */
	}
		
	 dismiss() {
	   this.viewCtrl.dismiss();
	 }
}

I tried it without the square bracket, as in you example, and with it.

The error I get is:

Typescript Error
An index signature must have exactly one parameter.

or

',' expected.

if I copy and paste your code.

This seems like it should be really simple, and in theory it’s much nicer to use than Ionic 1 was. But the problems I’m having here are, I’m sure you’ll agree, just silly. I’ve been reading about NavParams, I’ve watched Josh Morony’s video on it, and nowhere do I see descriptions of a need to declare things in the way you are describing. It’s… disappointing.


#8

Make an interface:

export interface ModalParams {
  title: string;
  text: string;
}

export class ModalPage {
  choice: ModalParams;

  constructor(np: NavParams) {
    this.choice = np.get('choice');
  }
}

#9

I’ve cracked it.

It was, indeed, to do with “this” but all it needed was some moving of code.

In the first page I have:

export class ContactPage {

  constructor(public navCtrl: NavController, public modalCtrl: ModalController, public params: NavParams) {
  }

  presentAboutModal(choice) {
   	let aboutModal = this.modalCtrl.create(ModalPage, {choice});
   	aboutModal.present();
 }

}

And in modal.ts:

export class ModalPage {

	choice;

	constructor(
		public viewCtrl: ViewController, 
		public params: NavParams
	){
		var choices = [
			{
				title:	'What',
				text:	'This is...'
			},
			{
				title:	'Who',
				text:	'This is for anyone ...'
			},
			{
				title:	'Why',
				text:	'This makes it easy...'
			},
			{
				title:	'Contact',
				text:	'Contact us...'
			}
		];
		this.choice = choices[this.params.get('choice')];
	}
		
	 dismiss() {
	   this.viewCtrl.dismiss();
	 }
}

I guess the modal.ts constructor needs to know that the object belongs to it, via this, and then it knows what do to with it.

Thanks for the input guys, it’s been helpful!

PS. I think the source for the modal demo in the components section of the docs should be modified. The modal-content.html is not used as the template is already in the .ts file and this is confusing for amateurs like me.


#10

I think having all those choices in the modal is a mistake, because you are identifying them only by numbers, which is brittle and hard to read. The choice object should be sent in to the modal as an object, not a number referencing an array that is not even a part of the public API of the modal page.


#11

Please make your code as we already proposed. Pass the object through the navparams. The way you’re solving this now isn’t a real solution for your problem. Just pass the object through those navparams and then bind it with this to your modal template.


#12

I tried what you said and it didn’t work.

I’ll try again.


#13

Ok, it’s working the other way now. I’ve no idea why though as I tried this and was getting errors I couldn’t fix. Here it is.

contact.ts

import { Component } from '@angular/core';
import { NavController, ModalController, NavParams } from 'ionic-angular';
import { ModalPage } from './modal';

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

  	constructor(public navCtrl: NavController, public modalCtrl: ModalController, public params: NavParams) {
	}	

	presentAboutModal(select) {

		var modalText = [
			{
				title:	'What',
				text:	'This is...'
			},
			{
				title:	'Who',
				text:	'This is for anyone ...'
			},
			{
				title:	'Why',
				text:	'This makes it easy...'
			},
			{
				title:	'Contact',
				text:	'Contact us...'
			}
		];

  		let choice = modalText[select];
   		let aboutModal = this.modalCtrl.create(ModalPage, {choice});
   		aboutModal.present();
 	}

}

modal.ts

import { Component } from '@angular/core';
import { ViewController, NavParams } from 'ionic-angular';

@Component({
  selector: 'modal',
  templateUrl: 'modal.html'
})
export class ModalPage {

	choice;

	constructor(public viewCtrl: ViewController, public params: NavParams){
		this.choice = this.params.get('choice');
		console.log(this.choice);
	}
		
	 dismiss() {
	   this.viewCtrl.dismiss();
	 }
}