White Screen for Launch External App in Ionic 4 - ionic-framework

I have a page that would like to launch external app when a button is clicked and the function goToApp() should run.
Following is my code for on the ts file but everything on the page could be loaded until the point I added
import { AppLauncher, AppLauncherOptions } from '#ionic-native/app-launcher/ngx';
Which right after it the page doesn't load anymore. There is no error code returned. Any idea? Thanks in advance.
import { Component,OnInit,Input } from '#angular/core';
import { AppLauncher, AppLauncherOptions } from '#ionic-native/app-launcher/ngx';
import { ModalController, Platform } from '#ionic/angular';
import { DomSanitizer,SafeResourceUrl } from '#angular/platform-browser';
/*
Generated class for the Posts page.
See http://ionicframework.com/docs/v2/components/#navigation for more info on
Ionic pages and navigation.
*/
#Component({
selector: 'page-fsfastcheck',
templateUrl: 'fsfastcheck.html',
styleUrls: ['fsfastcheck.scss'],
})
export class FSFastCheckPage implements OnInit {
#Input()
url: string = "https://eastchenconsultancy.com/feng-shui-fast-check/";
url2: string = "https://eastchenconsultancy.com/appointment-list/";
urlSafe: SafeResourceUrl;
urlSafe2: SafeResourceUrl;
mySegment: string = 'travelrequest';
constructor(
public modalView: ModalController,
public sanitizer: DomSanitizer,
private appLauncher: AppLauncher, private platform: Platform) { }
ngOnInit() {
this.urlSafe= this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
this.urlSafe2= this.sanitizer.bypassSecurityTrustResourceUrl(this.url2);
}
close() {
this.modalView.dismiss();
}
goToApp() {
const options: AppLauncherOptions = { }
if(this.platform.is('ios')) {
options.packageName = 'com.apple.compass'
} else {
options.packageName = 'com.gn.android.compass'
}
this.appLauncher.canLaunch(options)
.then((canLaunch: boolean) => console.log('Compass is available'))
.catch((error: any) => console.error('Compass is not available'));
}
}

Have you followed the standard part which you need to do when adding new modules to your app:
https://ionicframework.com/docs/native/overview#angular
Basically, you need to inject the module into the app:
// app.module.ts
import { AppLauncher } from '#ionic-native/app-launcher/ngx';
...
#NgModule({
...
providers: [
...
AppLauncher
...
]
...
})
export class AppModule { }

Related

Data from get to Global Variable

