i m new in ionic and i want to load my web api data in grid ionic so below is my code.
grid.html
<ion-header>
<ion-navbar>
<button ion-button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Grid Demo</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-refresher (ionRefresh)="doRefresh($event)">
<ion-refresher-content></ion-refresher-content>
</ion-refresher>
<ion-grid>
<ion-row *ngFor="let product of products">
<ion-col width-50 >
<h1>{{product.title}}</h1>
</ion-col>
</ion-row>
</ion-grid>
<ion-infinite-scroll (ionInfinite)="doInfinite($event)">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>
grid.ts
import { Component } from '#angular/core';
import { NavController, NavParams, LoadingController } from 'ionic-angular';
import { ProductListProvider } from '../../providers/product/product'
#Component({
templateUrl: 'grid.html',
providers:[ProductListProvider]
})
export class GridHttpPage {
public response: any;
public products: any =[];
public count: any;
public loader: any;
public page: number = 0;
public isLoading: boolean =true;
public totalItem: number ;
doRefresh(refresher) {
console.log('Begin async operation', refresher);
setTimeout(() => {
this.page=0;
this.loadData(true);
console.log('Async operation has ended');
refresher.complete();
}, 2000);
}
constructor(public navCtrl: NavController, public navParams: NavParams, public personListProvider: ProductListProvider, public loadingCtrl: LoadingController) {
this.count = 0;
this.loadData(this.isLoading);
}
presentLoading() {
this.loader = this.loadingCtrl.create({
// spinner: 'hide',
content: "Please wait...",
// duration: 3000,
// showBackdrop: true,
// enableBackdropDismiss: true,
// dismissOnPageChange: true
});
this.loader.onDidDismiss(() => {
// console.log('Dismissed loading');
});
this.loader.present();
}
loadData(isLoading) {
if(isLoading==true)
{
this.presentLoading();
}
this.page ++;
this.personListProvider.load(this.page)
.then(data => {
this.response = data;
this.totalItem = this.response.listing.total;
//this.products = this.response.listing.data;
for (let i = 0; i < this.response.listing.data.length; i++) {
this.products.push(this.response.listing.data[i]);
// console.log(this.response.listing.data[i]);
}
if(isLoading==true)
{
this.loader.dismiss();
}
console.log(this.response.listing);
console.log(this.products);
console.log(this.totalItem);
});
}
doInfinite(infiniteScroll) {
console.log('Begin async operation');
setTimeout(() => {
// for (let i = 0; i < 30; i++) {
// this.items.push( this.items.length );
// }
if(this.products.length <= this.totalItem )
{
this.loadData(false);
}
console.log('Async operation has ended');
infiniteScroll.complete();
}, 500);
}
}
When i run above code i get following type of output Refer screenshots.
GridView
It display single column list i want to display in 2 column so any idea how can i display in two column in gridview ionic?
I got solution
Make change in grid.ts file
rows: any;
in loadata funtion
loadData(isLoading) {
if(isLoading==true)
{
this.presentLoading();
}
this.page ++;
this.personListProvider.load(this.page)
.then(data => {
this.response = data;
this.totalItem = this.response.listing.total;
for (let i = 0; i < this.response.listing.data.length; i++) {
this.products.push(this.response.listing.data[i]);
}
this.rows = Array.from(Array(Math.ceil(this.products.length / 2)).keys());
if(isLoading==true)
{
this.loader.dismiss();
}
console.log(this.response.listing);
console.log(this.products);
console.log(this.totalItem);
});
}
in grid.html change as follows
<ion-grid>
<ion-row *ngFor="let i of rows">
<ion-col *ngFor="let product of products | slice:(i*2):(i+1)*2" width-50 (click)="openDetailPage(product)">
<ion-card>
<ion-avatar item-left>
<img src="{{product.medium_image}}" />
</ion-avatar>
<ion-card-content>
<ion-card-title>
<h6>{{product.title}}</h6>
<p> <b>Price: </b> {{product.price}}</p>
</ion-card-title>
</ion-card-content>
</ion-card>
</ion-col>
</ion-row>
</ion-grid>
Related
I try to test a template driven form in Ionic v4.
But I can`t find a way to get the input element in the ion-input element.
This is what I tried:
login-register.page:
import { GroupsService } from './../../services/groups.service';
import { AuthenticateService, RegisterLoginReturnMessage } from './../../services/authenticate.service';
import { Component, OnInit, OnDestroy, ViewChild } from '#angular/core';
import { ActivatedRoute, Router, NavigationExtras } from '#angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { AlertController, ToastController } from '#ionic/angular';
import { TranslateService } from '#ngx-translate/core';
import { Location } from '#angular/common';
import { NavController } from '#ionic/angular';
import { addslashes } from './../../helpers';
import { FCM } from '#ionic-native/fcm/ngx';
import { StorageService } from 'src/app/services/storage.service';
import { NgForm } from '#angular/forms';
#Component({
selector: 'app-login-register',
templateUrl: './login-register.page.html',
styleUrls: ['./login-register.page.scss'],
})
export class LoginRegisterPage implements OnInit, OnDestroy {
#ViewChild('loginRegisterForm', { static: true })loginRegisterForm: NgForm;
navParams: any;
email: string;
userName = 'blafasel';
firstName: string;
lastName: string;
password: string;
passwordreset: string;
loading = false;
emailRegExpr = '[a-zA-Z]{1}[a-zA-Z0-9.-_]*#[a-zA-Z0-9]{1}[a-zA-Z0-9.-]*[a-zA-Z0-9]{1}[.][a-zA-Z]{2,}';
gdprChecked = false;
private unsubscribe: Subject<void> = new Subject();
constructor(
private route: ActivatedRoute,
private router: Router,
private authenticateService: AuthenticateService,
public alertController: AlertController,
public translateService: TranslateService,
private location: Location,
private navCtrl: NavController,
private groupsService: GroupsService,
private toastController: ToastController,
private fcm: FCM,
private storageService: StorageService
) {
this.route.queryParams.subscribe(params => {
if (this.router.getCurrentNavigation().extras.state) {
console.log('if (this.router.getCurrentNavigation().extras.state)');
this.navParams = this.router.getCurrentNavigation().extras.state;
console.log(this.navParams);
}
});
}
ngOnInit() {}
ionViewWillEnter() {
console.log('login is entered');
}
submitForm(): void {
this.loading = true;
console.log('submitform');
if (this.navParams.mode === 'register') {
this.authenticateService
.registerUserAndGetMail(this.userName, this.email, this.firstName, this.lastName)
.pipe(takeUntil(this.unsubscribe))
.subscribe(
(response: RegisterLoginReturnMessage) => {
this.loading = false;
if (response.valid === true) {
this.navCtrl.navigateRoot('');
this.presentAlert('success', 'registerSuccess');
} else {
this.presentAlert('error', response.message[0], response.message[1] ? response.message[1] : '');
}
console.log('response:', response);
},
(error: RegisterLoginReturnMessage) => {
this.loading = false;
this.presentAlert('error', error.message[0], error.message[1] ? error.message[1] : '');
console.log('error bla:', error);
}
);
}
if (this.navParams.mode === 'login') {
this.authenticateService
.getUserToken(this.userName, addslashes(this.password))
.then((response: RegisterLoginReturnMessage) => {
this.loading = false;
// this.location.back();
// this.presentAlert('success', response.message[0], response.message[1] ? response.message[1] : '');
this.presentToast('success', response.message[0], response.message[1] ? response.message[1] : '');
// Fetch Groups from backend
this.groupsService.fetchUserData().then(data => {
console.log('promise all data:', data);
this.fcm
.subscribeToTopic(data[2].id)
.then(() => {
console.log('succesfullysubscribe:', data[2].id);
})
.catch(err => {
console.error('error subscription:', err);
});
});
this.navCtrl.navigateRoot('');
console.log('response:', response);
})
.catch((error: RegisterLoginReturnMessage) => {
this.loading = false;
if (error.status === 0) {
this.presentAlert('error', 'wrongConnectionWp');
} else if (error.status === 403) {
this.presentAlert('error', 'wrongLoginData');
} else {
this.presentAlert('error', error.status.toString(), error.statusText);
}
console.log('error bla:', error);
});
}
if (this.navParams.mode === 'passwordReset') {
this.authenticateService
.resetPassword(this.passwordreset)
.then(response => {
this.loading = false;
this.presentAlert('success', response.message);
this.navCtrl.navigateRoot('');
})
.catch(error => {
this.loading = false;
this.presentAlert('error', error.message[0]);
console.log('error in reseet pass catch', error);
});
}
}
presentAlert(header: string, message: string, messageTwo?: string): void {
this.translateService.get([header, message, messageTwo ? messageTwo : '', 'OK']).subscribe(async (res: string[]) => {
const newAlert = await this.alertController.create({
header: res[header],
message: messageTwo ? res[message] + res[messageTwo] : res[message],
buttons: [
{
text: 'OK',
handler: () => {
console.log('ok pressed');
},
},
],
});
await newAlert.present();
});
}
async presentToast(title: string, message: string, message2: string = '', duration?: number): Promise<void> {
this.translateService.get([title, message, message2, 'OK']).subscribe(async (res: string[]) => {
const toast = await this.toastController.create({
header: res[title],
message: message2 ? `${res[message]}<br>${res[message2]}` : `${res[message]}`,
position: 'bottom',
duration: duration ? duration : 3000,
showCloseButton: true,
});
toast.present();
});
}
showPassword(passwordInput) {
passwordInput.type = passwordInput.type === 'password' ? 'text' : 'password';
}
gotToGdpr() {
const bla = this.translateService.currentLang;
console.log('gotogdpr clkicked:', this.translateService.currentLang);
const navigationExtras: NavigationExtras = {
state: {
postId:
this.translateService.currentLang === 'de' ||
this.translateService.currentLang === 'de-AT' ||
this.translateService.currentLang === 'de-CH' ||
this.translateService.currentLang === 'de-DE' ||
this.translateService.currentLang === 'de-LI'
? this.storageService.appData.gdprId.de
: this.storageService.appData.gdprId.en,
},
};
this.router.navigateByUrl('posts', navigationExtras);
}
ngOnDestroy(): void {
// For unsubscribing all Subscriptions
console.log('ngOnDestory');
this.unsubscribe.next();
this.unsubscribe.complete();
}
}
login-register.page.html:
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button text="{{ 'back' | translate }}"></ion-back-button>
</ion-buttons>
<ion-title *ngIf="navParams.mode === 'login'">{{ 'login' | translate }}</ion-title>
<ion-title *ngIf="navParams.mode === 'register'">{{ 'register' | translate }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<form #loginRegisterForm="ngForm" (ngSubmit)="submitForm()">
<ion-list inset>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
<ion-input
[placeholder]="'email' | translate"
name="email"
id="emailField"
type="text"
required
[(ngModel)]="email"
[pattern]="emailRegExpr"
></ion-input>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
<ion-input
[placeholder]="'username' | translate"
name="userName"
id="userNameField"
type="text"
required
[(ngModel)]="userName"
pattern="[a-zA-Z0-9]{4,30}"
></ion-input>
</ion-item>
<div class="username-message" item-content *ngIf="navParams.mode === 'register'">
{{ 'usernameRestrictions' | translate }}
</div>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
<ion-input
[placeholder]="'firstName' | translate"
name="firstName"
id="firstNameField"
type="text"
required
[(ngModel)]="firstName"
pattern="[a-zA-Z0-9\-\s]{1,100}"
></ion-input>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
<ion-input
[placeholder]="'lastName' | translate"
name="lastName"
id="userNameField"
type="text"
required
[(ngModel)]="lastName"
pattern="[a-zA-Z0-9\-\s]{1,100}"
></ion-input>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'login'">
<ion-input
[placeholder]="'username' | translate"
name="userName"
id="userNameField"
type="text"
required
[(ngModel)]="userName"
></ion-input>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'login'">
<ion-input
#passwordInput
[placeholder]="'password' | translate"
name="password"
id="passwordField"
type="password"
required
[(ngModel)]="password"
></ion-input>
<ion-icon
*ngIf="passwordInput.type === 'password'"
slot="end"
name="eye"
(click)="showPassword(passwordInput)"
style="font-size: 1.7rem;z-index:10"
></ion-icon>
<ion-icon
*ngIf="passwordInput.type == 'text'"
slot="end"
name="eye-off"
(click)="showPassword(passwordInput)"
style="font-size: 1.7rem;z-index:10"
></ion-icon>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'passwordReset'">
<ion-input name="passwordreset" id="passwordreset" type="text" required [(ngModel)]="passwordreset"></ion-input>
</ion-item>
<div class="username-message" item-content *ngIf="navParams.mode === 'passwordReset'">
{{ 'passwordReset' | translate }}
</div>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
<a (click)="gotToGdpr()">{{ 'privacyPolicyLink' | translate }}</a>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
{{ 'gdprHint' | translate }}
<ion-checkbox pattern="true" name="gdprChecked" slot="end" [(ngModel)]="gdprChecked"></ion-checkbox>
</ion-item>
</ion-list>
<ion-row>
<ion-col>
<ion-button size="full" color="tertiary" type="submit" [disabled]="!loginRegisterForm.form.valid">{{
'submit' | translate
}}</ion-button>
</ion-col>
</ion-row>
</form>
<ion-spinner *ngIf="loading" class="spinner-large spinner-center" color="secondary"></ion-spinner>
</ion-content>
login-register.page.spec.ts:
import { AuthenticateService } from './../../services/authenticate.service';
import { IonicStorageModule } from '#ionic/storage';
import { CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { async, ComponentFixture, TestBed, inject } from '#angular/core/testing';
import { LoginRegisterPage } from './login-register.page';
import { TranslateModule, TranslateLoader } from '#ngx-translate/core';
import { HttpClientModule, HttpClient } from '#angular/common/http';
import { createTranslateLoader } from 'src/app/app.module';
import { FormsModule } from '#angular/forms';
import { IonicModule } from '#ionic/angular';
import { RouterTestingModule } from '#angular/router/testing';
import { FCM } from '#ionic-native/fcm/ngx';
import { FCMMock } from 'src/mocks/fcmMock';
import { Router } from '#angular/router';
import { By } from '#angular/platform-browser';
// test environment
const testModuleConfig = () => {
TestBed.configureTestingModule({
declarations: [LoginRegisterPage],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [{ provide: FCM, useClass: FCMMock }, AuthenticateService],
imports: [
FormsModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient],
},
}),
RouterTestingModule.withRoutes([]),
IonicModule.forRoot(),
IonicStorageModule.forRoot(),
HttpClientModule,
],
}).compileComponents();
};
describe('LoginRegisterPage', () => {
let component: LoginRegisterPage;
let fixture: ComponentFixture<LoginRegisterPage>;
let router: jasmine.SpyObj<Router>;
let service: AuthenticateService;
beforeEach(async(() => {
testModuleConfig();
}));
beforeEach(inject([AuthenticateService], (s) => {
service = s;
router = TestBed.get(Router);
spyOn(router, 'getCurrentNavigation').and.returnValue({ extras: { state: { mode: 'login' } } });
fixture = TestBed.createComponent(LoginRegisterPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
afterEach(() => {
fixture.destroy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should be navparams login', () => {
expect(component.navParams).toEqual({ mode: 'login' });
});
it('form invalid when empty', () => {
console.log('component.loginRegisterForm.form', component.loginRegisterForm.form);
expect(component.loginRegisterForm.form.valid).toBeFalsy();
});
it('should contain the correct title', () => {
// component.title = 'Test';
fixture.detectChanges();
// const element = fixture.debugElement.nativeElement.querySelector('#userNameField');
const element = fixture.debugElement.query(By.css('#userNameField input'));
console.log('element+++++++++++++++++', element);
console.log('element+++++++++.textContent++++++++', element.textContent);
const inputs = fixture.debugElement.queryAll(By.css('input'));
console.log('first input element+++++++++++++++++', inputs[0]);
// expect(element.i).toEqual('blafasel');
});
it('test function should return bla', () => {
expect(service.testTestFunction()).toBe('bla');
});
});
The
console.log('element+++++++++++++++++', element);
gives null. But the ion-input element is there with
fixture.debugElement.query(By.css('#userNameField'));
Can somebody help me here to make the input element available in the tests?
Thanx a lot.
You may use the #ViewChild angular decorator to get a reference to the ionic input element into a class instance variable.
For example, in your sample code:
<ion-input
#emailField
[placeholder]="'email' | translate"
name="email"
id="emailField"
type="text"
required
[(ngModel)]="email"
[pattern]="emailRegExpr"></ion-input>
In LoginRegisterPage, you can declare a member as:
#ViewChild('emailField', {static: false}) emailField: IonInput;
You can then access the control's angular component methods directly from the emailField member variable.
HTH.
I am in the process of upgrading from Ionic 2 beta to rc3. I have the following components that were working, but there must be something I need to do to make it fit with rc3.
When the user clicks an icon, it invokes the following function inorder to show a popover.
presentPopover(event: Event): void {
this.popover = this.popoverController.create(SearchJobsPopOverPage, {
ev: event
});
this.popover.present();
}
SearchJobsPopOverPage
import { Component } from '#angular/core';
import { NavController, ViewController, NavParams, Events } from 'ionic-angular';
import { MapPage } from '../map/map';
import { CategoryPage } from '../category/category';
import { JobModel } from '../model/jobModel';
import { ReviewPage } from '../review/review';
import { RatingModel } from '../model/ratingModel';
import { PersonModel } from '../model/personModel';
import { DateTimePage } from '../datetime/datetime';
#Component({
//selector: 'searchjobspopover',
template: `
<ion-content padding id="search-popover">
<ion-list>
<ion-row>
<ion-col>
<div style="text-align:center">
<div id="pinButton"><button ion-button class="search-popover-button" (click)="presentFilterMap()" color="danger"><ion-icon class="search-popover-icon" name="pin"></ion-icon></button></div>
<p>Location</p>
</div>
</ion-col>
<ion-col>
<div style="text-align:center">
<div id="pinButton"><button ion-button class="search-popover-button" (click)="presentFilterCategories()" primary><ion-icon class="search-popover-icon" name="happy"></ion-icon></button></div>
<p>Sectors</p>
</div>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<div style="text-align:center">
<div id="pinButton"><button ion-button class="search-popover-button search-button-star" (click)="presentFilterRating()"><ion-icon class="search-popover-icon" name="star"></ion-icon></button></div>
<p>Rating</p>
</div>
</ion-col>
<ion-col>
<div style="text-align:center">
<div id="pinButton"><button ion-button class="search-popover-button" (click)="presentFilterTime()" color="secondary"><ion-icon class="search-popover-icon" name="time"></ion-icon></button></div>
<p>Last Online</p>
</div>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<div style="text-align:center">
<div id="pinButton"><button ion-button class="search-popover-button" (click)="clearFilters()" color="light"><ion-icon class="search-popover-icon" name="trash"></ion-icon></button></div>
<p>Clear Filters</p>
</div>
</ion-col>
</ion-row>
</ion-list>
</ion-content>
`
})
export class SearchJobsPopOverPage {
public nav: NavController = null;
public jobModel: JobModel = null;
public events: Events = null;
public ratingModel: RatingModel = null;
public personModelLoggedIn: PersonModel = null;
public lastOnline: number = null;
constructor(public navParams: NavParams, nav: NavController, public viewCtrl: ViewController, events: Events) {
this.events = events;
this.nav = nav;
this.jobModel = navParams.get('jobModel');
this.lastOnline = navParams.get('lastOnline');
this.personModelLoggedIn = navParams.get('personModelLoggedIn');
if (!this.jobModel) {
this.jobModel = new JobModel();
}
this.ratingModel = navParams.get('ratingModel');
}
presentFilterMap(event: Event) {
//this.viewCtrl.dismiss().then(() => {
this.nav.push(MapPage, {
jobModel: this.jobModel,
ratingModel: this.ratingModel,
fromSearch: true
});
//});
}
presentFilterCategories(event: Event) {
this.viewCtrl.dismiss().then(() => {
this.nav.push(CategoryPage, {
jobModel: this.jobModel,
ratingModel: this.ratingModel,
fromSearch: true
});
});
}
presentFilterRating(event: Event) {
//this.viewCtrl.dismiss().then(() => {
this.nav.push(ReviewPage, {
jobModel: this.jobModel,
ratingModel: this.ratingModel,
personModelLoggedIn: this.personModelLoggedIn,
fromFilter: true
});
//});
}
presentFilterTime(event: Event) {
this.viewCtrl.dismiss().then(() => {
this.nav.push(DateTimePage, {
lastOnline: this.lastOnline,
fromSearch: true
});
});
}
clearFilters() {
if (this.jobModel) {
this.jobModel.locations = [];
this.jobModel.categories = [];
this.jobModel.subCategories = [];
this.lastOnline = null;
}
if (this.ratingModel) {
this.ratingModel.rating = -1;
}
let data = {
jobModel: this.jobModel,
ratingModel: this.ratingModel,
fromClearFilters: true
};
this.nav.popToRoot().then(() => {
this.events.publish('popupFilter:update', data);
});
}
}
Error
The popover is not displayed, but the following error is displayed in the browser console:
PopoverCmp ionViewPreLoad error: No component factory found for SearchJobsPopOverPage
Any help appreciated.
Sill me, I forgot to define the page in app.module.ts as is required post rc0.
I am in the process of upgrading from Ionic 2 beta to Ionic 2 rc3.
I have my app.component.ts file, that worked fine, when it was just displaying a root page. But as soon as I have tried to add menu items from my old working Ionic 2 beta version, I get the error below.
If anyone can advise how I can resolve this, I would appreciate the help.
Compile Error in CLI
[13:14:56] template error, "E:\Development\IDE\ionic-apps\WhatsAppClone\src\app\build\app.html": Error: ENOENT: no such
file or directory, open 'E:\Development\IDE\ionic-apps\WhatsAppClone\src\app\build\app.html'
Runtime Error in browser console
Unhandled Promise rejection: Failed to load build/app.html ; Zone: meteor-rxjs-zone ; Task: Promise.then ; Value: Failed to load build/app.html undefined polyfills.js:3:7730
Error: Uncaught (in promise): Failed to load build/app.html
Stack trace:
s#http://localhost:8100/build/polyfills.js:3:8568
s#http://localhost:8100/build/polyfills.js:3:8391
h/<#http://localhost:8100/build/polyfills.js:3:8902
sg</d</t.prototype.invokeTask#http://localhost:8100/build/polyfills.js:3:14040
sg</v</e.prototype.runTask#http://localhost:8100/build/polyfills.js:3:11392
i#http://localhost:8100/build/polyfills.js:3:8021
t/this.invoke#http://localhost:8100/build/polyfills.js:3:15204
app.component.ts
import { Component, ViewChild } from '#angular/core';
import { Storage } from "#ionic/storage";
import { Platform, Events, AlertController, Nav } from 'ionic-angular';
import { StatusBar, Push, Splashscreen } from 'ionic-native';
import { SearchJobsPage } from "../pages/searchjobs/searchjobs";
import { LoginPage } from '../pages/login/login';
import { LogoutPage } from '../pages/logout/logout';
import { PersonModel } from '../pages/model/personModel';
import { ChatsPage } from '../pages/chats/chats';
import { PersonPage } from '../pages/person/person';
import { SearchFavouriteJobsPage } from '../pages/searchfavouritejobs/searchfavouritejobs';
import { SearchPostingsPage } from '../pages/searchpostings/searchpostings';
import { SearchFavouritePostingsPage } from '../pages/searchfavouritepostings/searchfavouritepostings';
import { UtilityService } from '../pages/utils/utilityService';
import { NotificationService } from '../pages/service/notificationService';
import { JobService } from '../pages/service/jobService';
import { JobModel } from '../pages/model/jobModel';
import { MapLocationsPage } from '../pages/maplocations/maplocations';
import { MapRangePage } from '../pages/maprange/maprange';
//import { METEOR_PROVIDERS } from 'angular2-meteor';
// import * as Check from 'meteor/check';
// import * as EJSON from 'meteor/ejson';
//declare let Meteor;
#Component({
templateUrl: 'build/app.html'
})
export class MyApp {
#ViewChild(Nav) nav: Nav;
rootPage: any;
public storage: Storage = null;
public pages: Array<{ title: string, component: any }>;
public pages_person: Array<{ title: string, component: any }>;
public pages_person_admin: Array<{ title: string, component: any }>;
public menuTitle: string = 'Menu';
public personModel: PersonModel = null;
public utilityService: UtilityService = null;
public notificationService: NotificationService = null;
public personModelLoggedIn: PersonModel;
public jobService: JobService = null;
public events: Events = null;
public ios: boolean = false;
constructor(private platform: Platform, utilityService: UtilityService, notificationService: NotificationService, jobService: JobService, events: Events, private alertCtrl: AlertController, storage: Storage) {
this.storage = storage;
this.utilityService = utilityService;
this.jobService = jobService;
this.notificationService = notificationService;
this.events = events;
this.initializeApp();
if (this.platform.is('ios')) {
this.ios = true;
}
// this.rootPage = Meteor.user() ? TabsPage : LoginComponent;
this.rootPage = SearchJobsPage;
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.initializeApp();
StatusBar.styleDefault();
Splashscreen.hide();
});
// used for an example of ngFor and navigation
this.pages = [
{ title: 'Market', component: SearchJobsPage },
{ title: 'Postings', component: SearchPostingsPage },
{ title: 'Login', component: LoginPage }
];
this.pages_person = [
{ title: 'Market', component: SearchJobsPage },
{ title: 'Market Favourites', component: SearchFavouriteJobsPage },
{ title: 'Postings', component: SearchPostingsPage },
{ title: 'Favourite Postings', component: SearchFavouritePostingsPage },
{ title: 'Messages', component: ChatsPage },
{ title: 'Profile', component: PersonPage },
{ title: 'Logout', component: LogoutPage }
];
this.pages_person_admin = [
{ title: 'Market', component: SearchJobsPage },
{ title: 'Market Favourites', component: SearchFavouriteJobsPage },
{ title: 'Postings', component: SearchPostingsPage },
{ title: 'Favourite Postings', component: SearchFavouritePostingsPage },
{ title: 'Messages', component: ChatsPage },
{ title: 'Profile', component: PersonPage },
{ title: 'Logout', component: LogoutPage },
{ title: 'Map Locations', component: MapLocationsPage },
{ title: 'Map Range', component: MapRangePage }
];
}
initializeApp() {
StatusBar.styleDefault();
this.checkLogin();
this.utilityService.startUpChecks();
if (window['cordova']) {
this.utilityService.setLocalStrorage('this.chats.observe', 'false');
this.utilityService.setLocalStrorage('this.messages.observe', 'false');
this.utilityService.setLocalStrorage('this.messages.subscribe', 'false');
this.utilityService.setLocalStrorage('push:notifications.subscribe', 'false');
}
this.subscribeEvents();
}
// 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);
// }
public subscribeEvents(): void {
this.events.subscribe('push:notifications', (data) => {
this.checkLogin();
});
}
public pushNotifications(): void {
let observedPromise: Promise<string> = this.utilityService.getLocalStrorage('push:notifications.subscribe');
observedPromise.then((observed: string) => {
if (!observed || observed != 'true') {
this.utilityService.setLocalStrorage('push:notifications.subscribe', 'true');
try {
if (window['cordova']) {
if (this.personModelLoggedIn) {
let promiseJobsForPerson: Promise<JobModel[]> = this.jobService.getJobsByPerson(this.personModelLoggedIn.id);
promiseJobsForPerson.then((data) => {
let jobModelsForPerson: JobModel[] = data;
let topics: string[] = [];
topics.push('P' + this.personModelLoggedIn.id);
for (let i = 0; i < jobModelsForPerson.length; i++) {
let jobModel: JobModel = jobModelsForPerson[i];
topics.push('J' + jobModel.id);
}
//topics.push('J65'); // deleteme
//topics.push('P9'); // deleteme
let push = Push.init({
android: {
senderID: "893141127008",
topics: topics
},
ios: {
alert: "true",
badge: false,
sound: "true",
topics: topics
},
windows: {}
});
push.on('registration', (data1) => {
this.events.subscribe('messages:notify', (data) => {
let promise: Promise<string> = this.notificationService.push('null', data[0].topic, data[0].message, data[0].title);
promise.then((data2) => {
// console.log('app.ts messages2:notify', data2);
});
});
});
push.on('notification', (data) => {
this.events.publish('messages:update');
if (this.nav.getActive().name != 'ChatsPage' && this.nav.getActive().name != 'MessagesPage') {
//if user using app and push notification comes
if (data.additionalData.foreground) {
//if application open, show popup
let confirmAlert = this.alertCtrl.create({
title: data.title,
message: data.message,
buttons: [{
text: 'Ignore',
role: 'cancel'
}, {
text: 'View',
handler: () => {
this.rootPage = ChatsPage;
}
}]
});
confirmAlert.present(confirmAlert);
} else {
this.rootPage = ChatsPage;
}
}
});
push.on('error', (e) => {
alert('Error: ' + e.message);
console.log(e);
});
});
}
}
} catch (e) {
alert('Push Notification: ' + e.message());
console.log('Push Notification: ' + e.message());
}
}
});
}
public checkLogin(): void {
let promise: Promise<string> = this.utilityService.getLoggedInPerson();
promise.then((data) => {
this.personModelLoggedIn = JSON.parse(data);
if (this.personModelLoggedIn) {
this.utilityService.setUpMenuItems();
this.pushNotifications();
}
});
}
}
app.html
<ion-menu [content]="content" id="unauthenticated">
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
<ion-content>
<ion-list>
<button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)">
{{p.title}}
</button>
</ion-list>
</ion-content>
</ion-menu>
<ion-menu [content]="content" id="authenticated-person">
<ion-toolbar [class]="ios ? 'menu-toolbar' : ''">
<ion-title [class]="ios ? 'menu-title' : ''">
<div class="item-avatar-img" id="menu-item-avatar-img-person"></div>
<div class="item-avatar-name" id="menu-item-avatar-name-person"></div>
</ion-title>
</ion-toolbar>
<ion-content>
<ion-list>
<button menuClose ion-item *ngFor="let p of pages_person" (click)="openPage(p)">
{{p.title}}
</button>
</ion-list>
</ion-content>
</ion-menu>
<ion-menu [content]="content" id="authenticated-person-admin">
<ion-toolbar [class]="ios ? 'menu-toolbar' : ''">
<ion-title [class]="ios ? 'menu-title' : ''">
<div class="item-avatar-img" id="menu-item-avatar-img-person-admin"></div>
<div class="item-avatar-name" id="menu-item-avatar-name-person-admin"></div>
</ion-title>
</ion-toolbar>
<ion-content>
<ion-list>
<button menuClose ion-item *ngFor="let p of pages_person_admin" (click)="openPage(p)">
{{p.title}}
</button>
</ion-list>
</ion-content>
</ion-menu>
<!-- Disable swipe-to-go-back because it's poor UX to combine STGB with side menus -->
<ion-nav [root]="rootPage" #content swipeBackEnabled="false"></ion-nav>
Directory
You have set your templateUrl as build/app.html.
You shouldnt check it in build folder.
Try templateUrl: 'app.html' in app.component.ts
I am trying to make use of the Ionic DateTime component. I have the following code, but nothing displays (just the label and button). If anyone can advise, I would appreciate it.
datetime.html
<ion-header>
<ion-navbar>
<ion-title>Last Online</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<center>
<ion-spinner icon="android" *ngIf="loading"></ion-spinner>
</center>
<ion-row>
<ion-col>
<center>
<ion-label>Last Online</ion-label>
<ion-datetime displayFormat="h:mm A" pickerFormat="h mm A" [(ngModel)]="event.timeStarts"></ion-datetime>
</center>
</ion-col>
</ion-row>
<ion-buttons>
<button (click)="done()" block round class="form-button-text">{{'Done'}}</button>
</ion-buttons>
</ion-content>
datetime.ts
import { Component } from '#angular/core';
import { NavController, NavParams, Events } from 'ionic-angular';
import { JobModel } from '../model/jobModel';
#Component({
templateUrl: 'build/pages/datetime/datetime.html'
})
export class DateTimePage {
private loading: boolean = true;
private jobModel: JobModel = null;
private event: Events = null;
constructor(private nav: NavController, private navParams: NavParams, event: Events) {
this.event = event;
this.jobModel = navParams.get('jobModel');
if (!this.jobModel) {
this.jobModel = new JobModel();
}
this.loading = false;
}
private done(): void {
alert('todo');
}
}
The following works, it's a different date picker.
http://ionicframework.com/docs/v2/components/#datetime
I might sound old, but i am new for ionic 2. i wrote a code in ionic 2 for checkbox and it is working well but how do i retrieve the count of the checked boxes
Below is the code i have.
checklist.ts code
import { Component } from '#angular/core';
import { NavController, NavParams, Alert } from 'ionic-angular';
#Component({
templateUrl: 'build/pages/checklist/checklist.html',
})
export class ChecklistPage {
checklist:any;
constructor(public nav: NavController, public navParams: NavParams) {
this.checklist = this.navParams.get('checklist');
}
addItem(): void {
let prompt = Alert.create({
title: 'Add Item',
message: 'Enter the name of the task for this checklist below:',
inputs:[
{
name: 'name'
}
],
buttons:[
{
text: 'Cancel'
},
{
text: 'Save',
handler: data => {
this.checklist.addItem(data.name);
}
}
]
});
this.nav.present(prompt);
}
toggleItem(item): void {
this.checklist.toggleItem(item);
}
removeItem(item): void {
this.checklist.removeItem(item);
}
renameItem(item): void {
let prompt = Alert.create({
title: 'Rename Item',
message: 'Enter the new name of the task for this checklist below:',
inputs: [
{
name: 'name'
}
],
buttons: [
{
text: 'Cancel'
},
{
text: 'Save',
handler: data => {
this.checklist.renameItem(item,data.name);
}
}
]
});
this.nav.present(prompt);
}
checkallItems(): void {
this.checklist.items.forEach((item) => {
if(!item.checked){
this.checklist.toggleItem(item);
}
});
}
uncheckItems(): void {
this.checklist.items.forEach((item) => {
if(item.checked){
this.checklist.toggleItem(item);
}
});
}
}
checklist.html
<ion-header>
<ion-navbar secondary>
<ion-title>{{checklist.title}} #(checkeditem)/{{checklist.items.length}}</ion-title>
<ion-buttons end>
<button (click)="checkallItems()">
<ion-icon name="checkbox"></ion-icon>
</button>
<button (click)="uncheckItems()">
<ion-icon name="refresh-circle"></ion-icon>
</button>
<button (click)="addItem()">
<ion-icon name="add-circle"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-list no-lines>
<ion-item-sliding *ngFor="let item of checklist.items" class="home-sliding-item">
<ion-item>
<ion-label>{{item.title}}</ion-label>
<ion-checkbox [checked]="item.checked" (click)="toggleItem(item)" class="checklist-item"></ion-checkbox>
</ion-item>
<ion-item-options>
<button light (click)="renameItem(item)">
<ion-icon name="clipboard"></ion-icon>Edit
</button>
<button danger (click)="removeItem(item)">
<ion-icon name="trash"></ion-icon>Delete
</button>
</ion-item-options>
</ion-item-sliding>
</ion-list>
</ion-content>
You can add a method in your ChecklistPage like this:
public getItemsCount(): number {
let count= 0;
for(let i=0; i<this.checklist.items.length; i++) {
if(this.checklist.items[i].checked){
count++;
}
}
return count;
}
Or following the checkallItems() method:
public getItemsCount(): number {
let count= 0;
this.checklist.items.forEach((item) => {
if(item.checked){
count++;
}
});
return count;
}
And then in your view:
<ion-title>{{checklist.title}} #{{getItemsCount()}}/{{checklist.items.length}}</ion-title>