Ionic SqlStorage is not defined - ionic-framework

I'm trying to use SqlStorage in an ionic app. I'm getting the error in the title. I'm guessing I need to include SqlStorage but I'm not sure where. My code looks a lot like what's in the docs http://ionicframework.com/docs/v2/api/platform/storage/SqlStorage/ . How do you include SqlStorage?
var prefrences = {
foo: bar
}
let storage = new Storage(SqlStorage);
storage.set('storedPreferences', preferences);

Add SqlStorage to your list of 'include' packages via import statement. i.e
import {SqlStorage} from 'ionic-angular';
For example
import {SqlStorage,...} from 'ionic-angular';
#Page({
templateUrl: 'path/to/template'
})
export class MyPage {
constructor(){
let storage = new Storage(SqlStorage);
...
}
...
}

Related

Capacitor v3 Motion api - using AccelListenerEvent properties

I am using Capacitor version 3 and I'm trying out the Motion Api.
In the documentation here, the AccelListenerEvent comes with some properties which I want to set but there are no examples of how to use this.
So the part I'm using is addListener(‘orientation’, …)
I basically want to set the interval.
I've added this:
import { Component } from '#angular/core';
import { PluginListenerHandle } from '#capacitor/core';
import { Motion, AccelListenerEvent } from '#capacitor/motion';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
accelHandler: PluginListenerHandle;
accelListenerEvent: AccelListenerEvent;
constructor() {
this.accelListenerEvent.interval = 10;
}
But it doesn't like it in the constructor.
Does anyone have any ideas on how to set these properties?
You can access the properties this way:
Motion.addListener('accel', event => {
console.log('Interval:', event.interval);
});
Since this is an event, you can only receive values, not set them.

How to hide header on scroll in ionic 4?

I wanted to know how I can hide a header in Ionic 4 by scrolling down the page, and re-show it when scrolling up.
I found many solutions on how to do that, but they all turned out to not working or being out-of-date.
So I collected all piece of information I could find to provide this answer.
Thanks to this video I got it to work.
First of all call ionic g directive directives/hide-header. You can of course replace directive/hide-header with your own path and name.
hide-header.directive.ts
import { Directive, HostListener, Input, OnInit, Renderer2 } from '#angular/core';
import { DomController } from '#ionic/angular';
#Directive({
selector: '[appHideHeader]'
})
export class HideHeaderDirective implements OnInit {
#Input('header') header: any;
private lastY = 0;
constructor(
private renderer: Renderer2,
private domCtrl: DomController
) { }
ngOnInit(): void {
this.header = this.header.el;
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'transition', 'margin-top 700ms');
});
}
#HostListener('ionScroll', ['$event']) onContentScroll($event: any) {
if ($event.detail.scrollTop > this.lastY) {
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'margin-top', `-${ this.header.clientHeight }px`);
});
} else {
this.domCtrl.write(() => {
this.renderer.setStyle(this.header, 'margin-top', '0');
});
}
this.lastY = $event.detail.scrollTop;
}
}
After that, in your template:
<ion-header #header>
<ion-toolbar><ion-title>Test</ion-title></ion-toolbar>
</ion-header>
<ion-content scrollEvents="true" appHideHeader [header]="header">
</ion-content>
Take care of the scrollEvents, appHideHeader and the [header] attributes! The last one takes the header element as argument, in this case #header.
Most of the code is the same as shown in the video. I changed the host-property from the #Directive and used the more up-to-date HostListener.
If you want to use the directive in more than one directive, you need to create a SharedModule.
To do so, create the module with ng g module shared. After that, add the HideHeaderDirective to the declarations and the exports array.
shared.module.ts
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { HideHeaderDirective } from './directives/hide-header.directive';
#NgModule({
declarations: [HideHeaderDirective],
exports: [HideHeaderDirective],
imports: [
CommonModule
]
})
export class SharedModule {}
Now add the shared module to all the modules you want to use the directive in.
Note: You cannot import the directive in app.module.ts and use it in a submodule! You have to import the shared module in every direct module you want to use the directive in.
My current versions of node, npm and ionic:
For this you can just place the ion-header before the ion-content. this is the simple answer for that.

Ionic2 - Alternate way to route without using injected component?