first of all iwant to apologize for my poor englis, im trying to resolve this by my own for few days and i couldn't, i really need to solve this for a school project.
I have a variable named "myAccountData", im trying to put GET HTTP request result on it but its not working here's my code:
Page.ts:
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { NativeStorage } from '#ionic-native/native-storage';
import { EditaccountPage } from '../editaccount/editaccount';
import { AuthServiceProvider } from '../../providers/auth-service/auth-service';
import { Observable } from 'rxjs/Observable';
/**
* Generated class for the MyaccountPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
#IonicPage()
#Component({
selector: 'page-myaccount',
templateUrl: 'myaccount.html',
})
export class MyaccountPage {
public myAccountData;
constructor(public navCtrl: NavController, public navParams: NavParams, private nativeStorage: NativeStorage, public authServiceProvider: AuthServiceProvider) {
}
setmyAccountData(data){
this.myAccountData=this.authServiceProvider.getData("userbyid/40").subscribe( myData => {
this.myAccountData=myData;
});
}
gotoEdit(){
this.navCtrl.push(EditaccountPage);
}
}
authServiceProvider.ts:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import 'rxjs/add/operator/toPromise';
import { Observable } from 'rxjs/Observable';
let apiUrl = "http://192.168.1.2/api/v1/"
/*
Generated class for the AuthServiceProvider provider.
See https://angular.io/guide/dependency-injection for more info on providers
and Angular DI.
*/
#Injectable()
export class AuthServiceProvider {
constructor(public http: HttpClient) {
console.log('Hello AuthServiceProvider Provider');
}
public async postData(credentials, type): Promise<any> {
await this.http.post(apiUrl + type, JSON.stringify(credentials)).toPromise();
}
public getData(type): Observable<any> {
return this.http.get(apiUrl + type);
}
}
When i run "http://192.168.1.2/api/v1/userbyid/40" on postman this is what i get: {"id":"40","firstname":"Kebbab","lastname":"Walid","email":"walid#kebbab.fr","username":"walid","password":"a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3","sexe":"","birth":"2018-04-11","telephone":"0","type":"ouvrier","emailverified":"0"}
But on page.html if i use {{myAccountData.firstname}} it doesnt show anything
Error Log:
ERROR Error: Uncaught (in promise): TypeError: _co.myAccountData is undefined
View_MyaccountPage_0/<#ng:///AppModule/MyaccountPage.ngfactory.js:128:13
updateRenderer#http://localhost:8100/build/vendor.js:14342:20
checkAndUpdateView#http://localhost:8100/build/vendor.js:13866:5
callViewAction#http://localhost:8100/build/vendor.js:14211:21
execComponentViewsAction#http://localhost:8100/build/vendor.js:14143:13
checkAndUpdateView#http://localhost:8100/build/vendor.js:13867:5
ViewRef_.prototype.detectChanges#http://localhost:8100/build/vendor.js:11653:9
NavControllerBase.prototype._viewAttachToDOM#http://localhost:8100/build/vendor.js:51117:9
Tab.prototype._viewAttachToDOM#http://localhost:8100/build/vendor.js:77128:9
NavControllerBase.prototype._transition#http://localhost:8100/build/vendor.js:51197:13
NavControllerBase.prototype._nextTrns/<#http://localhost:8100/build/vendor.js:50918:40
F</l</t.prototype.invoke#http://localhost:8100/build/polyfills.js:3:14974
onInvoke#http://localhost:8100/build/vendor.js:4982:24
F</l</t.prototype.invoke#http://localhost:8100/build/polyfills.js:3:14901
F</c</r.prototype.run#http://localhost:8100/build/polyfills.js:3:10124
f/<#http://localhost:8100/build/polyfills.js:3:20240
F</l</t.prototype.invokeTask#http://localhost:8100/build/polyfills.js:3:15649
onInvokeTask#http://localhost:8100/build/vendor.js:4973:24
F</l</t.prototype.invokeTask#http://localhost:8100/build/polyfills.js:3:15562
F</c</r.prototype.runTask#http://localhost:8100/build/polyfills.js:3:10815
o#http://localhost:8100/build/polyfills.js:3:7887
F</h</e.invokeTask#http://localhost:8100/build/polyfills.js:3:16823
p#http://localhost:8100/build/polyfills.js:2:27646
v#http://localhost:8100/build/polyfills.js:2:27893
Stack trace:
c#http://localhost:8100/build/polyfills.js:3:19752
c#http://localhost:8100/build/polyfills.js:3:19461
f/<#http://localhost:8100/build/polyfills.js:3:20233
F</l</t.prototype.invokeTask#http://localhost:8100/build/polyfills.js:3:15649
onInvokeTask#http://localhost:8100/build/vendor.js:4973:24
F</l</t.prototype.invokeTask#http://localhost:8100/build/polyfills.js:3:15562
F</c</r.prototype.runTask#http://localhost:8100/build/polyfills.js:3:10815
o#http://localhost:8100/build/polyfills.js:3:7887
F</h</e.invokeTask#http://localhost:8100/build/polyfills.js:3:16823
p#http://localhost:8100/build/polyfills.js:2:27646
v#http://localhost:8100/build/polyfills.js:2:27893
core.js:1350
In my page.html i usef { { myAccountData?.firstname } } instead of { { myAccountData.firstname } } and it worked

Ionic 3 lazy loading : view displayed before enf of global configuration loading

I'm trying to implement lazy loading in my Ionic 3 application. In my app, I have a configuration provider which get / set configuration from local storage.
This is the code of the provider :
import { Injectable } from '#angular/core';
import { Storage } from '#ionic/storage';
import 'rxjs/add/operator/map';
#Injectable()
export class ConfigProvider {
public name: string = null;
constructor(private storage: Storage) {}
initialize() {
return new Promise((resolve, reject) => {
Promise.all([
this.storage.get('name').then(value => this.name = value),
]).then(value => {
resolve();
});
});
}
setName(name: string): void
{
this.name = name;
this.storage.set('name', this.name);
}
}
I call the initialize method in the constructor of the MyApp Component :
constructor(
public platform: Platform,
public menu: MenuController,
public statusBar: StatusBar,
public splashScreen: SplashScreen,
private modalCtrl: ModalController,
private configProvider: configProvider
) {
configProvider.initialize().then(() => {
this.initializeApp();
});
}
But, if I call my Page Component directly from the url, the name property of my provider is null...
#IonicPage({
name: ‘test’,
segment: ’test’
})
#Component({
selector: 'page-test’,
templateUrl: 'test'
})
export class TestPage {
constructor(
private configProvider: configProvider) {
}
ngAfterViewInit() {
// this.configProvider.name is null !!!!
}
Could someone tell me why ?
Thnax for your help :)

