PopoverController Ionic 4? - ionic-framework

How does the PopoverController work in Ionic 4?
The current documentation is incorrect and there's no breaking changes for it?
const popover = this.popoverCtrl.create({
component: 'PopupMenuComponent',
ev: event
});
popover.present();
I've created a Component and when I try to present it, I receive the below error...
[ts] Property 'present' does not exist on type 'Promise<HTMLIonPopoverElement>'. Did you forget to use 'await'?
Thanks.

In your example, you didnt await it. As of Alpha-7 the create method returns a promise. You can find the latest documentation here. Take alook at this example:
import { Component } from '#angular/core';
import { PopoverController } from '#ionic/angular';
#Component({
template: `
<ion-list no-margin>
<ion-item (click)="onDismiss()">Dismiss</ion-item>
</ion-list>
`
})
export class PopupMenuComponentPopover {
constructor(private popoverCtrl: PopoverController) {
}
async onDismiss() {
try {
await this.popoverCtrl.dismiss();
} catch (e) {
//click more than one time popover throws error, so ignore...
}
}
}
And here is how to open it:
async openPopover(args) {
const popover = await this.popoverController.create({
component: PopupMenuComponentPopover,
ev: args,
translucent: false
});
return await popover.present();
}
Edit: here is you can call it:
#NgModule({
...
declarations: [DashboardWebsiteMorePopover],
entryComponents: [DashboardWebsiteMorePopover],
...
})
export class PopupMenuComponentModule {}

Related

ionic 4 pass data back from modal which is opened inside another modal to base page

I have a page called home.component.ts. On this page, a modal called address-modal(first modal) is opened to let users select an address and the selected address is passed back to the home page. Meanwhile, On address-modal(first modal), If the user wants to add another address there is another modal called add-address-modal(second modal) is opened on button click.
Now when a user adds another address (the second modal is opened on the first modal) I want to dismiss both modals send a newly added address to home.apge without really sending it to address-modal.
Currently
I am getting data back from address-modal(first modal) to home page
I am getting data from add-address-modal(second modal) to address-modal(first modal)
But I want to get data directly from 2nd modal to base page
here is my code
home.module.ts // base page
import { AddressPage } from '../pages/address/address.page';
import { AddAddressPage } from '../pages/add-address/add-address.page'
#NgModule({
imports: [
// all imports
],
declarations: [HomePage, AddressPage, AddAddressPage],
entryComponents :[AddressPage , AddAddressPage]
})
export class HomePageModule {}
home.page.ts
import { ModalController } from '#ionic/angular';
import { AddressPage } from '../pages/address/address.page';
constructor(public modalController: ModalController) {}
async address_modal(){
// console.log("clicked")
const modal = await this.modalController.create({
component: AddressPage,
});
modal.onDidDismiss()
.then((data) => {
const user = data['data']; // Here's your selected user!
console.log("from address " + user)
});
return await modal.present();
}
}
home.html
<ion-button (click) = "address_modal()">address</ion-button> // to open first modal
address.page.ts // first modal
import { ModalController } from '#ionic/angular';
import { AddAddressPage } from '../add-address/add-address.page'
x:any;
constructor(private modalController: ModalController) {
this.x =2;
}
close(){
this.modalController.dismiss(this.x)
}
async add_address(){
// console.log("clicked")
const modal = await this.modalController.create({
component: AddAddressPage,
});
modal.onDidDismiss()
.then((data) => {
const user = data['data']; // Here's your selected user!
console.log( "from add-adreess" + user)
});
return await modal.present();
}
address.html
<ion-button (click)="close()">close</ion-button> // close modal
<ion-button (click)="add_address()">open</ion-button> // open second modal
add-address.page.ts
import { ModalController } from '#ionic/angular';
x:any;
constructor(private modalController: ModalController) {
this.x =5;
}
close(){
this.modalController.dismiss(this.x)
}
add-address.html
<ion-button (click) ="close()">close</ion-button >

Menu items not appearing programmatically ionic 3 when user signs in. (AWS Cognito)

