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.
Related
Given the following Toolbar component, I am trying to test the locale changing upon click on menu item ... but the wrapper content is not changing after a mouseover event on the menu selector ...
Toolbar.vue
<template>
<v-toolbar height="80px" fixed>
<v-toolbar-title>
<img src="#/assets/images/app_logo.png" alt="">
<v-menu bottom offset-y open-on-hover class="btn btn--flat" style="margin-bottom: 12px;">
<v-btn id="current-flag" flat slot="activator">
<img :src="flagImage(currentLocaleIndex)" width="24px">
</v-btn>
<v-list>
<v-list-tile v-for="(locale, index) in locales" :key="index" #click="switchLocale(index)">
<div class="list__tile__avatar avatar--tile" #click="switchLocale(index)">
<img :src="flagImage(index)" width="24px">
</div>
<div class="list__tile__title" v-html="flagTitle(index)"></div>
</v-list-tile>
</v-list>
</v-menu>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<!-- MENU HOME-->
<v-btn flat #click="$router.push(menuItems.home.link)">
<v-icon left>{{ menuItems.home.icon }}</v-icon>
<span>{{ menuItems.home.title | translate }}</span>
</v-btn>
<!-- ABOUT HOME-->
<v-btn flat #click="$router.push(menuItems.about.link)">
<v-icon left>{{ menuItems.about.icon }}</v-icon>
<span>{{ menuItems.about.title | translate }}</span>
</v-btn>
</v-toolbar-items>
</v-toolbar>
</template>
<script>
// import i18n from '#/locales'
export default {
name: "Toolbar",
props: ["appName"],
data() {
return {
menuItems: {
home: { icon: "home", title: "Home", link: "/" },
about: { icon: "info", title: "About", link: "/about" }
},
locales: [
{ id: "en", title: "English", flag: "#/assets/images/flag_en_24.png" },
{ id: "fr", title: "Français", flag: "#/assets/images/flag_fr_24.png" },
{ id: "br", title: "Português", flag: "#/assets/images/flag_br_24.png" }
]
};
},
computed: {
currentLocaleIndex: function() {
let index = this.locales.findIndex(o => o.id === this.$i18n.locale);
return index;
},
currentLocaleTitle: function() {
let obj = this.locales.find(o => o.id === this.$i18n.locale);
return obj.title;
},
currentLocaleFlag: function() {
let obj = this.locales.find(o => o.id === this.$i18n.locale);
return obj.flag;
}
},
methods: {
flagImage: function(index) {
return require("#/assets/images/flag_" +
this.locales[index].id +
"_24.png");
},
flagTitle: function(index) {
return this.locales[index].title;
},
switchLocale: function(index) {
this.$i18n.locale = this.locales[index].id;
}
},
mounted() {}
};
</script>
Toobar.spec.je
import Vue from "vue";
import router from "#/router";
import Vuetify from "vuetify";
import i18n from "#/locales";
import { mount, shallowMount } from "#vue/test-utils";
import Toolbar from "#/components/shared/Toolbar.vue";
describe("App.vue", () => {
let wrapper;
beforeEach(() => {
Vue.use(Vuetify);
Vue.filter("translate", function(value) {
if (!value) return "";
value = "lang.views.global." + value.toString();
return i18n.t(value);
});
const el = document.createElement('div');
el.setAttribute('data-app', true);
document.body.appendChild(el);
});
it("should change locale", () => {
// given
wrapper = mount(Toolbar, { router, i18n });
console.log('CURRENT LOCALE INDEX: ', wrapper.vm.currentLocaleIndex);
// console.log(wrapper.html());
const currentFlagBtn = wrapper.find("#current-flag");
console.log(currentFlagBtn.html())
currentFlagBtn.trigger('mouseover');
wrapper.vm.$nextTick( () => {
console.log(wrapper.html());
// const localesBtn = wrapper.findAll("btn");
});
// when
// localesBtn.at(1).trigger("click"); // French locale
// then
// expect(wrapper.wrapper.vm.currentLocaleIndex).toBe(1);
});
});
console.log
console.log tests/unit/Toolbar.spec.js:32
CURRENT LOCALE INDEX: 0
console.log tests/unit/Toolbar.spec.js:35
<button type="button" class="v-btn v-btn--flat" id="current-flag"><div class="v-btn__content"><img src="[object Object]" width="24px"></div></button>
console.log tests/unit/Toolbar.spec.js:38
<nav class="v-toolbar v-toolbar--fixed" style="margin-top: 0px; padding-right: 0px; padding-left: 0px; transform: translateY(0px);">
<div class="v-toolbar__content" style="height: 80px;">
<div class="v-toolbar__title">
<img src="#/assets/images/app_logo.png" alt="">
<div class="v-menu btn btn--flat v-menu--inline" style="margin-bottom: 12px;">
<div class="v-menu__activator">
<button type="button" class="v-btn v-btn--flat" id="current-flag">
<div class="v-btn__content">
<img src="[object Object]" width="24px">
</div>
</button>
</div>
</div>
</div>
<div class="spacer"></div>
<div class="v-toolbar__items">
<button type="button" class="v-btn v-btn--flat">
<div class="v-btn__content">
<i aria-hidden="true"class="v-icon v-icon--left material-icons">home</i>
<span>Home</span>
</div>
</button>
<button type="button" class="v-btn v-btn--flat">
<div class="v-btn__content">
<i aria-hidden="true" class="v-icon v-icon--left material-icons">info</i>
<span>About</span>
</div>
</button>
</div>
</div>
</nav>
I found a solution, but maybe someone can explain why :
btnFlags.at(1).vm.$emit('click'); // OK
and
btnFlags.at(1).trigger('click'); // NOT OK
this is the spec which is running fine :
import Vue from "vue";
import router from "#/router";
import Vuetify from "vuetify";
import i18n from "#/locales";
import { mount, shallowMount } from "#vue/test-utils";
import Toolbar from "#/components/shared/Toolbar.vue";
describe("Toolbar.vue", () => {
let wrapper;
beforeEach(() => {
Vue.use(Vuetify);
Vue.filter("translate", function(value) {
if (!value) return "";
value = "lang.views.global." + value.toString();
return i18n.t(value);
});
const el = document.createElement('div');
el.setAttribute('data-app', true);
document.body.appendChild(el);
});
it("should change locale", async () => {
// given
wrapper = shallowMount(Toolbar, { router, i18n });
console.log('CURRENT LOCALE INDEX: ', wrapper.vm.currentLocaleIndex);
const btnFlags = wrapper.findAll("v-list-tile-stub");
// when
btnFlags.at(1).vm.$emit('click');
await wrapper.vm.$nextTick();
// then
console.log('NEW LOCALE INDEX: ', wrapper.vm.currentLocaleIndex);
expect(wrapper.vm.currentLocaleIndex).toBe(1);
});
});
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>
hi I'am new in ionic and i working with ionic 2. my problem is :
I have write the functions in my about.ts this function run well (i have test this in the constructor of the page) but when i call this in about.html, nothing of this functions run. (sorry i don't speak english well)
that is my about.ts
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import {Contacts, Contact} from 'ionic-native';
import { AlertController } from 'ionic-angular';
//, ContactField
#Component({
selector: 'page-about',
templateUrl: 'about.html'
})
export class AboutPage {
private customColor:string[] = ["#f44336", "#3f51b5", "#2196f3", "#009688", "#4caf50"];
// index qui nous permet de changer de couleur
private indexColor:number = 0;
// les contactes trouvés
public allContacts:Contact[];
public findItem:string;
constructor(public navCtrl: NavController,public alertCtrl: AlertController) {
this.findContact('');
this.openModal();
}
/** Suppression d'un contact */
public delete(contactToDelete:Contact):void{
contactToDelete.remove().then(()=>this.findContact(''));
}
public getCustomColor():string{
let color:string = this.customColor[this.indexColor];
this.indexColor++;
if(this.indexColor === 5){
this.indexColor = 0;
}
return color;
}
/** Ouverture de la modale pour la création de contact */
public openModal():void{
//let modal = Modal.create(CreateContact);
// this._navController.present(modal);
// modal.onDismiss(data => {
// this.allContacts.push(data);
// });
let alert = this.alertCtrl.create({
title: 'soty',
subTitle: 'rost',
buttons: ['OK']
});
alert.present();
}
/** Méthode pour effectuer la recherche de contact */
public findContact(value:any){
let alert = this.alertCtrl.create({
title: value,
subTitle: value,
buttons: ['OK']
});
alert.present();
let fn = value === undefined ? '' :value;
Contacts.find(['displayName', 'phoneNumbers'], {
filter:fn,
hasPhoneNumber:true
}).then(data => {
this.allContacts = data;
});
}
/** Création des initiales sur 2 lettres */
public getCustomInitial(value):string{
let names:string[] = value.split(' ');
let firstName = '';
let secondName = '';
if(names[0] != undefined){
firstName = names[0].substring(0,1);
}
if(names[1] != undefined){
secondName = names[1].substring(0,1);
}
return firstName + secondName;
}
}
that is my about.html
<ion-header>
<ion-navbar>
<ion-title>
Gestion des contacts
</ion-title>
<ion-buttons start>
<button (click)="openModal()">
<ion-icon ios="ios-add" md="md-add"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content padding class="page1">
<ion-item>
<ion-input
type="text"
placeholder="rechercher"
[(ngModel)]="findItem"
(Change)="findContact($event)"></ion-input>
</ion-item>
<ion-list>
<ion-item-sliding *ngFor="let contact of allContacts">
<ion-item class="bloc-contact">
<ion-avatar item-left>
<span
class="initial" [style.background] = "getCustomColor()">
{{ getCustomInitial(contact.displayName) }}
</span>
</ion-avatar>
<h2>{{contact.displayName}}</h2>
<div *ngFor="let phone of contact.phoneNumbers">
<ion-item *ngIf="phone.type == 'mobile'" class="line">
<ion-icon ios="ios-phone-portrait" md="md-phone-portrait"></ion-icon>
Mobile
<ion-badge teal item-right>{{phone.value}}</ion-badge>
</ion-item>
<ion-item *ngIf="phone.type == 'home'" class="line">
<ion-icon ios="ios-home" md="md-home"></ion-icon>
Home
<ion-badge green item-right>{{phone.value}}</ion-badge>
</ion-item>
</div>
</ion-item>
<ion-item-options>
<button danger (click) = "delete(contact)">
<ion-icon name="trash"></ion-icon>
Delete
</button>
</ion-item-options>
</ion-item-sliding>
</ion-list>
</ion-content>
somebody can help me please
there is no problem with openModal() and the way you call it; but you must use this for your input event:
<ion-input type="text" placeholder="rechercher" [(ngModel)]="findItem" (input)='findContact($event.target.value)'>
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>