I am building a mobile app and I'd like the user to have the ability to set their starting page via a settings-page. The idea is that the user can select a page from a list of options, the setting gets stored to local-storage and later, when the user logs back in, the user is automatically taken to that page first.
I have a page-service which contains a mapping of Id's to page-components. This is what I use to find the page I want to use when I read in my user's saved start-page data.
My issue is that I have developed a cyclic-dependency that I don't think I can break without finding a way to route in Ionic2 that doesn't involve using the injected component. As far as I can tell, the only way routing is achieved in Ionic2 is with the NavController.push(component) or Nav.setRoot(component).
PageService.ts
import {Injectable} from "#angular/core";
import {HomePage} from "../pages/home/home";
import {SettingsPage} from "../pages/settings/settings";
import {CartPage} from "../pages/cart/cart";
#Injectable()
export class PageService {
public pages = [
{
id: "HOME",
component: HomePage
}, {
id: "SETTINGS",
component: SettingsPage
}, {
id: "CART",
component: CartPage
}
];
constructor() {
}
getPageById(id: string) {
return this.pages.find(page => (page.id === id));
}
}
settings.ts:
My SettingsPage component has the PageService injected so that it can get access to get the list of pages. This is where my cyclical dependency occurs. The SettingsPage is injecting PageService which has a reference to SettingsPage in it.
import {Component} from "#angular/core";
import {PageService} from "../../providers/page-service";
import {UserService} from "../../providers/user-service";
#Component({
selector: "page-settings",
templateUrl: "settings.html",
})
export class SettingsPage {
startPages = [];
constructor(private pageService: PageService, private userService: UserService) {
this.startPages = this.pageService.getStartPages();
}
}
settings.html:
Just a simple list with a card to output the selection.
<ion-content padding>
<ion-list>
<ion-card padding>
<ion-card-title>Starting Page</ion-card-title>
<ion-item>
<ion-select [(ngModel)]="userService.activeUser.startPage">
<ion-option *ngFor="let page of startPages" value="{{page.id}}">
{{page.id}}
</ion-option>
</ion-select>
</ion-item>
</ion-card>
</ion-list>
</ion-content>
...and finally, when the app starts up and I want to automatically go to my start page I execute the following:
const startPage = this.pageService.getPageById(this.userService.activeUser.startPage);
this.nav.setRoot(startPage.component);
Updated answer
Use forward ref in the SettingsPage constructor..
constructor(#Inject(forwardRef(() => PageService)) private pageService: PageService) {
this.startPages = this.pageService.getStartPages();
}
Old Answer - not appropriate because angular should be handling the instantiation of services through injection. "new"ing is a bad idea (but it did work).
I changed how the PageService was loaded in the SettingsPage and the cyclical dependency was resolved. I moved the PageService code out of the constructor and put it into the ngAfterViewInit() function. Now the PageService is only instantiated when the view is loaded.
ngAfterViewInit(){
this.pageService = new PageService();
this.startPages = this.pageService.getStartPages();
}

Show multiple pages for large screen sizes in Ionic 3

I'm building a simple app with a side menu and two ion-tab. What I am trying to do is, when the screen wide enough, forget about the tabs and open both pages side by side:
To keep the menu visible if the screen is large enough, I am using:
<ion-split-pane when="lg">
And to hide the Tabs:
TS file: this.showTabs = platform.width() < 992;
And then, in the HTML file, I just add the attribute: *ngIf="showTabs"
Is it possible to load two pages inside an ion-content? Any alternative solution?
Any help would be appreciated!
Ok, I've found a solution for this. I'll post it here in case someone experiences the same problem.
We can create a custom component with:
ionic generate component name-of-component
The components can be embedded within the ionic pages. To use them in a Page, you just have to import the component in the .module.ts of the Page and then use the HTML tag with the selector name of the component, as Ivaro18 mentioned:
<component-name></component-name>
If you want to use lazy loading, you can create a components.module.ts inside the components folder to act as an index of all the custom components. It would look like this:
import { NgModule } from '#angular/core';
import { IonicModule } from 'ionic-angular';
import { Component1 } from './component1/component1';
import { Component2 } from './component2/component2';
import { Component3 } from './component3/component3';
#NgModule({
declarations: [
Component1,
Component2,
Component3
],
imports: [IonicModule],
exports: [
Component1,
Component2,
Component3
]
})
export class ComponentsModule{}
Then, in the Pages, we would import ComponentsModule. That would allow us to lazy load any of the components:
<component-2-selector></component-2-selector>
Hope this helps!

How to redirect to an external URL in Angular2?

