problem in Ionic3 cordova wordpress woo-commerce android app, from home.html page when tapping on a product many time it open product page perfectly but some time it freeze while opening product page, can not go back.
same problem from grid.html page when tapping on a product many time it open product page perfectly but some time it freeze while opening product page, can not go back.
some time it freeze on tapping after 2-3 products, some time it freeze on tapping after 7-8 products , open below link for video (live demo of problem)
<div class="filter">
<ion-scroll scrollX="true" class="item filter">
<ion-row nowrap>
<ion-col col-auto no-padding>
<button ion-button small round outline (click)="showCategory()">{{param.name || ('CATEGORIES' |
translate)}}</button>
</ion-col>
<ion-col col-auto no-padding *ngFor="let x of attributes">
<button ion-button small round outline (click)="showFilter(x)">
{{x.name}}
<span *ngIf="param.attribute_term && param.attribute==x.slug"> • {{param.attribute_term.split(",").length}}</span>
</button>
</ion-col>
<!--<ion-col col-auto no-padding>-->
<!--<button ion-button small round outline (click)="showSort()">Sort</button>-->
<!--</ion-col>-->
</ion-row>
</ion-scroll>
</div>
</div>
{{ 'EMPTY' | translate}}
<button class="fav" (click)="setFav(x)" ion-button clear icon-only>
<ion-icon *ngIf="x.variations.length == 0" no-padding name="heart{{!wishlist.isFav(x) ? '-outline' : ''}}"></ion-icon>
</button>
<div text-left class="product-item" tappable (click)="goTo('ProductPage', x)">
<div class="img" [ngStyle]="{'background-image': 'url(' + x.images[0].src +')'}">
<ion-badge *ngIf="x.on_sale">{{x | discount}}</ion-badge>
</div>
<h5 [innerHTML]="x.name"></h5>
<div class="price">
<span class="disc" *ngIf="x.on_sale">{{x.regular_price | money}}</span>
{{x.price | money}}
</div>
<ion-row no-padding class="reviews" *ngIf="x.rating_count">
<ion-col col-auto no-padding>
<ion-rating *ngIf="x.average_rating" item-start [numStars]="5" [readOnly]="true" [value]="x.average_rating">
</ion-rating>
<span *ngIf="x.rating_count">{{x.rating_count}}</span>
</ion-col>
</ion-row>
</div>
<ion-row class="remove">
<ion-col>
<ng-container *ngIf="x.in_stock || !x.manage_stock">
<button tappable (click)="addToCart(x)" ion-button small block>{{ 'TO_CART' | translate}}</button>
</ng-container>
<ng-container *ngIf="!x.in_stock && x.manage_stock">
<button tappable ion-button small block disabled>Out of Stock</button>
</ng-container>
</ion-col>
</ion-row>
</ion-col>
Grid.ts******************************************************************
import { Component } from ‘@angular/core’;
import { StatusBar } from ‘@ionic-native/status-bar’;
import { Keyboard } from ‘@ionic-native/keyboard’;
import { IonicPage, NavController, Platform, AlertController, ModalController, NavParams, ActionSheetController } from ‘ionic-angular’;
import { WooCommerceProvider, CartProvider, ToastProvider, LoadingProvider, WishlistProvider } from ‘…/…/…/providers/providers’;
import { TranslateService } from ‘@ngx-translate/core’;
import { FormGroup, FormBuilder } from ‘@angular/forms’;
@IonicPage()
@Component({
selector: ‘page-product-grid’,
templateUrl: ‘grid.html’,
})
export class ProductGridPage {
private search : FormGroup;
showCancel: boolean;
param: any = {};
WooCommerce: any;
subcategory: any;
products: any = ;
attributes: any = ;
categories: any;
min: number;
max: number;
page: number;
more: boolean;
constructor(private statusBar: StatusBar, private cart: CartProvider, private platform: Platform, private keyboard: Keyboard, public toast: ToastProvider, private alert: AlertController, fb: FormBuilder, private translate: TranslateService, private loader: LoadingProvider, public navCtrl: NavController, public modal: ModalController, public navParams: NavParams, private woo: WooCommerceProvider, public wishlist: WishlistProvider, public actionSheetCtrl: ActionSheetController) {
this.page = 1;
console.log(this.navParams.data.params);
this.param.name = this.navParams.data.params.name ? this.navParams.data.params.name.replace(/&/g, '&') : '';
this.param.id = this.navParams.data.params.id;
this.param.search = this.navParams.data.params.search ? this.navParams.data.params.search.replace(/&/g, '&') : '';
this.param.per_page = 10;
this.search = fb.group({
name: this.param.name || this.param.search
});
this.woo.getSubCategories().then( val=> {
this.categories = val;
});
if(this.param.id) this.loadSubCategory(this.param.id);
this.woo.getAttributes().then((tmp) => {
for(let i in tmp){
this.attributes[i] = tmp[i];
this.woo.getAttributeTerms(tmp[i].id).then((val) => {
if(val){
for(let j in val){
val[j].checked = false;
this.attributes[i].options = val;
}
}
})
}
});
// this.param.min = this.min;
// this.param.max = this.max;
this.loadProducts(this.param);
// if(this.platform.is(‘cordova’))
// this.keyboard.show();
}
ionViewWillEnter(){
if (this.platform.is(‘cordova’))
this.statusBar.styleDefault();
}
loadSubCategory(id){
this.woo.getCategories(id).then( y=> {
this.subcategory = y;
});
}
loadProducts(x: any){
this.loader.present();
this.woo.getAllProducts(1, x.id, x.search, null, null, x.per_page, null, x.order, x.attribute, x.attribute_term).then((val) => {
this.products = val;
if (this.products.length == x.per_page)
this.more = true;
this.loader.dismiss();
}, (err) => {
console.log(err)
this.loader.dismiss();
});
}
loadMoreProducts(event){
this.page++;
this.woo.getAllProducts(this.page, this.param.id, this.param.search, null, null, this.param.per_page, null, this.param.order, this.param.attribute, this.param.attribute_term).then((val) => {
let temp = val;
event.complete();
this.products = this.products.concat(temp);
if (temp.length < this.param.per_page){
this.more = false;
event.enable(false);
this.translate.get(['NOMORE']).subscribe( x=> {
this.toast.show(x.NOMORE);
});
}
}, (err) => {
console.log(err)
});
}
showSort() {
this.translate.get([‘SORT’, ‘NEWEST’, ‘OLDEST’, ‘CANCEL’]).subscribe( x=> {
this.actionSheetCtrl.create({
title: x.SORT,
buttons: [{
text: x.NEWEST,
handler: () => {
this.param.order = ‘desc’;
this.loadProducts(this.param);
}
},{
text: x.OLDEST,
handler: () => {
this.param.order = ‘asc’;
this.loadProducts(this.param);
}
},{
text: x.CANCEL,
role: ‘cancel’
}
]
}).present();
});
}
viewCart(){
this.modal.create(‘MiniCartPage’, {}, { cssClass: ‘inset-modal’ }).present();
}
addToCart(product: any){
this.translate.get([‘ADDED_TO_CART’]).subscribe( x=> {
this.cart.post(product);
this.toast.show(x.ADDED_TO_CART);
});
this.viewCart();
}
setFav(product: any){
this.translate.get([‘REMOVE_WISH’, ‘ADDED_WISH’]).subscribe( x=> {
let msg = product.isFav ? x.REMOVE_WISH : x.ADDED_WISH;
this.wishlist.post(product);
product.isFav = product.isFav ? false : true;
this.toast.show(msg);
});
}
showFilter(attribute: any){
this.loader.present();
let alert = this.alert.create();
alert.setTitle(attribute.name);
this.translate.get([‘FILTER_DESC’], {value: attribute.name}).subscribe( x=> {
alert.setSubTitle(x.FILTER_DESC);
});
for(let x in attribute.options){
alert.addInput({
type: 'checkbox',
label: attribute.options[x].name,
value: attribute.options[x].id,
checked: this.param.attribute_term ? this.param.attribute_term.includes(attribute.options[x].id) : false
});
}
this.translate.get(['CANCEL']).subscribe( x=> {
alert.addButton(x.CANCEL);
});
alert.addButton({
text: 'Ok',
handler: (data: any) => {
this.param.attribute = attribute.slug;
this.param.attribute_term = data.join();
this.loadProducts(this.param);
}
});
alert.present();
this.loader.dismiss();
}
showCategory(){
this.loader.present();
let alert = this.alert.create();
this.translate.get([‘CATEGORIES’, ‘CATEGORIES_DESC’]).subscribe( x=> {
alert.setTitle(x.CATEGORIES);
alert.setSubTitle(x.CATEGORIES_DESC);
});
for(let x in this.categories){
alert.addInput({
disabled: true,
type: 'radio',
label: this.categories[x].name.replace(/&/g, '&')
});
for(let y in this.categories[x].child){
alert.addInput({
type: 'radio',
label: this.categories[x].child[y].name.replace(/&/g, '&')+' ('+this.categories[x].child[y].count+')',
value: this.categories[x].child[y],
checked: this.categories[x].child[y].id == this.param.id ? true : false
});
}
}
this.translate.get(['CANCEL']).subscribe( x=> {
alert.addButton(x.CANCEL);
});
alert.addButton({
text: 'Ok',
handler: (data: any) => {
this.param.id = data.id;
this.param.name = data.name;
this.loadSubCategory(this.param.id);
this.loadProducts(this.param);
}
});
alert.present();
this.loader.dismiss();
}
submit(){
this.param.search = this.search.value.name;
this.loadProducts(this.param);
}
reset(e){
this.param.search = ‘’;
this.search.reset();
}
backToRoot(){
this.navCtrl.pop();
}
goTo(page, params){
this.navCtrl.push(page, {params: params});
}
}
Product.html*****************************************************
<ion-list-header mode="md" no-margin no-padding margin-left *ngIf="product.variations.length > 0">
{{'VARIATION' | translate}}
</ion-list-header>
<ion-list mode="md" radio-group (ionChange)="setVariation($event)" padding-bottom no-margin margin-horizontal margin-bottom *ngIf="product.variations.length > 0">
<ion-item mode="ios" *ngFor="let x of product.variations" no-padding>
<ion-label>
<span *ngFor="let y of x.attributes">
{{y.name}}: {{y.option}}
</span>
</ion-label>
<ion-radio mode="ios" value="{{x | json}}"></ion-radio>
</ion-item>
</ion-list>
<ion-list mode="md" class="specs">
<ion-list-header mode="md" no-margin no-padding margin-left>
{{'SPECIFICATION' | translate}}
</ion-list-header>
<ion-item>
<ion-grid no-padding>
<ion-row no-padding>
<ion-col col-4 no-padding>Category</ion-col>
<ion-col col-8 no-padding>
<span *ngFor="let cat of product.categories">{{cat.name}}</span>
</ion-col>
</ion-row>
<!--ion-row no-padding *ngIf="product.total_sales">
<ion-col col-4 no-padding>Total Sales</ion-col>
<ion-col col-8 no-padding>
{{product.total_sales}}
</ion-col>
</ion-row-->
<ion-row no-padding *ngIf="product.sku">
<ion-col col-4 no-padding>SKU</ion-col>
<ion-col col-8 no-padding>
{{product.sku}}
</ion-col>
</ion-row>
<ion-row no-padding *ngIf="product.in_stock">
<ion-col col-4 no-padding>Stock</ion-col>
<ion-col col-8 no-padding>
{{product.stock_quantity}}
</ion-col>
</ion-row>
<ion-row no-padding *ngIf="product.weight">
<ion-col col-4 no-padding>Weight</ion-col>
<ion-col col-8 no-padding>
{{product.weight}}
</ion-col>
</ion-row>
<ion-row no-padding *ngFor="let att of product.attributes">
<ion-col col-4 no-padding>{{ att.name}}</ion-col>
<ion-col col-8 no-padding *ngIf="!att.options">
{{att.option}}
</ion-col>
<ion-col col-8 no-padding *ngIf="att.options">
<span *ngFor="let option of att.options"> {{ option }}</span>
</ion-col>
</ion-row>
</ion-grid>
</ion-item>
</ion-list>
<ion-list mode="md" *ngIf="product.description">
<ion-list-header mode="md" no-margin no-padding margin-left margin-top>
{{'DESCRIPTION' | translate}}
</ion-list-header>
<ion-item mode="md">
<div [innerHTML]="product.description"></div>
</ion-item>
</ion-list>
<ion-list-header mode="md" no-margin no-padding margin-left *ngIf="product.rating_count > 0">
{{'REVIEW' | translate}}
</ion-list-header>
<ion-list no-margin margin-horizontal padding-bottom *ngIf="product.rating_count > 0">
<ion-item *ngFor="let x of product.reviews" no-padding>
<ion-row no-padding>
<ion-col col-4>
<div>{{x.name}}</div>
<div class="ago">{{x.date_created | moment:"ago" | lowercase}}</div>
<ion-rating *ngIf="x.rating"
[numStars]="5"
[readOnly]="true"
[value]="x.rating">
</ion-rating>
</ion-col>
<ion-col col-8>
{{x.review}}
</ion-col>
</ion-row>
</ion-item>
</ion-list>
<div class="product-slide">
<ion-list-header mode="md" no-margin no-padding margin-left margin-bottom>
{{'RELATED' | translate}}
</ion-list-header>
<ion-slides margin-bottom spaceBetween="10" slidesPerView="2.5">
<ion-slide *ngFor="let y of product.related">
<button class="fav" tappable (click)="setFav(y)" ion-button clear icon-only>
<ion-icon *ngIf="y.variations.length == 0" no-padding name="heart{{!wishlist.isFav(y) ? '-outline' : ''}}"></ion-icon>
</button>
<div text-left class="product-item" tappable (click)="goTo('ProductPage', y)">
<div class="img" [ngStyle]="{'background-image': 'url(' + y.images[0].src +')'}">
<ion-badge *ngIf="y.on_sale">{{y | discount}}</ion-badge>
</div>
<h5 [innerHTML]="y.name"></h5>
<div class="price" *ngIf="y.price">
<span class="disc" *ngIf="y.on_sale">{{y.regular_price | money:app}}</span>
{{y.price | money:app}}
</div>
<ion-row no-padding class="reviews" *ngIf="y.rating_count">
<ion-col col-auto no-padding>
<ion-rating *ngIf="y.average_rating" item-start
[numStars]="5"
[readOnly]="true"
[value]="y.average_rating">
</ion-rating>
<span *ngIf="y.rating_count">{{y.rating_count}}</span>
</ion-col>
</ion-row>
</div>
</ion-slide>
</ion-slides>
</div>
</div>
<ion-footer *ngIf=“product.price”>
<h5 *ngIf=“product.price”>
<span class=“disc” *ngIf=“product.on_sale”>{{product.regular_price | money:app}}
{{product.price | money:app}}
<ion-row no-padding class=“reviews” *ngIf=“product.rating_count”>
<ion-rating *ngIf=“product.average_rating” item-start
[numStars]=“5”
[readOnly]=“true”
[value]=“product.average_rating”>
<span *ngIf=“product.rating_count”>{{product.rating_count}}
<ng-container *ngIf=“product.in_stock || !product.manage_stock”>
<button ion-button block tappable (click)=“openModal(‘MiniCartPage’)”>{{‘TO_CART’ | translate}}
<ng-container *ngIf="!product.in_stock && product.manage_stock">
Out of Stock
Product.ts*******************************************************
import { Component } from ‘@angular/core’;
import { IonicPage, NavController, AlertController, Platform, ModalController, NavParams } from ‘ionic-angular’;
import { WishlistProvider, SettingsProvider, LoadingProvider, ToastProvider, WooCommerceProvider, HistoryProvider } from ‘…/…/providers/providers’;
import { SocialSharing } from ‘@ionic-native/social-sharing’;
import { TranslateService } from ‘@ngx-translate/core’;
@IonicPage()
@Component({
selector: ‘page-product’,
templateUrl: ‘product.html’,
})
export class ProductPage {
product: any = {
variations:
};
variations: any = ;
reviews: any = ;
related: any = ;
isSetVariation: boolean = false;
app: any;
constructor(private history: HistoryProvider, private settings: SettingsProvider, private alert: AlertController, private platform: Platform, private socialSharing: SocialSharing, private translate: TranslateService, private toast: ToastProvider, private wishlist: WishlistProvider, private navCtrl: NavController, private loader: LoadingProvider, private modal: ModalController, private navParam: NavParams, private woo: WooCommerceProvider) {
this.loader.present();
this.settings.load().then( (x)=> {
this.app = x.settings;
this.product = this.navParam.data.params;
this.history.post(this.product);
if(this.product.variations.length > 0){
this.woo.getProductVariations(this.product.id).then( (val) => {
this.product.variations = val;
})
}
if(this.product.rating_count > 0){
this.woo.getProductReviews(this.product.id).then( (val) => {
this.product.reviews = val;
this.loader.dismiss();
})
}
this.product.related = this.woo.getProductRelated(this.product.related_ids);
this.loader.dismiss();
})
}
ionViewWillEnter(){
}
setVariation(e){
let x = JSON.parse(e);
this.product.variation_id = x.id;
this.product.price = x.price;
this.product.regular_price = x.regular_price;
this.product.on_sale = x.on_sale;
this.product.in_stock = x.in_stock;
this.product.stock_quantity = x.stock_quantity;
this.product.attributes = x.attributes;
this.isSetVariation = true;
}
viewCart(){
this.modal.create(‘MiniCartPage’, {}, { cssClass: ‘inset-modal’ }).present();
}
openModal(pageName) {
if(this.product.variations.length > 0 && !this.isSetVariation){
this.translate.get([‘SELECT_VARIATION’]).subscribe( x=> {
this.toast.show(x.SELECT_VARIATION);
});
}else{
this.modal.create(pageName, {product: this.product}, { cssClass: ‘inset-modal’ }).present();
this.translate.get([‘ADDED_TO_CART’]).subscribe( x=> {
this.toast.show(x.ADDED_TO_CART);
});
}
}
setFav(product: any){
this.translate.get([‘REMOVE_WISH’, ‘ADDED_WISH’]).subscribe( x=> {
let msg = product.isFav ? x.REMOVE_WISH : x.ADDED_WISH;
this.wishlist.post(product);
product.isFav = product.isFav ? false : true;
this.toast.show(msg);
});
}
share(product: any){
// console.log(product);
if (!this.platform.is(‘cordova’)) {
this.translate.get([‘OK’, ‘ONLY_DEVICE’, ‘ONLY_DEVICE_DESC’]).subscribe( x=> {
this.alert.create({
title: x.ONLY_DEVICE,
message: x.ONLY_DEVICE_DESC,
buttons: [{
text: x.OK
}]
}).present();
return false;
});
}else{
let img = [];
for(let i in product.images)
img.push(product.images[i].src);
this.socialSharing.share(product.name, product.name, img, product.permalink).then((x) => {
console.log(x);
this.toast.show('Successfully shared');
}).catch((err) => {
console.log(err);
});
}
}
goTo(page: string, params: any){
this.navCtrl.push(page, {params: params});
}
}