I am making an internal live chat system using Firebase. I make this call to get a list of all chat messages:
firebase.database().ref('chatrooms/'+this.roomkey+'/chats').on('value', resp => {
this.chats = [];
this.chats = snapshotToArray(resp);
setTimeout(() => {
if(this.content._scroll) { this.content.scrollToBottom(0); }
}, 1000);
});
In my view I have this HTML to loop through the chats:
<ion-content>
<ion-list>
<ion-item *ngFor="let chat of chats" no-lines>
<div class="chat-status" text-center *ngIf="chat.type==='join'||chat.type==='exit';else message">
<span class="chat-date">{{chat.sendDate | date:'short'}}</span>
<span class="chat-content-center">{{chat.message}}</span>
</div>
<ng-template #message>
<div class="chat-message" text-right *ngIf="chat.user === nickname">
<div class="right-bubble">
<span class="msg-name">Me</span>
<span class="msg-date">{{chat.sendDate | date:'short'}}</span>
<p text-wrap>{{chat.message}}</p>
</div>
</div>
<div class="chat-message" text-left *ngIf="chat.user !== nickname">
<div class="left-bubble">
<span class="msg-name">{{chat.user}}</span>
<span class="msg-date">{{chat.sendDate | date:'short'}}</span>
<p text-wrap>{{chat.message}}</p>
</div>
</div>
</ng-template>
</ion-item>
</ion-list>
</ion-content>
And here is my relevant CSS:
ion-content {
height: 100%;
overflow: hidden;
.item-md, .item-ios {
background: none;
}
}
There are currently 30 chat messages. They are loaded from Firebase and then after a second, when the setTimeout finishes, the user is automatically scrolled to the bottom of the page so they can see the most recent message. This makes the page load a bit odd with the jump down to the bottom of the page after a second.
Is there any way to replace the timeout with something that will achieve the goal of the user initially seeing the most recent messages? Maybe there is some trigger that can be made that detects that chats has changed in the view and then does the scroll? This would seem better than a fixed 1 second pause?
You could scroll to the bottom of the list when changes to the list of chats are detected:
Associate a template reference variable to the ion-item elements (e.g. #chatItems)
Use ViewChildren to get the QueryList of ion-item elements
In ngAfterViewInit, subscribe to the QueryList.changes event
Scroll to the bottom of the list when the list changes
<ion-content>
<ion-list>
<ion-item #chatItems *ngFor="let chat of chats" no-lines>
...
</ion-item>
</ion-list>
</ion-content>
export class MyComponent {
#ViewChildren("chatItems") chatItems: QueryList<any>;
ngAfterViewInit() {
this.scrollContentToBottom();
this.chatItems.changes.subscribe(() => {
this.scrollContentToBottom();
});
}
scrollContentToBottom() {
if(this.content._scroll) {
this.content.scrollToBottom(0);
}
}
...
}
Note: I used QueryList<any> because I don't know the ion-item component type. You can put the appropriate type if you know what it is.
Related
I am trying to implement an ion-list with ion-items that are swipable but don't have to be clicked on the side to trigger an event.
It should work like like the default contacts app on Samsung phones, where you can either swipe left to call or right to send a SMS.
The list in the parent page looks like this:
<ion-list *ngFor="let person of persons | filter:searchTerm">
<app-person-entry [person]="person" (click)="openModal(person)"></app-person-entry>
</ion-list>
The person-entry component looks like this:
<ion-item>
<ion-avatar slot="start">
<img src={{person.icon}}>
</ion-avatar>
<div>
<div class="container">
<ion-label>{{person.lastname}}</ion-label>
<ion-label>{{person.firstname}}</ion-label>
</div>
<div class="container">
<ion-label>{{person.postalCode}}</ion-label>
<ion-label>{{person.city}}</ion-label>
<ion-label>{{person.address}}</ion-label>
</div>
</div>
</ion-item>
you can use ion-item-sliding.
e.g:
<ion-list>
<ion-item-group #myItemsId>
<ion-item-sliding (ionSwipe)="swipeEvent($event, myItemsId)">
<ion-item-options side="start">
<ion-item-option>CALL</ion-item-option>
</ion-item-options>
<ion-item>
<ion-label>Item Options</ion-label>
</ion-item>
<ion-item-options side="end">
<ion-item-option>SMS</ion-item-option>
</ion-item-options>
</ion-item-sliding>
</ion-item-group>
</ion-list>
.ts:
swipeEvent($event, item) {
console.log($event)
if ($event.detail.side == 'start') {
console.log('call now');
this.closeAllItems(item)
} else {
console.log('SMS now');
this.closeAllItems(item)
}
}
closeAllItems(item) {
let a = Array.prototype.slice.call(item.el.children)
a.map((val) => {
val.close();
})
}
I want to catch scrolling event of list component in ionic3 as in this example:
<ion-content on-scroll = "scrolling()" on-scroll-complete = "scrollComplete()">
<ion-list>
<ion-item ng-repeat="item in items"
item="item"
href="#/item/{{item.id}}">
Item {{ item.id }}
</ion-item>
</ion-list>
</ion-content>
https://codepen.io/etipirev/pen/aNYNpy?editors=1111
as it is seemed it is working in ionic 1, but not in ionic 3? i havent found any event description in ionic docs. is it possible to catch scrolling of list items in ionic 3?
The syntax is different in Ionic2/3. Here's how it should be:
<ion-content (ionScroll)="scrolling($event)" (ionScrollEnd)="scrollComplete($event)">
<ion-list>
...
</ion-list>
</ion-content>
then in your ts file
constructor(){}
scrolling(event) {
// your content here for scrolling
}
scrollComplete(event) {
// your content here of scroll is finished
}
}
I'm trying to implement infinite scroll in my app but i'm finding difficulties. currently my json file has 30 records in it and when the page loads up, every data show up on the data. what i want to achieve is on the page load it show only show up 5 of the data ans when the user scrolls to the buttom the infinite scroll takes over and loads another 5 of the data and keep on repeating.
HTML
<ion-content>
<div class="list card has-subheader" ng-repeat="item in feeds track by item.u_pic_id">
<div class="item item-avatar">
<img src="../usr_up_img/{{item.profile_pix}}">
<h2><a class="mylinks" href="#/tab/source/{{item.profile_id}}">{{item.fname}} {{item.lname}}</a></h2>
<p>November 05, 1955</p>
</div>
<div class="item item-body">
<img class="full-image" src="../images/{{item.profile_pix}}">
<p>
This is a "Facebook" styled Card. The header is created from a Thumbnail List item,
the content is from a card-body consisting of an image and paragraph text. The footer
consists of tabs, icons aligned left, within the card-footer.
</p>
<p>
{{item.love_total}} Loves
{{item.com_total}} Comments
</p>
</div>
</div>
<ion-infinite-scroll
on-infinite="loadmore()"
distance="1%">
</ion-infinite-scroll>
</ion-content>
JS
.controller('feedsctrl',['$scope','$http',function($scope,$http){
$scope.feeds = [];
$scope.loadmore=function() {
var params = {};
if($scope.feeds.length > 0) {
params['after']=$scope.feeds[$scope.feeds.length - 1].profile_id;
}
$http.get('http://localhost/myapp/app_ion/feeds.php').success(function(data){
$scope.feeds=console.log(data) ;
$scope.feeds=data;
$scope.$broadcast('scroll.infiniteScrollComplete');
});
}
}])
any help on how to get this working?
try this
.controller('feedsctrl',['$scope','$http',function($scope, $http) {
$scope.items = [];
$scope.loadMore = function() {
$http.get('http://localhost/myapp/app_ion/feeds.php').success(function(items) {
$scope.items.push(items);
$scope.$broadcast('scroll.infiniteScrollComplete');
});
};
$scope.$on('$stateChangeSuccess', function() {
$scope.loadMore();
});
}])
This is a example http://codepen.io/elm/pen/Becqp
If you need more help doc
I need to remove an ionic 2 card when someone clicks on the trash icon. The code I have so far gives a querySelector is null error when I run it.
The view html looks like this:
<ion-card *ngFor="#mediaItem of mediaItems" id="item{{mediaItem.id}}" class="media-item">
<ion-card-header class="title-header">
<div class="title-item">
{{mediaItem.title}}
</div>
<ion-icon name="trash" class="bookmark_trash_icon" (click)="removeItem(mediaItem.id)"></ion-icon>
</ion-card-header>
<ion-card-content class="outer-content" >
<img src='{{mediaItem.url}}'>
</ion-card-content>
<ion-item class="bookmark-media-item">
<!-- <button (click)="topup(mediaItem)" clear item-left> -->
<div style="float:left;">
<ion-icon name="heart"></ion-icon>
{{mediaItem.liked}}
<ion-icon name="close-circle"></ion-icon>
{{mediaItem.disliked}}
</div>
<a (click)="showUserProfile(mediaItem.owner, mediaItem.username)" style="float:left;">
{{mediaItem.username}}
</a>
<div style="float:right;">
<img src="img/tiny-v.png" class="bookmark-v-icon">
{{mediaItem.credits_left}}
</div>
</ion-item>
</ion-card>
My controller javascript code looks like this:
removeItem(theItemID) {
let cardToHide = '#item'+theItemID;
document.querySelector(cardToHide).style.display = 'none';
}
The error I get is
querySelector is null
You can send the object instead of the id by changing that part of the code:
(click)="removeItem(mediaItem)"
And then find that object in you mediaItems array and delete it from there. Then your view will be automatically updated.
First get the index of that object in the array, and then you can use the mediaItems.splice(index, 1) to delete it from the array:
removeItem(theItem) {
let index = this.mediaItems.indexOf(theItem);
this.mediaItems.splice(index,1);
}
I set up a basic example with Ionic Popover. However, when I open the popover, the opacity stays at zero, preventing the popover from showing. I know the method openPopover is called because I receive the opened console log in my web console. If I remove the opacity property from the console, the popover displays.
My controller..
angular.module('search')
.controller('SearchResultsController', searchResultsController)
searchResultsController.$inject = ['$ionicPopover', '$scope'];
function searchResultsController($ionicPopover, $scope) {
var vm = this;
vm.openPopover = openPopover;
activate();
function activate( ) {
$ionicPopover.fromTemplateUrl('/templates/search/filter-popover.html', {
scope: $scope
}).then(function(popover) {
console.log(popover)
vm.popover = popover;
});
}
function openPopover( $event ) {
console.log("opened")
vm.popover.show($event);
}
}
My view page...
<ion-view hide-nav-bar="true">
<signed-in-header></signed-in-header>
<ion-content class="padding has-header">
<div class="row">
<div class="col col-75 text-left">
<div>4 RESULTS FOR "263355"</div>
</div>
<div class="col col-25 text-right">
<div ng-click="searchResults.openPopover()">
<i class="icon ion-arrow-down-b"></i>
Filter
</div>
</div>
</div>
</ion-content>
<ion-footer-bar>
Ad here 1
</ion-footer-bar>
</ion-view>
My popover template.
<ion-popover-view>
<ion-header-bar>
<h1 class="title">My Popover Title</h1>
</ion-header-bar>
<ion-content>
Hello!
</ion-content>
</ion-popover-view>
Why does the popover not show and how can I fix this?
I did some digging in the ionic CSS for popover, and the opacity is set to 0 by default. You can override the opacity to 1 and the popover will display, but I found this: https://github.com/driftyco/ionic/issues/2343. Basically, you have to pass the event ($event) to popover.show() and it will work. The ionic example shows this but the documentation could be more explicit. In your code, change your template to ng-click="searchResults.openPopover($event)".
In my case i just didn't put the popover component in the entryComponent section in my shared module. I didn’t get an error until I restarted the server, don't know why