What is the method for redirecting the user to a completely external URL in Angular 2. For example, if I need to redirect the user to an OAuth2 server in order to authenticate, how would I do that?
Location.go(), Router.navigate(), and Router.navigateByUrl() are fine for sending the user to another section (route) within the Angular 2 app, but I can't see how they could be used to redirect to an external site?
You can use this-> window.location.href = '...';
This would change the page to whatever you want..
An Angular approach to the methods previously described is to import DOCUMENT from #angular/common (or #angular/platform-browser in Angular
< 4) and use
document.location.href = 'https://stackoverflow.com';
inside a function.
some-page.component.ts
import { DOCUMENT } from '#angular/common';
...
constructor(#Inject(DOCUMENT) private document: Document) { }
goToUrl(): void {
this.document.location.href = 'https://stackoverflow.com';
}
some-page.component.html
<button type="button" (click)="goToUrl()">Click me!</button>
Check out the platformBrowser repo for more info.
The solution, as Dennis Smolek said, is dead simple. Set window.location.href to the URL you want to switch to and it just works.
For example, if you had this method in your component's class file (controller):
goCNN() {
window.location.href='http://www.cnn.com/';
}
Then you could call it quite simply with the appropriate (click) call on a button (or whatever) in your template:
<button (click)="goCNN()">Go to CNN</button>
I think you need à target="_blank", so then you can use window.open :
gotoGoogle() : void {
window.open("https://www.google.com", "_blank");
}
If you've been using the OnDestry lifecycle hook, you might be interested in using something like this before calling window.location.href=...
this.router.ngOnDestroy();
window.location.href = 'http://www.cnn.com/';
that will trigger the OnDestry callback in your component that you might like.
Ohh, and also:
import { Router } from '#angular/router';
is where you find the router.
---EDIT---
Sadly, I might have been wrong in the example above. At least it's not working as exepected in my production code right now - so, until I have time to investigate further, I solve it like this (since my app really need the hook when possible)
this.router.navigate(["/"]).then(result=>{window.location.href = 'http://www.cnn.com/';});
Basically routing to any (dummy) route to force the hook, and then navigate as requested.
in newer versions of Angular with window as an any
(window as any).open(someUrl, "_blank");
There are 2 options:
if you want to redirect in same window/tab
gotoExternalDomain(){
window.location.href='http://google.com/'
}
if you want to redirect in new tab
gotoExternalDomain(){
(window as any).open("http://google.com/", "_blank");
}
After ripping my head off, the solution is just to add http:// to href.
Go somewhere
I used window.location.href='http://external-url';
For me the the redirects worked in Chrome, but didn't work in Firefox.
The following code resolved my problem:
window.location.assign('http://external-url');
I did it using Angular 2 Location since I didn't want to manipulate the global window object myself.
https://angular.io/docs/ts/latest/api/common/index/Location-class.html#!#prepareExternalUrl-anchor
It can be done like this:
import {Component} from '#angular/core';
import {Location} from '#angular/common';
#Component({selector: 'app-component'})
class AppCmp {
constructor(location: Location) {
location.go('/foo');
}
}
You can redirect with multiple ways:
like
window.location.href = 'redirect_url';
another way Angular document:
import document from angular and the document must be inject as well as bellow otherwise you will get error
import { DOCUMENT } from '#angular/common';
export class AppComponent {
constructor(
#Inject(DOCUMENT) private document: Document
) {}
this.document.location.href = 'redirect_url';
}
None of the above solutions worked for me, I just added
window.location.href = "www.google.com"
event.preventDefault();
This worked for me.
Or try using
window.location.replace("www.google.com");
To use #Inject, you must import it. I didn't see this in any of the answers.
TS file:
import { Component, Inject } from '#angular/core';
import { DOCUMENT } from '#angular/common';
#Component({
selector: 'app-my-comp.page',
templateUrl: './my-comp.page.component.html',
styleUrls: ['./my-comp.page.component.scss']
})
export class MyCompPageComponent {
constructor(
#Inject(DOCUMENT) private document: Document
) { }
goToUrl(): void {
this.document.location.href = 'https://google.com/';
}
}
HTML file:
<button type="button" (click)="goToUrl()">Google</button>
In your component.ts
import { Component } from '#angular/core';
#Component({
...
})
export class AppComponent {
...
goToSpecificUrl(url): void {
window.location.href=url;
}
gotoGoogle() : void {
window.location.href='https://www.google.com';
}
}
In your component.html
<button type="button" (click)="goToSpecificUrl('http://stackoverflow.com/')">Open URL</button>
<button type="button" (click)="gotoGoogle()">Open Google</button>
<li *ngFor="item of itemList" (click)="goToSpecificUrl(item.link)"> // (click) don't enable pointer when we hover so we should enable it by using css like: **cursor: pointer;**
Just simple as this
window.location.href='http://www.google.com/';