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.
Related
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';
});
}
}
I'm storing a JSON Array via Ionic Storage like this:
this.storage.set('data', this.data).then().catch(err => {
this.data.splice(this.data.indexOf(Data), 1);
});
and fetching it in a function:
fetchData(){
this.storage.get('data').then(
(data: {value: string, usage: string, date: string, addedDate: string}[]) => {
this.data = data != null ? data : [];
console.log('DATA FETCHED: ' + data);
return data;
}
).catch(err => {
console.log(err);
});
}
I stored 4 objects in the array, but the console.log just gives me this back:
DATA FETCHED: [object Object],[object Object],[object Object],[object Object]
What should I do to get the array displayed right? I already tried with .toString() and .slice()
relevant part in home.html:
<ion-item *ngFor="let item of items">
<h2>{{ item.usage }}</h2>
<p>{{ item.date | date:'dd MMM yyyy' }}</p>
<h1 item-end ngClass="{{ item.value.charAt(0) === '-' ? 'expense' : 'income' }}">{{ item.value }} €</h1>
<!--<h1 item-end class="income">+ 450,00 €</h1>!-->
</ion-item>
home.ts:
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
items: any = this.moneyService.fetchData();
incomeval: any = IncomevalPage;
expenseval: any = ExpensevalPage;
constructor(public navCtrl: NavController, private moneyService: MoneyService) {}
ionViewWillEnter(){
this.items = this.moneyService.fetchData();
}
}
I think that, in addition to what Marco said in his answer, the problem is that you're not returning anything from fetchData(). The return statement is inside the promise. Promises might take a while to get used to, but if you return the result, it will be a new promise with the new value. It might be easier to understand with an example:
var promise = Promise.resolve("first").then(val => "second");
promise.then(val => console.log("val is", val));
// Prints: "val is second"
You are setting this.data of the MoneyService but it's not accessed anywhere in the HomePage component.
What if you change fetchData to this:
fetchData(){
return this.storage.get('data').then((data: {value: string, usage: string, date: string, addedDate: string}[]) => {
return data != null ? data : [];
});
}
It will now return a promise, which you will have to take care of properly in HomePage, maybe something like this (untested):
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
items: any;
incomeval: any = IncomevalPage;
expenseval: any = ExpensevalPage;
constructor(public navCtrl: NavController, private moneyService: MoneyService) {
moneyService.fetchData().then(result => this.items = result);
}
}
It will update this.items as soon as the data is available.
You need some corrections with home.ts:
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
items: any;
moneyService: any;
incomeval: any = IncomevalPage;
expenseval: any = ExpensevalPage;
constructor(public navCtrl: NavController, data: MoneyService) {
this.items = null;
this.moneyService = data;
}
ionViewWillEnter(){
this.items = this.moneyService.fetchData();
}
}
I'm having a hard time trying to set a max value using the data driven approach in Angular2.
I want to set the max value of the input to a property called userLimit, which I get from firebase. This is my code:
component.ts
import { Component, OnInit, AfterViewInit } from '#angular/core';
import { FormBuilder, FormGroup, Validators, FormControl } from "#angular/forms";
import { FiredbService } from '../services/firedb.service';
import { AuthService } from '../services/auth.service';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';
#Component({
selector: 'my-dashboard',
styleUrls: ['./recibirpago.component.scss'],
templateUrl: './recibirpago.component.html'
})
export class RecibirpagoComponent implements OnInit, AfterViewInit {
myForm2: FormGroup;
uid: string;
userLimit: any;
constructor(private fb: FormBuilder,
private dbfr: FiredbService,
private db: AngularFireDatabase,
private authService: AuthService) {
this.myForm2 = this.fb.group({
email: ['', Validators.email],
clpmount: ['', [Validators.required, Validators.max(this.userLimit)]]
});
}
ngOnInit() {
this.uid = this.authService.getUserUid();
}
ngAfterViewInit() {
this.dbfr.getUserLimit(this.uid).subscribe(snapshot => {
this.userLimit = snapshot.val().accountLimit;
console.log(this.userLimit);
})
}
If I write, for example, Validators.max(5000) it works, but if I try to get the data from Firebase it doesn't work.
Thanks for your help!
The problem is that the constructor is executing before the ngAfterViewInit so you don't have the value of the userLimit at that point.
Instead use the setVAlidators method within the subscribe where you get the data.
Something like this:
constructor
this.myForm2 = this.fb.group({
email: ['', Validators.email],
clpmount: ['', Validators.required] // <-- not here
});
ngAfterViewInit
ngAfterViewInit() {
this.dbfr.getUserLimit(this.uid).subscribe(snapshot => {
this.userLimit = snapshot.val().accountLimit;
console.log(this.userLimit);
const clpControl = this.myForm2.get(`clpmount');
clpControl.setValidators(Validators.max(this.userLimit)); // <-- HERE
clpControl.updateValueAndValidity();
})
}
NOTE: Syntax was not checked.
I started to write Angular 2 application. I use there angular2 schema forms. It generates me bootstrap-like form well, however I'm not able to style it in any manner.
Component where I use schema forms body
import {Component, Input, OnInit} from '#angular/core';
import { HttpClient } from '../../shared/HttpClient.service';
#Component({
selector: 'stylists-section',
templateUrl: './stylists-section.component.html',
styleUrls: ['./stylists-section.component.scss'],
})
export class StylistsSectionComponent implements OnInit{
#Input() quantity: number;
#Input() col: string;
#Input() query: string;
#Input() title: string;
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get('data/Users', {'isStylist': true})
.subscribe(response => {
this.stylists = response;
}, err => {
console.error('our error: ', err);
})
}
I tried to style it through this scss file. What I do wrong?
I experiment with Angular 2 - Material Design Lite especially with the table component but I can not figure out how would I pass data from server on ajax request. Here is the example provided for table initialisation.
How would I pass data from restAPI to table component?
Here I have a kind of working example. I placed the initial data on my Component Init method where I call the DataService which populates the table. I'm not sure if is the right workaround but at this point I have data in table.
import { Component, ViewChild, ViewContainerRef, OnInit, Pipe, PipeTransform } from '#angular/core';
import { MdDialog, MdDialogConfig, MdIcon } from "#angular/material";
import { AuthenticationService, DialogsService, DataService } from '../../../services/';
import { RouterModule, Routes, Router } from '#angular/router';
import {
IMdlTableModelItem,
MdlDefaultTableModel
} from 'angular2-mdl';
export interface ITableItem extends IMdlTableModelItem {
username: string;
email: string;
role: string;
unitPrice: number;
}
#Component({
selector: 'employees',
templateUrl: 'app/layouts/secure/employees/employees.html',
providers: [DialogsService, MdIcon]
})
export class EmployeesComponent implements OnInit {
public message: string;
public employees: any[];
public result: any;
public showSearchBar: false;
public tableData:[ITableItem];
public selected;
public tableModel = new MdlDefaultTableModel([
{key:'username', name:'Username', sortable:true},
{key:'email', name:'Email', sortable:true},
{key:'role', name:'Role', sortable:true},
{key:'status', name:'Status', sortable:true},
{key:'unitPrice', name:'Test', numeric:true}
]);
constructor(
private dialogsService: DialogsService,
public viewContainerRef: ViewContainerRef,
private _dataService : DataService,
private router: Router
) {
}
openDialog() {
this.dialogsService
.confirm('User Form', 'Are you sure you want to do this?', this.viewContainerRef)
.subscribe(res => this.result = res);
}
toggleSearch() {
console.log(this)
}
ngOnInit() {
var self = this;
this._dataService
.GetAll('employees')
.subscribe( data => {
data = Object.keys(data).map((key)=>{ return data[key]})
this.employees = data;
this.tableData = data;
this.tableModel.addAll(this.tableData);
}, error => console.log(error),
() => function ( data ) {
this.tableData = this.employees;
this.tableModel.addAll(this.tableData);
this.selected = this.tableData.filter( data => data.selected);
},
);
}
generateArray(obj){
return Object.keys(obj).map((key)=>{ return obj[key]});
}
selectionChanged($event){
this.selected = $event.value;
}
}
#fefe made it a little more difficult than it had to be, at least with the current version. The magic of the as keyword can do the heavy lifting.
For example my class setup looks like:
import...
export interface IUnreadMessage extends IMdlTableModelItem {
messageId: number;
subject: string;
from: string;
}
#Component ...
export class ...
private unreadMessagesTable = new MdlDefaultTableModel([
{key: 'messageId', name: 'Message ID'},
{key: 'subject', name: 'Subject'},
{key: 'from', name: 'From'}
]);
Then in my ajax call I have:
...ajax call here).subscribe(value => {
const messages = value as Array<IUnreadMessage>;
this.unreadMessagesTable.addAll(messages);
},
error => {
...error handler here...
});
Make sure your interface is EXACTLY (including case) the same as your returned ajax data and it should hook right up!