Ionic 3 in #Component, use variable from class - ionic-framework

I'm trying to implement template for different app language.
1 approach I've came out with if possible, can I use variable from class to be defined in #IonicPage() #Component -> templateUrl ? My ts:
#IonicPage()
#Component({
selector: 'page-mypage',
templateUrl: {templatePath},
})
export class MyPage {
templatePath;
constructor(... , private storage: Storage) {
storage.get('lang').then((langVal) => {
this.templatePath = (langVal=='de') ? 'mypage_de.html' : 'mypage.html';
});
}
}

Related

Add Components dynamically in DOM ionic+angular

I am following How to Dynamically Create a Component in Angular to add components dynamically inside another component. I am receiving a weired error of undefined variable.
My Component file (MessComponent)
<template #messContainer>
<p>
mess works!
</p>
</template>
ts file
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-mess',
templateUrl: './mess.component.html',
styleUrls: ['./mess.component.scss'],
})
export class MessComponent implements OnInit {
constructor() { }
ngOnInit() {}
}
Parent Component (hosting dynamic component)
module ts file
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { CommonModule } from '#angular/common';
import { IonicModule } from '#ionic/angular';
import { FormsModule } from '#angular/forms';
import { HomePage } from './home.page';
import { HomePageRoutingModule } from './home-routing.module';
import { MessComponent } from './../mess/mess.component';
#NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
HomePageRoutingModule
],
declarations: [HomePage, MessComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
entryComponents: [MessComponent]
})
export class HomePageModule {}
ts file
import { Component, ViewChild, ViewContainerRef, ComponentFactoryResolver, ComponentRef, ComponentFactory, OnInit } from "#angular/core";
import { MessComponent } from "./../mess/mess.component";
#Component({
selector: "app-home",
templateUrl: "home.page.html",
styleUrls: ["home.page.scss"],
})
export class HomePage implements OnInit {
componentRef: any;
#ViewChild('messContainer', { read: ViewContainerRef, static: true }) entry: ViewContainerRef;
createComponent() {
this.entry.clear();
const factory = this.resolver.resolveComponentFactory(MessComponent);
this.componentRef = this.entry.createComponent(factory);
}
destroyComponent() {
this.componentRef.destroy();
}
constructor(private resolver: ComponentFactoryResolver) {}
ngOnInit(): void {
this.createComponent();
}
}
and the error I am receiving
Uncaught (in promise): TypeError: this.entry is undefined
I understand this is claiming regarding the variable entry, but don't understand why it is not identifying that variable. To conclude, why I cannot add the component?
Solved it. Actually I was passing wrong param to the #ViewChild(''). I was passing the template name (container) of the child while I should have passed the container name in the parent component. So created a div in the parent component with #messContainer and corrected the #ViewChild
Important!:
now #messContainer is in the parent component and everything works as expected.
#ViewChild('messContainer', { read: ViewContainerRef, static: true }) entry: ViewContainerRef;

Ionic 3 - Multiple tables in indexedDB

I want to use two tables in the indexedDB but the inoic 3 documentation is not very good at this point.
in app.modules I imported the IonicStorageModule
IonicStorageModule.forRoot()
Then in my storage-uitls.ts file I tried to generate two tables in the constructor like it is mentioned here
constructor(private storage: Storage) {
console.log("---------------")
this.gpsData = new Storage({
name: '__my_custom_db',
storeName: '_contacts',
driverOrder: ['indexeddb', 'sqlite', 'websql'],
});
this.serviceData = new Storage({
name: '__my_custom_db',
storeName: '_media',
driverOrder: ['indexeddb', 'sqlite', 'websql'],
});
}
But this doesn't work. I just get the default generated table in the indexedDB.
Anyone know how to generate my own tables and acces them?
My setup for an IONIC 4 project (I've not tried it in a IONIC 3 project):
import { Storage } from '#ionic/storage';
#Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss']
})
export class Tab1Page implements OnInit {
private newReleasesDB: any;
constructor() {
this.newReleasesDB = new Storage({
name: '__myCustom_db',
storeName: '_newReleases',
driverOrder: ['sqlite', 'indexeddb', 'websql', 'localstorage']
});
}
ngOnInit() {
// get saved records from Storage
this.newReleasesDB.get('keyname').then((data: any) => {
// do stuff with the data in storage
});
}
}
This works with multiple stores in the same DB, like so:
import { Storage } from '#ionic/storage';
#Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss']
})
export class Tab1Page implements OnInit {
private newReleasesDB: any;
private myFrendsDB: any;
constructor() {
this.newReleasesDB = new Storage({
name: '__myCustom_db',
storeName: '_newReleases',
driverOrder: ['sqlite', 'indexeddb', 'websql', 'localstorage']
});
this.myFrendsDB = new Storage({
name: '__myCustom_db',
storeName: '_myFriends',
driverOrder: ['sqlite', 'indexeddb', 'websql', 'localstorage']
});
}
ngOnInit() {
// get saved records from Storage
this.newReleasesDB.get('keyname').then((data: any) => {
// do stuff with the data in storage
});
// get saved friends from Storage
this.myFrendsDB.get('keyname').then((data: any) => {
// do stuff with the data in storage
});
}
}
If you're having trouble try clearing your storage and running the script again.

what is wrong in my storage implementation ionic 2 app?

