This post is kinda old, there is a full example on using IonModal Here No TS Ionic Vue Example If you have issues let me know.
-
The Ionic Components forVueJS are still in beta, but I have been using them for a while now and occasionally go back and update some of the samples I have posted in my github repo. Recently I was asked about handling modals, callbacks. I am going to quickly cover all of those in this blog post.
See Video
Setting Up The Parent Component App
to Call Modal
<template>
<ion-app>
<ion-page>
<ion-header>
<ion-toolbar color="primary">
<ion-title>Modal Test App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-button @click="openModal">Show Modal</ion-button>
</ion-content>
</ion-page>
</ion-app>
</template>
first we import the modal component
import SimpleModal from "./components/SimpleModal.vue";
Inside the script tag for our page, in the methods, section we create a modalCloseHandler
method that will be called when the modal is closed.
modalCloseHandler(_value) {
console.log("modal-closed", _value);
if (_value.success) {
// only on success
alert(JSON.stringify(_value.noteInfo, null, 2));
}
}
then we have the function openModal
that will actually open the modal. In this example I am passing in a property timeStamp
just as a way to show how properties are passed into the component when using Ionic.
We next call modal.present()
to actually show the modal.
Then finally wait for a response with modal.onDidDismiss()
We need to handle the scenario where the user clicks the backdrop to exit the modal; in that situation we do not want to process the response.
async openModal() {
let modal = await this.$ionic.modalController.create({
component: SimpleModal,
componentProps: {
propsData: {
timeStamp: new Date()
}
}
});
// show the modal
await modal.present();
// wait for a response when closing the modal
let modalResponse = await modal.onDidDismiss();
// when dismissed by backdrop click, data is undefined,
// we only process a response from the user behavior
modalResponse.data && this.modalCloseHandler({...modalResponse.data})
}
This is the complete <script>
section of the App
component
import SimpleModal from "./components/SimpleModal.vue";
export default {
name: "App",
components: {},
methods: {
/**
* called when the modal is closed
*/
modalCloseHandler(_value) {
console.log("modal-closed", _value);
if (_value.success) {
// only on success
alert(JSON.stringify(_value.noteInfo, null, 2));
}
},
/**
* when the user clicks button, we open the modal
*/
async openModal() {
let modal = await this.$ionic.modalController.create({
component: SimpleModal,
componentProps: {
parent: this,
propsData: {
timeStamp: new Date()
}
}
});
// show the modal
await modal.present();
// wait to see if i get a response
let modalResponse = await modal.onDidDismiss();
// when dismissed by clicking outside of modal,
// data is undefined so we do not handle it
modalResponse.data && this.modalCloseHandler({...modalResponse.data})
}
}
};
The Modal Component - SimpleModal
Please note that the input elements are specific to vue; We are using the vue specific input elements ion-input-vue
and ion-textarea-vue
We handle the button click events by calling modalClose(true)
when user wants to save the data and modalClose(false)
when user clicks cancel
<template>
<div>
<ion-header>
<ion-toolbar>
<ion-title>Note Modal</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-item>
<ion-label color="primary" position="floating">Title</ion-label>
<ion-input-vue
type="text"
name="title"
placeholder="Title for note..."
v-model="noteInfo.title"
></ion-input-vue>
</ion-item>
<ion-item>
<ion-label color="primary" position="floating">Description</ion-label>
<ion-textarea-vue rows="5" placeholder="Note description" v-model="noteInfo.description"></ion-textarea-vue>
</ion-item>
<ion-item style="font-size:smaller; text-align: center" lines="none">
<ion-label>{{(timeStamp +"").split('(')[0]}}</ion-label>
</ion-item>
<ion-row>
<ion-col>
<ion-button expand="block" @click="modalClose(true)">Save Note</ion-button>
</ion-col>
<ion-col>
<ion-button expand="block" color="danger" @click="modalClose(false)">Cancel</ion-button>
</ion-col>
</ion-row>
</ion-content>
</div>
</template>
Inside the code/ script tag section of the component be sure to specify the properties that are being passed into the component; in this case it is just the timeStamp
export default {
name: "SimpleModal",
props: ["timeStamp"],
methods: {}
}
We specify the data fields for the form we are working with in the data section of the modal component.
data() {
return {
noteInfo: {
title: "",
description: ""
}
};
}
And finally the modalClose
function in the methods section. Here we return the data from the form if success
is true otherwise we return null.
to pass the information back to the parent onDismiss
listener, we access the controller this.$ionic.modalController
and call the dismiss method passing the response data as the parameter.
methods: {
modalClose: function(success) {
let response = {
success,
noteInfo: success ? this.noteInfo : null
};
this.$ionic.modalController.dismiss(response);
}
},
This is the complete <script>
section of the SimpleModal
component
export default {
name: "SimpleModal",
props: ["timeStamp"],
methods: {
modalClose: function(success) {
let response = {
success,
noteInfo: success ? this.noteInfo : null
};
this.$ionic.modalController.dismiss(response);
}
},
data() {
return {
noteInfo: {
title: "",
description: ""
}
};
}
};
Using Vue Event Emitters
Here we are building off of the previous section where we demonstrated how to use a modal form to present information in a vuejs application using Ionic Framework Components.
More information on Custom Events: https://vuejs.org/v2/guide/components-custom-events.html
In this example, we will show how to use standard vue $emit
to get a similar result. This is also an approach for managing events from the Modal component other than actually closing the modal.
Setting Up App
Component
The the App
component lifecycle event created
we add the following code. This will listen for the modal-closed
event from the SimpleModal
vue component.
/**
* vue component lifecycle method where we setup listener
* for when the modal is closed
*/
created() {
this.$on("modal-closed", this.modalCloseHandler);
}
Next we need to make a change to how we call the component to appropriately handle the event.
First we add the property parent
to the component so we can send the event back to this component, the parent; we assign it the vale this
Also notice there is no more listening for onDismiss
and process the response; all of that is now handled with the event listener modal-closed
/**
* when the user clicks button, we open the modal
*/
async openModal() {
let modal = await this.$ionic.modalController.create({
component: SimpleModal,
componentProps: {
parent: this,
propsData: {
timeStamp: new Date()
}
}
});
// show the modal
await modal.present();
}
We now handle the dismiss
with the call inside of the modalCloseHandler
modalCloseHandler(_value) {
console.log("modal-closed", _value);
if (_value.success) {
// only on success
alert(JSON.stringify(_value.noteInfo, null, 2));
}
},
Changes To SimpleModal
Component
The only change needed here is to modify the modalClose
method to emit the event instead of calling this.$ionic.modalController.dismiss
modalClose: function(success) {
let response = {
success,
noteInfo: success ? this.noteInfo : null
};
this.$parent.$emit("modal-closed", response);
}
Either approach can work, but I wanted to investigate an approach to process events from the Modal
without having to actually close the modal and this approach can solve that problem.
Benefits of Emitting Events
We dont always want to just close the modal...Useless example, tracking when a form field changes?
<ion-item>
<ion-input-vue
type="text"
name="title"
placeholder="Title for note..."
v-model="noteInfo.title"
@ionChange="titleChanged"
></ion-input-vue>
</ion-item>
add the code for the function titleChanged
to the methods
section of the SimpleModal
component
titleChanged: function(_value) {
this.$parent.$emit("modal-title-changed", _value.detail);
},
Then in the parent component App
add an additional listener to the onCreated
lifecycle event handler.
created() {
this.$on("modal-closed", this.modalCloseHandler);
this.$on("modal-title-changed", function(d) {
console.log(d);
});
}
Project Source Code
Here is the gist with the source code from the project Part One