how to get realtime JSON from endpoint in Ionic App

Followed the content of the url to implement dynamic menu items using JSON file stored under /assets/data. The menu is working fine with stored JSON file. Now I need to dynamically retrieve the JSON of same format in real time from a Salesforce API and display its content.
Can someone please suggest what changes I need to make here? should the json path in getMainMenu() method be replaced with the actual Saleforce API?
Below is the data-service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/add/operator/map';
/*
Generated class for the DataServiceProvider provider.
See https://angular.io/guide/dependency-injection for more info on providers
and Angular DI.
*/
#Injectable()
export class DataServiceProvider {
constructor(public http: Http) {
console.log('Hello DataServiceProvider Provider');
}
getMainMenu(){
return this.http.get('assets/data/mainmenu.json')
.map((response:Response)=>response.json().Categories);
}
}
and app.component.ts
import { Component, ViewChild } from '#angular/core';
import { Nav, Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { HomePage } from '../pages/home/home';
import { ListPage } from '../pages/list/list';
import { DataServiceProvider } from '../providers/data-service/data-service'
#Component({
templateUrl: 'app.html'
})
export class MyApp {
#ViewChild(Nav) nav: Nav;
rootPage: any = HomePage;
pages: any[]; //Array<{title: string, component: any}>;
mainmenu: any[];
constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen, public dataService: DataServiceProvider) {
this.initializeApp();
this.dataService.getMainMenu().subscribe((Response)=>{
this.mainmenu = Response;
console.log(this.mainmenu);
});
// used for an example of ngFor and navigation
this.pages = [
{ title: 'Home', component: HomePage },
{ title: 'List', component: ListPage }
];
}
initializeApp() {
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.
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
openPage(page) {
// Reset the content nav to have just this page
// we wouldn't want the back button to show in this scenario
this.nav.setRoot(page.component);
}
toggleSection(i) {
this.mainmenu[i].open = !this.mainmenu[i].open;
};
toggleItem(i,j) {
this.mainmenu[i].SubCategories[j].open = !this.mainmenu[i].SubCategories[j].open;
};
}
It looks like you will need to update the url in the getMainMenu method to that of your api. There might be some other changes you will need to make, such as adding authentication headers, but if the data coming from the api is the same as whats stored in the assets folder, your component shouldn't care "where" the data comes from.

Splash screen make http request and pass the response to another page

What I am trying to do is when the splash screen is loading, a http request is made to the server to pull some information and pass the response to another page.
Below is the code I am working with.
import { Component } from '#angular/core';
import { Platform, LoadingController } from 'ionic-angular';
import { StatusBar, Splashscreen } from 'ionic-native';
import { CacheService } from "ionic-cache/ionic-cache";
import { Apis } from './apis';
import { StayPage} from '../pages/stay/stay';
#Component({
templateUrl: 'app.html',
providers: [Apis]
})
export class MyApp {
rootPage = StayPage;
constructor(platform: Platform, cache: CacheService, public loadingCtrl: LoadingController, public Apis: Apis ) {
cache.setDefaultTTL(60 * 60);
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.
this.Apis.types().subscribe( response => {
response.results;
StatusBar.styleDefault();
Splashscreen.hide();
}, err => {
this.Apis.error( err );
});
});
}
}
When I run the above code, the splash screen is stuck on loading and doesn't move to another page.
You need to make HTTP request in constructor or ngOnInit of StayPage.
export class StayPage implements OnInit {
...
constructor(public navCtrl: NavController,
public navParams: NavParams
public http: Http) { }
ngOnInit(){
this.http.get(apiUrl)
.subscribe(
responseSuccess => ...
responseError => ...
}
}
}

Fire Nativescript tabitem event when tabitem gets selected