i'm trying to save data in local storage in ionic 2 app so i
import the storage and did exactly like i saw in the website and it not save the data in the storage
import { Component} from '#angular/core';
import { NavController,NavParams,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";
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
pages: Array<{title: string, component: any}>;
photo:any;
constructor(public navCtrl: NavController,public storage:Storage) {
}
ionViewDidLoad() {
this.getDetailsFacebook();
}
getDetailsFacebook() {
var that=this;
Facebook.getLoginStatus().then((response)=> {
if (response.status == 'connected') {
Facebook.api('/' + response.authResponse.userID + '?fields=id,name,gender', []).then((response)=> {
that.uid = response.id;
that.photo = "http://graph.facebook.com/"+that.uid+"/picture?type=large";
that.storage.set('photo',that.photo');
//console.log("id:"+this.uid+this.name+this.photo);
}, (error)=> {
alert(error);
})
}
else {
alert('Not Logged in');
}
})
photo of the inspect with chrome developer
i don't see any key of photo as i set it.. why is that?
Installation
To use this in your Ionic 2/Angular 2 apps, either start a fresh Ionic project which has it installed by default, or run:
npm install #ionic/storage
If you'd like to use SQLite as a storage engine, install a SQLite plugin (only works while running in a simulator or on device):
cordova plugin add cordova-sqlite-storage --save
In order to use Storage you may have to edit your NgModule declaration in src/app/app.module.ts to add Storage as a provider as below:
import { Storage } from '#ionic/storage';
#NgModule({
declarations: [
...
],
imports: [
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
...
],
providers: [ Storage ] // Add Storage as a provider
})
export class AppModule {}
Now, you can easily inject Storage into a component:
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { Storage } from '#ionic/storage';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController, public storage: Storage) {
}
}
To set an item, use Storage.set(key, value):
this.storage.set('name', 'Mr. Ionitron');
To get the item back, use Storage.get(name).then((value) => {}) since get() returns a Promise:
this.storage.get('name').then((name) => {
console.log('Me: Hey, ' + name + '! You have a very nice name.');
console.log('You: Thanks! I got it for my birthday.');
});
For more info on Storage module refer link: https://github.com/driftyco/ionic-storage

Angular 2 How to add click event with empty template?

I have the following Component:
import {Component, ElementRef} from 'angular2/core';
#Component({
selector: 'test',
template: ''
})
export class TestComponent {
el;
constructor(public elementRef: ElementRef) {
this.el = elementRef.nativeElement;
this.renderer = new THREE.WebGLRenderer();
this.el.appendChild(this.renderer.domElement);
}
onClick() {
console.log(this);
}
}
Since the template is empty, how can I add a click event to the component? Note that
this.el.addEventListener('click', this.onClick, false);
won't work because the click event is added to this.el, instead of the component itself (console log returns < test >< /test > rather than TestComponent itself).
You can use host-listener:
#Component({
selector: 'test',
template: ''
host: {'(click)':'clickHandler($event)'}
})
export class TestComponent {
// #HostListener('click') // alternative way to the decorator argument
clickHandler() {
doSomething();
}
}

how to access super component class variable into sub component Class?

How i access super component class variable into sub component in Angular2?
super Component Article.ts
#Component({
selector: 'article'
})
#View({
templateUrl: './components/article/article.html?v=<%= VERSION %>',
styleUrls : ['./components/article/article.css'],
directives: [CORE_DIRECTIVES, AmCard, NgFor]
})
export class Article{
articleArr : Array;
constructor() {
this.articleArr = new Array();
}
articleSubmit(articleSubject, articleName, articleUrl)
{
this.articleArr.push({title: articleSubject.value, user : articleName.value, url : articleUrl.value});
}
}
super Component article.html
<div *ng-for="#item of articleArr">
<am-card card-title="{{item.title}}" card-link="{{item.url}}" card-author="{{item.user}}"></am-card>
</div>
sub component amcard.ts
#Component({
selector: 'am-card',
properties : ['cardTitle', 'cardLink', 'cardAuthor']
})
#View({
templateUrl: './components/card/card.html?v=<%= VERSION %>',
styleUrls : ['./components/card/card.css'],
directives: [CORE_DIRECTIVES]
})
export class AmCard {
constructor() {
}
}
sub Component amcard.html
<div class="card">
...
</div>
So my question is how to access articleArr of Article Class in AmCard class ?
advanced
Thanks for helping me.
You can inject a parent component into a child using angular2 Dependency Injection. Use #Inject parameter decorator and forwardRef to do it (forwardRef allows us to refer to Article which wasn't yet defined). So your AmCard component will look like (see this plunker):
#Component({
selector: 'am-card',
template: `
<span>{{ articleLength }} - {{ cardTitle }}<span>
`
})
export class AmCard {
#Input() cardTitle: string;
#Input() cardLink: string;
#Input() cardAuthor: string;
constructor(#Inject(forwardRef(() => Article)) article: Article) {
// here you have the parent element - `article`
// you can do whatever you want with it
this.articleLength = article.articleArr.length;
setTimeout(() => {
article.articleSubmit({ value: Math.random() }, {}, {});
}, 1000)
}
}
But, IMHO, it's a bad pattern. If possible, it's much better to use output property (event binding) to pass message to a parent component and in a parent component handle that message. In your case it would look like (see this plunker):
#Component({ /* ... component config */})
class AmCard {
// ... input properties
#Output() callSubmit = new EventEmitter();
constructor() {
setTimeout(() => {
// send message to a parent component (Article)
this.callSubmit.next({ value: Math.random() });
}, 1000)
}
}
#Component({
// ... component config
template: `
<h3>Article array:</h3>
<div *ng-for="#item of articleArr">
<am-card
[card-title]="item.title"
[card-link]="item.url"
[card-author]="item.user"
`/* handle message from AmCard component */+`
(call-submit)=" articleSubmit($event, {}, {}) "
></am-card>
</div>
`
})
class Article{
// ... properties and constructor
articleSubmit(aa, an, au) {
this.articleArr.push({ title: as.value, user: an.value, url: au.value });
}
}