Ionic3 cordova woo-commerce android app freeze while opening product page

#1

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)

app is live on play store search Het Nigeria

below link for code

http://www.mediafire.com/file/4bmk3c3zqkg5poe/grid.html.txt/file

http://www.mediafire.com/file/xd69t7y6mlzl2as/grid.ts.txt/file

http://www.mediafire.com/file/vjfjttb9e6bkqv5/product.html.txt/file

http://www.mediafire.com/file/i4ae4lev1pvqo4a/product.ts.txt/file

Grid.html*************************************************

  <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">&nbsp;•&nbsp;{{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(/&amp;/g, '&') : '';
this.param.id = this.navParams.data.params.id;
this.param.search = this.navParams.data.params.search ? this.navParams.data.params.search.replace(/&amp;/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(/&amp;/g, '&')
  });
  for(let y in this.categories[x].child){
    alert.addInput({
      type: 'radio',
      label: this.categories[x].child[y].name.replace(/&amp;/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});
}

}