I am using a Nativescript (Angular 2) TabView with two TabItems. The XML is divided intro three files. One that holds the TabView and two others for each TabItem. Therefore I also have three TypeScript components.
At the moment I am loading data in the second TabItem's onInit method. The problem is that this action already happens when the first TabItem of the TabView is being displayed/loaded.
What is the best practice to load this data only when the second TabItem is selected?
This is my (shortened) code:
home.page.html:
<ActionBar title="Home"></ActionBar>
<TabView #tabview (selectedIndexChanged)="tabIndexChanged($event)" toggleNavButton>
<StackLayout *tabItem="{title: 'Tab 1'}">
<tab1></tab1>
</StackLayout>
<StackLayout *tabItem="{title: 'Tab 2'}">
<tab2></tab2>
</StackLayout>
</TabView>
home.page.ts:
import {Component} from "#angular/core";
#Component({
selector: "home-page",
templateUrl: "./pages/home/home.page.html",
providers: []
})
export class HomePage {
public activeTab: string;
public constructor() {
}
public tabIndexChanged(e: any) {
switch (e.newIndex) {
case 0:
console.log(`Selected tab index: ${e.newIndex}`);
break;
case 1:
console.log(`Selected tab index: ${e.newIndex}`);
break;
default:
break;
}
}
}
tab1.tab.html:
<StackLayout orientation="vertical" class="p-20">
<Label text="Tab 1"></Label>
</StackLayout>
tab1.tab.ts:
import { Component, OnInit } from "#angular/core";
#Component({
selector: "tab1",
templateUrl: "./pages/partials/tab1.tab.html",
providers: []
})
export class Tab1 implements OnInit {
public constructor() {}
public ngOnInit() {
console.log("init Tab 1");
}
}
tab2.tab.html:
<StackLayout orientation="vertical" class="p-20">
<Label text="Tab 2"></Label>
</StackLayout>
tab2.tab.ts:
import { Component, OnInit } from "#angular/core";
#Component({
selector: "tab2",
templateUrl: "./pages/partials/tab2.tab.html",
providers: []
})
export class Tab2 implements OnInit {
public constructor() {}
public ngOnInit() {
console.log("init Tab 2");
this.getSomeDataViaHttp();
}
private getSomeDataViaHttp() {
//getting data from an API
}
}
Is there an Angular 2 / Nativescript event other than onInit that would help here?
Or should I use the method tabIndexChanged in the home.page.ts for that?
Or put all the logic and the XML for the TabView back into one xml file and one ts file?
What is best practice?
You could use a service and a Subject as followed.
Import the service file in all ts files (use the name and location you like):
import { NavService } from "./services/nav.service";
Make sure to import it also in your app.module.ts to generally load it:
import { NavService } from "./services/nav.service";
#NgModule({
declarations: [
AppComponent,
],
bootstrap: [AppComponent],
imports: [
],
providers: [
NavService
]
})
export class AppModule {}
Create the service file in the specified location with the following content:
import { Injectable } from "#angular/core";
import { Subject } from "rxjs";
#Injectable()
export class NavService {
private currentState = new Subject<any>();
constructor () {
}
setCurrentState(navPoint: number){
this.currentState.next(navPoint);
}
getCurrentState() {
return this.currentState.asObservable();
}
}
Change the tab2.tab.ts to the following:
import { Component, OnInit } from "#angular/core";
import { NavService } from "./services/nav.service";
#Component({
selector: "tab2",
templateUrl: "./pages/partials/tab2.tab.html",
providers: []
})
export class Tab2 implements OnInit {
public constructor(private _navService: NavService) {}
public ngOnInit() {
console.log("init Tab 2");
this._navService.getCurrentState().subscribe(
(state) => {
if (state == {{something}}) {
//write your code here which should be executed when state has the property {{something}}
this.getSomeDataViaHttp();
}
}
);
}
private getSomeDataViaHttp() {
//getting data from an API
}
}
Call the setCurrentState of the service in your home.page.ts:
import {Component} from "#angular/core";
import { NavService } from "./services/nav.service";
#Component({
selector: "home-page",
templateUrl: "./pages/home/home.page.html",
providers: []
})
export class HomePage {
public activeTab: string;
public constructor(private _navService: NavService) {
}
public tabIndexChanged(e: any) {
this._navService.setCurrentState(e.newIndex);
}
}
Take care that the "typeof" setting and getting the state is correct.