I am building an ionic app using AWS as a backend (has been challenging!), and for some reason on my user sign-in page, I got this nasty bug that wasn't there when I was using firebase as the backend. In a nutshell, my side menu has items that should appear based on whether the user is logged in or not. If the user is logged in, the menu should have a logout item. If the user is not logged in, the menu should either not have any options, or a redundant sign-in option.
I got the hard part down, which was setting up AWS Cognito to work the sign-in logic, and setting the correct root page, however, after a user logs in, the menu does not show the logout option.
Funny thing, if I reload the app, the menu does show the logout option. Not sure why. Also weird, after I reload the app and I click the logout button, the correct options for a user that is not logged in do appear in the menu. If someone can take a look and tell me why the menu options only render correctly when I log out and if I log in only after I reload the app, I would be very grateful! Thank you in advance for your time! Code below...
app.component.ts:
import { Component } from '#angular/core';
import { Platform, NavController, MenuController } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { TabsPage } from '../pages/tabs/tabs';
import { SignInPage } from '../pages/sign-in/sign-in';
import { AuthService } from '../services/auth';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage: any;
isLoggedIn //this variable holds the status of the user and determines the menu items;
constructor(platform: Platform,
statusBar: StatusBar,
splashScreen: SplashScreen,
private menuCtrl: MenuController,
private authService: AuthService) {
this.verifyUserstate(); //method to check if a user is logged in
console.log(this.isLoggedIn); //debug line
console.log(this.menuCtrl.get()); //debug line
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
}
onLoad(page: any) {
console.log("onLoad");
this.nav.setRoot(page);
this.menuCtrl.close();
}
onLogout() {
this.authService.logout();
this.verifyUserstate();
this.menuCtrl.close();
}
verifyUserstate() {
console.log("in verify userstate");
this.authService.isAuthenticated()
.then(() => {
this.isLoggedIn = true; //if a user is logged in = true
this.rootPage = TabsPage;
console.log(this.isLoggedIn); // more debug
})
.catch((error) => {
this.isLoggedIn = false; //if user is not logged in = false
this.rootPage = SignInPage;
console.log(this.isLoggedIn); //more debug
});
}
}
app.html:
<ion-menu [content]="nav">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<button ion-item icon-left (click)="onLoad(signinPage)" *ngIf="!isLoggedIn"> <!-- check isLoggin-->
<ion-icon name="log-in"></ion-icon>
Sign In
</button>
<button ion-item icon-left (click)="onLogout()" *ngIf="isLoggedIn">
<ion-icon name="log-out"></ion-icon>
Log Out
</button>
</ion-list>
</ion-content>
auth.ts:
import { Injectable } from "#angular/core";
import { AlertController } from "ionic-angular";
import { CognitoUserPool, AuthenticationDetails, CognitoUser, CognitoUserSession } from "amazon-cognito-identity-js";
const POOL_DATA = {
UserPoolId: "xx-xxxx-X_XXXX",
ClientId: "You do not need to know :)"
}
const userPool = new CognitoUserPool(POOL_DATA);
export class AuthService {
signin(email: string, password: string) {
let message: string;
var authenticationData = {
Username : email,
Password : password,
};
var authDetails = new AuthenticationDetails(authenticationData);
let userData = {
Username: email,
Pool: userPool
}
let cognitoUser = new CognitoUser(userData);
return new Promise((resolve, reject) => {
cognitoUser.authenticateUser(authDetails, {
onSuccess(result: CognitoUserSession) {
console.log(result)
resolve("Success!")
},
onFailure(error) {
let message: string = error.message;
reject(message);
}
}
logout() {
this.getAuthenticatedUser().signOut();
}
isAuthenticated() {
return new Promise((resolve, reject) => {
let user = this.getAuthenticatedUser();
if (user) {
user.getSession((err, session) => {
if(session.isValid()) {
resolve(true);
} else if (err) {
reject(err.message);
}
})
} else {
reject("Not authenticated");
}
});
}
}
Finally, the sign-in.ts file (where the magic of login in happens):
import { Component } from '#angular/core';
import { NgForm } from '#angular/forms';
import { LoadingController, AlertController } from 'ionic-angular';
import { AuthService } from '../../services/auth';
import { NavController } from 'ionic-angular/navigation/nav-controller';
import { MyApp } from '../../app/app.component';
#Component({
selector: 'page-sign-in',
templateUrl: 'sign-in.html',
})
export class SignInPage {
constructor(private authService: AuthService,
private loadingCtrl: LoadingController,
private alertCtrl: AlertController,
private navCtrl: NavController) {
}
onSignin(form: NgForm) {
const loading = this.loadingCtrl.create({
content: "Signing you in..."
});
loading.present();
this.authService.signin(form.value.email, form.value.password)
.then(data => {
this.navCtrl.setRoot(MyApp); /*navigate to myApp again to reverify the
*login status. This sets the right rootPage,
*but I have a feeling here also lies the menu problem.
*/
console.log(data);
})
.catch(error => {
console.log(error);
let alert = this.alertCtrl.create({
title: "Oops",
message: error,
buttons: ["Ok"]
});
alert.present();
})
loading.dismiss();
}
}

How to create loader once and use it all over the app? - Ionic 3

Everywhere in the blogs & article loader is created in the components. I need to create a loader once and use it all over the app. But the problem is, in ionic 3, we can't dismiss loader manually. It should be dismissed after it has presented such as below correct code:
ionViewLoaded() {
let loader = this.loading.create({
content: 'Getting latest entries...',
});
loader.present().then(() => {
this.someService.getLatestEntries()
.subscribe(res => {
this.latestEntries = res;
});
loader.dismiss();
});
}
I tried creating loader once using service and use it whenever I wanted all over app. such as follows:
import {Injectable} from '#angular/core';
import { LoadingController } from 'ionic-angular';
#Injectable()
export class BasicService{
loader: any;
constructor(public loadingCtrl: LoadingController){
//creates loader once so there is less data redundancy
this.loader = this.loadingCtrl.create({
content: `loading...`,
});
}
showLoader() { //call this fn to show loader
this.loader.present();
}
hideLoader() { //call this fn to hide loader
this.loader.dismiss();
}
}
But it doesn't work, gives an error such as.
Runtime Error Uncaught (in promise): removeView was not found
So is there any way where can achieve this feat in ionic 3, which can help me with data redundancy?
constructor(public loadingCtrl: LoadingController){
//creates loader once so there is less data redundancy
}
showLoader() { //call this fn to show loader
this.loader = this.loadingCtrl.create({
content: `loading...`,
});
this.loader.present();
}
Remove creating LoadingController instance from the controller and add it in the showLoader() function in your service.
You got that error because you call this.loader.dismiss(); when your loader is not presenting. So, the right way is:
showLoader(content?: string) {
if (this.loader) {
this.loader.dismiss();
}
this.loader = this.loadingCtrl.create({
content: content ? content : "Loading..."
})
this.loader.present();
this.loader.onDidDismiss(()=>{
this.loader = null;
})
}
hideLoader() {
if(this.loader)
this.loader.dismiss();
}

Bluetooth Serial Ionic 2

I am trying to build a simple bluetooth serial app to connect to my arduino. I am using ionic2 to make android app.right now, all I am trying to do is list all the availabe bluetooth devices. Below is my code :
import { Component } from '#angular/core';
import { BluetoothSerial } from 'ionic-native';
import { NavController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public working:string;
public var2: string ;
bluetoothSerial.isEnabled(
function() {
this.working= "Bluetooth is enabled";
},
function() {
this.working="Bluetooth is *not* enabled";
}
);
public lists = [];
bluetoothSerial.discoverUnpaired(function(devices) {
this.lists.push(devices);
}, function(){ this.var2 = 'could not find any bluetooth device';});
constructor() { }
}
Whenever I do ionic serve I do plenty of error, mainly because Bluetooth is not recognized (function implementation is missing). It also does not allow me to build app either.
Please help on this.
Thank you so much
Looking at the docs
isEnabled()
Platforms: Android iOS Windows Phone
Reports if bluetooth is enabled
Returns: Promise returns a promise
Couple of things. You cannot call your method like that.
You should capitalize your BluetoothSerial
You should put it in a function
import { Component } from '#angular/core';
import { BluetoothSerial } from 'ionic-native';
import { NavController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public working:string;
public var2: string ;
public lists = [];
constructor(){
this.getAlBluetoothDevices();
}
// put BluetoothSerial inside a function, can't be called different
getAllBluetoothDevices(){
// async so keep everything in this method
BluetoothSerial.isEnabled().then((data)=> {
// not sure of returning value, probably a boolean
console.log("dont know what it returns"+data);
// returns all the available devices, not just the unpaired ones
BluetoothSerial.list().then((allDevices) => {
// set the list to returned value
this.lists = allDevices;
if(!this.lists.length > 0){
this.var2 = "could not find any bluetooth devices";
}
});
});
}
}
}
The below code is for scanning the Bluetooth device
startScanning(){
this.isScanning =true;
this.bluetoothSerial.isEnabled().then(()=>{
this.bluetoothSerial.discoverUnpaired().then((allDevices)=>{
this.devices=allDevices;
this.isScanning =false;
});
});
And this code is for connecting to the device
onDeviceReady(){
let device = this.navParams.get('device');
this.bluetoothSerial.connect(device.id).subscribe((data)=>{
let alert = this.alertCtrl.create({
title: 'Bluetooth',
subTitle: data,
buttons: ['ok']
});
alert.present();
},error=>{
let alert = this.alertCtrl.create({
title: 'Bluetooth',
subTitle: error,
buttons: ['ok']
});
alert.present();
});
}
Note: It's working for me

ionic 2: how to dismiss loader after data is ready?

In my Ionic 2 app, I have i have component that GET to fetch data.
i want to maker loader and dismiss it after data is ready.
i tried to look on other posts around the stack overflow but my issue is different.
i did something but the loader is forever and its not helps me.
It looks like following:
import { Component,ViewChild } from '#angular/core';
import { NavController,LoadingController,AlertController,ViewController} from 'ionic-angular';
import { Facebook } from 'ionic-native';
//import pages
import {LoginPage} from "../../pages/login/login";
import {User} from '../../models/user'
import { Storage} from '#ionic/storage';
//import provider
import { ProfileData } from '../../providers/profile-data';
import { NotesData } from '../../providers/notes-data';
import firebase from 'firebase'
import {AddNote} from "../add-note/add-note";
/*
Generated class for the NotesList page.
See http://ionicframework.com/docs/v2/components/#navigation for more info on
Ionic pages and navigation.
*/
#Component({
selector: 'page-notes-list',
templateUrl: 'notes-list.html'
})
export class NotesList {
//facebook user
userProfile: any = null;
uid: any = null;
fireUid:any=null;
name:string=null;
photo: any =null;
user:User=null;
photos:any=null;
currentUser:any=null;
photonew:any=null;
//notes list
notes:any=null;
data:any;
pages: Array<{title: string, component: any}>;
constructor(public navCtrl: NavController,public profileData:ProfileData,private viewCtrl: ViewController,public notesData:NotesData,private loadingCtrl: LoadingController,private alertCtrl: AlertController,public storage:Storage) {
this.data={};
this.data.title="";
this.data.desc="";
}
ionViewDidLoad() {
//if i do that the loader is forever
/*
let loader = this.loadingCtrl.create({
dismissOnPageChange: true,
});
loader.present();
*/
// here i want the loader to be until the data is ready.
this.getNotesList(); //this functions not returns data so i can't do this.getNotesList().then(()=>
}
getNotesList(){
console.log("get event");
var that=this;
this.notesData.getNotesLIst().on('value', snapshot => {
let notesList= [];
snapshot.forEach( snap => {
console.log("id note"+snap.val().id);
notesList.push({
id: snap.val().id,
title: snap.val().title,
desc: snap.val().desc,
color:snap.val().color,
photo:snap.val().photo,
});
});
that.notes = notesList;
});
}
addNote(){
this.navCtrl.push(AddNote);
}
logOutFacebook(){
Facebook.logout().then((response)=>
{
this.navCtrl.push(LoginPage);
alert(JSON.stringify(response));
},(error)=>{
alert(error);
})
}
}
At first, you should show how do you implement your loading page. Is it a splash screen with cordorva? Or just as div displaying some image?
If it is a splash screen, you can add this code in your component after you get data, (it is from starter template, you can see the detail by creating a new project with ionic start):
this.platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
StatusBar.styleDefault();
Splashscreen.hide();
});
And, if you use a div in your index page, it is similar, you can just get that element and remove it, with pure js.
okay it succeed to do that
this is my answer
ionViewDidLoad() {
let loader = this.loadingCtrl.create({});
loader.present();
this.getNotesList().then((x) => {
if (x) loader.dismiss();
});
}
getNotesList(){
return new Promise(resolve => {
var that=this;
this.notesData.getNotesLIst().on('value', snapshot => {
let notesList= [];
snapshot.forEach( snap => {
console.log("id note"+snap.val().id);
notesList.push({
id: snap.val().id,
title: snap.val().title,
desc: snap.val().desc,
color:snap.val().color,
photo:snap.val().photo,
});
});
that.notes = notesList;
resolve(true);
});
})
}