I'm trying to implement load more functionality in the half portion of the page.
So I put that code inside the ion-scroll but somehow current implementation is not working i.g. the method is
(ionInfinite)="doInfinite($event)"
is not triggered and loader UI is not rendered. However, the same implementation is working if the content placed in ion-content instead of ion-scroll.
<ion-content padding>
<ion-scroll scrollY="true" id="accountList" class="list-box">
<ion-list >
<ion-item *ngFor="let item of [1,2,3,4,5,6,7,8,9]">
<ion-icon ios="ios-add-circle" md="ios-add-circle" item-start color="secondary"></ion-icon>
Item1
<ion-buttons item-end>
<button ion-button clear icon-only color="orange">
<ion-icon ios="md-create" md="md-create" item-end ></ion-icon>
</button>
<button ion-button clear icon-only color="danger">
<ion-icon ios="md-close" md="md-close" item-end></ion-icon>
</button>
</ion-buttons>
</ion-item>
</ion-list>
<ion-infinite-scroll (ionInfinite)="doInfinite($event)">
<ion-infinite-scroll-content
loadingSpinner="bubbles"
loadingText="Loading more data...">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-scroll>
</ion-content>
Sorry for my bad english, but I resolved this problem by using below code:
<ion-scroll #scrollWeb scrollY="true" class="scroll-y">
<ion-grid>
<ion-row>
<ion-col col-4 col-sm-6 col-md-4 col-lg-4 col-xl-4 *ngFor="let item of items">
<item-card [item]="item"></item-card>
</ion-col>
</ion-row>
</ion-grid>
</ion-scroll>
And on my component:
#ViewChild('scrollWeb') scrollWeb: Scroll;
Added listener on DOM Element to discover if the scroll arrived in the end as follows:
ngAfterViewInit() {
if (this.scrollWeb) {
this.scrollWeb.addScrollEventListener((ev) => {
if ((ev.target.offsetHeight + ev.target.scrollTop) >= ev.target.scrollHeight) {
this.doInfinite(null);
}
});
}
}
In doInfinite function you can omit or show a loader as follows:
if (infiniteScroll !== null) {
infiniteScroll.complete();
}
Ionic-version: 3.9.2
I have a similar problem in the component. My solution was:
Replace <ion-scroll> with <ion-content>
Add overflow: auto; style for <ion-content>
Enjoy virtual scrolling
You need call the $event.complete() method. From the Ionic documentation page of InifniteScroll:
"The expression assigned to the infinite event is called when the user
scrolls to the specified distance. When this expression has finished
its tasks, it should call the complete() method on the infinite scroll
instance."
ion-Scroll doesn't fire scroll events right now, thus ion-infinite-scroll subscription to scroll events is not fired.
You can try to find some workarounds like firing similar event yourself. I just desided to emulate visual similarity in regular ion-content using css for now (not perfect solution).
Link to issue on Ionic Github: https://github.com/ionic-team/ionic/issues/13904
Link to issue on forum: https://forum.ionicframework.com/t/ionscroll-event-doesnt-fire-on-ion-scroll/96188/3
Related
I'm building an Angular app using Ionic. The goal of the app is to keep track of your expenses and to be able to know how much money you have on each of your different accounts. I am using an ion-fab-list to show the different buttons both for adding a transaction and for adding a new bank account. These buttons open different ion-modals. I've already gotten the modal for adding a new transaction to work. However, when I try to add the one for adding a new account I just canĀ“t dismiss the other modal anymore.
This is the HTML (the modal for adding transactions isn't complete since it's pretty long and anything after that can't be causing the issue)
<ion-fab horizontal="end" vertical="bottom" slot="fixed">
<ion-fab-button color="primary" class="">
<ion-icon name="add"></ion-icon>
</ion-fab-button>
<ion-fab-list side="top">
<ion-fab-button id="add-transaction" expand="block" color="primary" data-desc="Add transaction">
<ion-icon name="receipt-outline"></ion-icon>
</ion-fab-button>
<ion-fab-button id="add-account" expand="block" color="primary" data-desc="Add account">
<ion-icon name="card-outline"></ion-icon>
</ion-fab-button>
</ion-fab-list>
</ion-fab>
<ion-modal trigger="add-account">
<ng-template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button (click)="cancel_account()">Cancel</ion-button>
</ion-buttons>
<ion-title>Welcome</ion-title>
<ion-buttons slot="end">
<ion-button (click)="confirm_account()" [strong]="true">Confirm</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
</ng-template>
</ion-modal>
<ion-modal trigger="add-transaction">
<ng-template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button (click)="cancel_transaction()">Cancel</ion-button>
</ion-buttons>
<ion-buttons slot="end">
<ion-button (click)="confirm_transaction()" [strong]="true">Confirm</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
And here's the Typescript (ignore the first 4 rows of the confirm-transaction function since it's only relevant to send the new transactions to the database.)
#ViewChild(IonModal) modal: IonModal;
cancel_transaction(){
this.modal.dismiss('cancel');
}
cancel_account() {
this.modal.dismiss('cancel');
}
async confirm_transaction() {
await this.transactionService.addTransactions(this.new_transaction)
this.getTransactions()
this.getAccounts();
this.modal.dismiss('confirm');
}
I have already tried changing #ViewChild to #ViewChildren as I saw someone suggested in a similar question but it still didn't work. Also, the reason why there's two identical functions for dismissing the modals is because I thought using the same function for both modals was what could be causing this but the issue persisted. Whenever i try to close the modal for adding a transaction it just doesn't work.
Each modal needs its own role (id) and that is then passed to the dismiss method. Like so:
this.modal.dismiss('confirm', 'modal1');
https://ionicframework.com/docs/api/modal#dismiss
This is a side menu on the Ionic web app.
<ion-content>
<ion-list>
<ion-menu-toggle autoHide="false" *ngFor="let p of appPages; let i = index">
<ion-item (click)="selectedIndex = I"
[class.selected]="selectedIndex == i" tappable (click)="goToPage(p)">
<ion-icon slot="start" [name]="p.ionicIcon? p.ionicIcon: ''"></ion-icon>
<ion-label>
{{p.title}}
</ion-label>
</ion-item>
</ion-menu-toggle>
</ion-list>
</ion-content>
</ion-menu>
Doc: https://ionicframework.com/docs/api/item#css-custom-properties
Here I need to give a Hover effect. But it is not working. Key thing here is you can see that I do not use routerLink here. So how can I do that?
I have tried this. But not working.
ion-item:hover {
--background-hover: gray !important;
}
If you read through the docs, you'll see your "tappable" attribute is no long valid.
All you need to do is set button="true" on the ion-item.
<ion-item button="true">
My Item
</ion-item>
https://codepen.io/mhartington/pen/KKVemNx?editors=1000
Also worth noting...
You do not need to use the :hover selector on the element. It should just be
ion-item {
--background-hover: gray;
}
I have this code for multi buttons inside Ngfor and I want just the clicked button to change its color not all of them, how can I do it please?
.html:
<ion-col size="6" *ngFor="let data of dataArray" >
<ion-card>
<ion-card-header>
<ion-button class="fav-icon2" ion-button [color]="ionicNamedColor (click)="changecolor()" >
<ion-icon name="heart"></ion-icon>
</ion-button>
</ion-card-header>
</ion-card>
</ion-col>
.ts:
public ionicNamedColor: string = 'warning';
changecolor() {
if(this.ionicNamedColor === 'warning') {
this.ionicNamedColor = 'primary'
} else {
this.ionicNamedColor = 'warning'
}
}
here you are using the array named dataArray for showing the buttons on the screen.
Add one more property called clicked in the object used in the dataArray.
So whenever you call the method for changeColor, you just check the property clicked and decide whether to change the color or not.
So your file should be updated with the following code:
<ion-col size="6" *ngFor="let data of dataArray" >
<ion-card>
<ion-card-header>
<ion-button class="fav-icon2" ion-button [color]="data.isClicked?'warning':'primary" (click)="data.isClicked = !data.isClicked" >
<ion-icon name="heart"></ion-icon>
</ion-button>
</ion-card-header>
Here there is not need to add anything in your typescript file.
You are iterating over an array through an ngFor loop, means many button elements could get created, but you have only one single variable for the color attribute, thats why changing for one button, shall change colors for all.
Having said that, you'll have to devise a mechanism so that each rendered button elements through ngFor should get its own reference of color variable. Seeing your code, you should either have the color variable inside the dataArray array, or maintain a separate array of string equal in length to dataArray. Something like this..
public colorArr:string[]= [];
//initially I've populated dataArray with initial colors.
public ngOnInit(){
this.dataArray.forEach(x=>this.colorArr.push('warning'));
}
Your HTML would get modified, like this
<ion-col size="6" *ngFor="let data of dataArray; let i = index" >
<ion-card>
<ion-card-header>
<ion-button class="fav-icon2" ion-button [color]="colorArr[i]" (click)="changecolor(i)" >
<ion-icon name="heart"></ion-icon>
</ion-button>
</ion-card-header>
</ion-card>
</ion-col>
And your changeColor mehtod would get modified like this
changecolor(index) {
if(this.colorArr[index] === 'warning') {
this.colorArr[index] = 'primary'
} else {
this.colorArr[index] = 'warning'
}
}
So in essence we are maintaing colors in separate array for each single button element, without affecting original dataArray.
Another approach could be you create a separate component only for button elements, and pass its relevant data through #input decorators. In that case your this approach of single variable would work.
Thanks.
Try this using button index..
<ion-col size="6" *ngFor="let data of dataArray; index as i;" >
<ion-card>
<ion-card-header>
<ion-button
class="fav-icon2"
ion-button [color]="activeIndex==i ? 'warning' : 'primary'
(click)="setIndex(i)" >
<ion-icon name="heart"></ion-icon>
</ion-button>
</ion-card-header>
</ion-card>
</ion-col>
activeIndex;
setIndex(index) {
this.activeIndex = index:
}
Note: you can change color as per the condition..
I have a clarification, Basically i am passing a list from parent page to Ionic modal. In modal, i will iterating over a list. i am basically modifying a property of an object on click of ion-item.
Below is the html code in the modal.
<ion-card *ngFor="let item of items">
<ion-row>
<ion-col size="3">
<ion-img width="80" height="80" [src]="item.imagePath"></ion-img>
</ion-col>
<ion-col size="7" >
<ion-label class="item-name">item.name</ion-label>
<ion-label class="item-price">item.cost</ion-label>
<ion-label class="item-date">item.date</ion-label>
</ion-col>
<ion-col size="2">
<ion-icon class="select-icon" name="add-circle" (click)="updateObj(item)"></ion-icon>
</ion-col>
</ion-row>
</ion-card>
In modal.component.ts
ngOnInit() {
this.items = this.navParams.get("items");
}
dismissModal(){
this.modalCtrl.dismiss();
}
updateObj(object){
if(object){
object.status = true
}
}
i am using navParams to get the list from parent page to the modal. When i click on ion-item i will be calling updateObj method where i am updating the status of object to true. Everything works fine.
But when i update the object in the modal, the original list sent to the modal also gets updated.
Could anyone explain why updating the list in the modal updates the original list. Is it bcoz of using navParams as it referers to the list?
In Parent.component.ts
async openSearchModal(){
const modal = await this.modalCtrl.create({
component: CouponSearchPage,
componentProps: { items: this.itemListData,
}
});
This is how i am passing the list to the modal from parent screen.
When you pass this.itemListData to modal, you are passing the reference of the object.
If you don't want to modify the actual object, you can pass a new object.
Try this:
const modal = await this.modalCtrl.create({
component: CouponSearchPage,
componentProps: { items: { ...this.itemListData},
}
});
[Print screen] [1]: https://i.stack.imgur.com/VWLBX.png
and this is the home.page.html
<ion-header >
<ion-toolbar >
<ion-title>HOME</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<div [innerHTML] id="days"></div>
</ion-content>
Ionic 4 has a bunch of changes and the onClick is no longer valid. You should use <ion-button (click)="myCallback()">