Auto scroll to bottom with ng-repeat in Ionic - javascript

I have a problem that become a realy nightmare. I build a mobile chat app with Ionic, Angular and Firebase. The message exchange works well, but i have problem with auto scroll do bottom when received new messages, i try use $ionicScrollDelegate, scroll-glue Directive, Jquery function and nothing works.
Page chat
<div ng-controller="ChatController as chatCtrl" id="chats_page" class="upage-content vertical-col left hidden has-subheader">
<div class="bar bar-subheader subheader-chat">
<h2 class="title">{{chatCtrl.status}}</h2>
</div>
<div class="" data-uib="layout/row" data-ver="0" id="chatBox">
<ion-content id="autoscroll" class="widget uib_w_92 d-margins topbar" data-uib="ionic/list" data-ver="0" delegate-handle="mainScroll">
<ion-list scroll-glue>
<ion-item ng-repeat="msg in chatCtrl.messages" class="item widget uib_w_93 chat-cliente item-text-wrap" data-uib="ionic/list_item" data-ver="0" ng-class="chatCtrl.getRole(msg.role)">{{msg.text}}<a class="chat-time">{{msg.time}}</a>
</ion-item>
</ion-list>
</ion-content>
</div>
<div class="bar bar-footer footer-chat" >
<i class="placeholder-icon "></i>
<textarea type="text" name="msg" placeholder="Digite sua mensagem..." class="chat-text" ng-disabled="chatCtrl.msgText()" ng-model="myMsg" ></textarea>
<button class="button ion-paper-airplane btn-chat-send" ng-click="chatCtrl.sendMsg(myMsg)" ng-disabled="chatCtrl.msgText()" id='btn_send_chat'></button>
</div>
</div>
And piece of ChatController
angular.module('myApp')
.controller("ChatController", ['User','FireBaseApp','$firebase','$ionicLoading','$timeout','$ionicPlatform','$location','$ionicHistory','$timeout','$ionicPopup','$ionicScrollDelegate','$scope',function(User, FireBaseApp ,$firebase, $ionicLoading,$timeout,$ionicPlatform,$location,$ionicHistory,$timeout,$ionicPopup,$ionicScrollDelegate,$scope){
var self = this;
... pieces of code ...
self.sendMsg = function(msg){
$scope.myMsg = null;
$ionicScrollDelegate.scrollBottom();
}

You can use.
$ionicScrollDelegate.scrollBottom(true);
Example on codepen

After a year i found a solution: Separate my app in angular template and finally scrollglue works.

Related

Ionic Cordova: Angualarjs double binding is not working

I am developing a hybrid application by using Ionic Framework. However, my application failed in double binding when user back to hybrid application. The application able to retrieve Array Object from localstorage but my ngrepeats failed to load the var I assigned from localstorage. The following is my code.
controller.js
.controller('ChatsCtrl', ['$scope','$state', '$ionicTabsDelegate' , '$ionicListDelegate', '$rootScope'
,function($scope,$state,$ionicTabsDelegate, $ionicListDelegate, $rootScope) {
var channel_list = [];
channel_list = localStorage.getItem("channel_list");
$scope.chats = channel_list;
}])
HTML File
<ion-view cache-view="false" view-title="DRDM Chat">
<div class="bar bar-header bar-calm">
<div class="h1 title">DRDM Chat</div>
</div>
<ion-content on-swipe-right="goBack()" on-swipe-left="goForward()">
<br><br>
<ion-list>
<ion-item class="item-remove-animate item-avatar item-icon-right" ng-repeat="chat in chats" type="item-text-wrap" ng-click="chatRoom({{'chat.displayName'}}, {{'chat.channelID'}})">
<img ng-src="data:image/png;base64,{{chat.profilePicture}}">
<h2>{{chat.displayName}}</h2>
<p>{{chat.lastText}}</p>
<i class="icon ion-chevron-right icon-accessory"></i>
<ion-option-button class="button-assertive" ng-click="remove($index, chat.channelID)">Delete</ion-option-button>
</ion-item>
</ion-list>
</ion-content>
</ion-view>
Try calling a function on page load that re initialize your list something like this,
Controller.js
$scope.init = function(){
var channel_list = [];
channel_list = localStorage.getItem("channel_list");
$scope.chats = JSON.parse(channel_list);
}
$scope.init();
And make sure when ever you visit this page this function is fired.
Note: if you are on the same page and wants to rebind the list then call this function in your goBack() or goForward() function where ever required.
Hope this solves your problem.
JS
var channel_list = [];
channel_list = localStorage.getItem("channel_list");
$scope.chats = JSON.parse(channel_list);
HTML file
<ion-view cache-view="false" view-title="DRDM Chat">
<div class="bar bar-header bar-calm">
<div class="h1 title">DRDM Chat</div>
</div>
<ion-content on-swipe-right="goBack()" on-swipe-left="goForward()">
<br><br>
<ion-list>
<ion-item class="item-remove-animate item-avatar item-icon-right" ng-repeat="chat in chats" type="item-text-wrap" ng-click="chatRoom(chat.displayName,chat.channelID)">
<img ng-src="data:image/png;base64,{{chat.profilePicture}}">
<h2>{{chat.displayName}}</h2>
<p>{{chat.lastText}}</p>
<i class="icon ion-chevron-right icon-accessory"></i>
<ion-option-button class="button-assertive" ng-click="remove($index, chat.channelID)">Delete</ion-option-button>
</ion-item>
</ion-list>
</ion-content>
ng-click="chatRoom(chat.displayName,chat.channelID) Pass value like this.

Why an ionic modal freezes the UI when it is closed or submitted?

I have a popover which two options -Add Favorite and Add Comment-, the first options is working correctly: it does not freeze the user interface; but the second one once the form is omitted or submitted freezes the interface. This is what is happening:
Note how when I close the form the interface does not respond.
This is the code I have used to create the popover and and modal:
$ionicPopover.fromTemplateUrl('templates/dish-detail-popover.html',{
scope: $scope})
.then(function(popover){
$scope.popover = popover;
});
$scope.openPopover = function($event){
$scope.popover.show($event);
}
$scope.closePopover = function() {
$scope.popover.hide();
};
$ionicModal.fromTemplateUrl('templates/dish-comment.html', {
scope: $scope
}).then(function(modal) {
$scope.commentModal = modal;
});
// Triggered in the reserve modal to close it
$scope.closeAddComment = function() {
$scope.commentModal.hide();
};
// Open the reserve modal
$scope.showCommentModal = function($event) {
$scope.closePopover();
$scope.commentModal.show($event);
};
The template for dish-detail-popover.html:
<ion-popover-view>
<ion-content>
<div class="list">
<a class="item" ng-click="addFavorite(dish.id)">
Add to favorites
</a>
<a class="item" ng-click="showCommentModal()">
Add Comment
</a>
</div>
</ion-content>
</ion-popover-view>
and the template for dish-comment.html:
<ion-modal-view>
<ion-header-bar>
<h1 class="title">Submit Comment on Dish</h1>
<div class="buttons">
<button class="button button-clear" ng-click="closeAddComment()">Close</button>
</div>
</ion-header-bar>
<ion-content>
<form id="comentDishForm" name="comentDishForm" ng-submit="doComment()">
<div class="list">
<label class="item item-input item-select">
<span class="input-label">Rating</span>
<select ng-model="comment.rating">
<option ng-repeat="n in [1,2,3,4,5]" value="{{n}}">{{n}}</option>
</select>
</label>
<label class="item item-input">
<span class="input-label">Your Name</span>
<input type="text" ng-model="comment.author">
</label>
<label class="item item-input">
<span class="input-label">Your Comment</span>
<input type="text" ng-model="comment.comment">
</label>
<label class="item">
<button class="button button-block button-positive" type="submit">Submit</button>
</label>
</div>
</form>
</ion-content>
</ion-modal-view>
NOTE: When the form is called from the Add Comment button (the green one), it works correctly. The failure is related when it called from the popover.
Some suggestions, or ideas,... to solve this?
The screen gets freezed because despite closing the popover before opening the modal, the body tag remains dirty with the class 'popover-open'. A quick solution, but not the neatest, is to close the popover again when closing the modal. This way, ionic framework will remove the class 'popover-open' from the body tag. Example:
$scope.$on('modal.hidden', function() {
$scope.closePopover();
});
Hope it helps.
I also ran into the same issue and had no idea why this was happening. Reading the Ionic docs about ionicPopover, I found that the .hide() method is actually returning a promise which will resolve once the popover is animated out. So, what you can actually do is setup your closePopover() method as follows:
$scope.closePopover = function () {
return $scope.popover.hide();
};
As for the method to be executed when someone clicks the "Add Comment" option, you can implement that as follows:
$scope.addComment = function addComment() {
$scope.closePopover()
.then(function() {
$scope.openAddCommentModal();
});
};
This will ensure that the modal is only shown once the popover is completely animated out and those classes are removed from the body tag. This will clear the dirty states and make the app respond.

Best practice displaying menu and toolbar in Angular2

I have a webapplication where a user can log into his account. When the user is logged in now the sidenav(menu) and toolbar appears. But when the user isn't logged in (maybe he is going to login or registrate) the toolbar and sidenav should be not visible.
What is the best practice to do that in Angular2(version: 2.1.0 and angular/router version: 3.1.0)
I tried to disable the toolbar and sidenav with ngIf but It doesn't really work and I think it is not a clean solution.
Then I thought about two <router-outlet>. One for the routing when the user is logged in and one when the user is not logged in. Is this the right way to solve my problem? If yes, how does it work?
Here my app.component.html where I define my toolbar, sidenav and the <router-outlet>:
<md-sidenav-layout class="{{themeService.ActualTheme}}" fullscreen>
<div *ngIf="menuToolbarConfigService.ActualPage !== 'landing' && menuToolbarConfigService.ActualPage !== 'register'">
<md-sidenav #sidenav mode="{{menuToolbarConfigService.setSideNav(sidenav)}}">
<div>
<div class="sidenav-header">
<div class="logo-circle">
<span class="logo">GT</span>
</div>
<span class="user-name">Nico</span>
<span class="open-tasks">Offene Tasks: 4</span>
</div>
<md-list>
<div [ngClass]="{'highlight': menuToolbarConfigService.ActualPage === 'start'}" class="nav-list-item">
<md-list-item>
<md-icon>assignment</md-icon> Taskboard
</md-list-item>
</div>
<div [ngClass]="{'highlight': menuToolbarConfigService.ActualPage === 'groups'}" class="nav-list-item">
<md-list-item>
<md-icon>group</md-icon> Gruppen
</md-list-item>
</div>
<div [ngClass]="{'highlight': menuToolbarConfigService.ActualPage === 'user'}" class="nav-list-item">
<md-list-item>
<md-icon>account_circle</md-icon> Benutzer
</md-list-item>
</div>
<div [ngClass]="{'highlight': menuToolbarConfigService.ActualPage === 'user'}" class="nav-list-item">
<md-list-item>
<md-icon>search</md-icon> Taskbrowser
</md-list-item>
</div>
</md-list>
</div>
</md-sidenav>
</div>
<md-toolbar color="primary">
<span *ngIf="menuToolbarConfigService.ShowMenuIcon" (click)="sidenav.open();" class="menu-icon"><md-icon>menu</md-icon></span>
<span class="app-title">GroupTasking</span>
<!-- This fills the remaining space of the current row -->
<span class="example-fill-remaining-space"></span>
</md-toolbar>
<router-outlet></router-outlet>
</md-sidenav-layout>
Thank you in advance!

ng-click inside a form modal doesn't fire event

I just wrote that simple button that open a modal. In this modal I put a "Close" button that fires a "closeLogin()" function that works well. The same way I create a beer button inside the login form to launch a "doTestme()" function but it is never launched. Please see below:
Button that correctly trigger the modal:
<script id="templates/home.html" type="text/ng-template">
<ion-view view-title="Welcome">
<ion-content class="padding">
<button type="button" class="button" ng-click="login()">Log-in Test, click on the beer!</button>
</ion-content>
</ion-view>
</script>
The "MainCtrl" that handle the $scope for this:
.controller('MainCtrl', function($scope, $ionicSideMenuDelegate, $ionicModal, $timeout) {
$scope.loginData = {};
// Create the login modal that we will use later
$ionicModal.fromTemplateUrl('templates/login.html', {
scope: $scope
}).then(function(modal) {
$scope.modal = modal;
});
// Triggered in the login modal to close it
$scope.closeLogin = function() {
$scope.modal.hide();
};
// Open the login modal
$scope.login = function() {
$scope.modal.show();
};
$scope.doTestme = function() {
alert("test ok");
};
Modal that correctly pop-out:
<script id="templates/login.html" type="text/ng-template">
<ion-modal-view>
<ion-header-bar>
<h1 class="title">Login</h1>
<div class="buttons">
<button class="button button-clear" ng-click="closeLogin()">Close</button>
</div>
</ion-header-bar>
<ion-content>
<form ng-submit="doLogin()">
<div class="list">
<label class="item item-input">
<span class="input-label">Username</span>
<input type="text" ng-model="loginData.username">
</label>
<label class="item item-input">
<span class="input-label">Password</span>
<input type="password" ng-model="loginData.password" style="-webkit-flex: 1 0 100px;"><button type="button" ng-click="doTestme()" class="button button-icon ion-beer" style="font-size:35px;"></button>
</label>
<label class="item">
<button class="button button-block button-positive" type="submit">Log in</button>
</label>
</div>
</form>
</ion-content>
</ion-modal-view>
</script>
It's as if the ng-click is never watched, I don't have any errors in console, no way to debug this so... Any idea?
Here is the codepen: http://codepen.io/anon/pen/jEpNGB
You should not use buttons inside label.It will not work properly.
Just change the container from <label> to <div>
<div class="item item-input">
<span class="input-label">Password</span>
<input type="password" ng-model="loginData.password" style="-webkit-flex: 1 0 100px;">
<button type="button" ng-click="doTestme()" class="button button-icon ion-beer" style="font-size:35px;"></button>
</div>
Check this working codepen
In first moment i tried two things:
Change the function to "doAlert()"
Change the button to a normal link " test"
It's worked! But few minutes after the link not fired anymore the alert box.
I tried just in CodePlen. Please do it outside there and send a feed back.

Ionic infinite scrolling, only scrolls when navigated away and back to page

I have a ionic content with a ionic list in it.
Here is my HTML:
<ion-content>
<ion-view>
<ion-list >
<div class='myCard' ng-repeat="maanta in maanta| limitTo : limit track by $index">
<a class='normala' href="#/tab/dash/{{maanta.id}}">
<div class='cardHeader item-text-wrap'>
{{maanta.title}}
</div>
<hr class='divi'>
<div class='cardDivider item-text-wrap'>
{{maanta.source}} - {{maanta.pub_date}}
</div>
<hr class='divi'>
<div class='cardBody item-text-wrap'>
{{maanta.summery}}
</div>
</a>
</div> </ion-list>
<ion-infinite-scroll ng-if="!noMoreItemsAvailable" on-infinite="loadMore()" distance="1%"></ion-infinite-scroll>
</ion-content>
</ion-view>
Here is my JS:
$scope.limit = 10;
$scope.loadMore = function() {
$scope.limit +=10
if ( $scope.maanta.length <$scope.limit) {
$scope.noMoreItemsAvailable = true;
}
$scope.$broadcast('scroll.infiniteScrollComplete');
};
The problem
When I first land on the page the infinite scrolling doesn't change limit for my ng-repeat. When I navigate away to another page and come back the infinite loop works as expected.
Check out your HTML. There's a mistake in the tag sequence :
<ion-content>
<ion-list >
<div class='myCard' ng-repeat="maanta in maanta| limitTo : limit track by $index">
<a class='normala' href="#/tab/dash/{{maanta.id}}">
<div class='cardHeader item-text-wrap'>
{{maanta.title}}
</div>
<hr class='divi'>
<div class='cardDivider item-text-wrap'>
{{maanta.source}} - {{maanta.pub_date}}
</div>
<hr class='divi'>
<div class='cardBody item-text-wrap'>
{{maanta.summery}}
</div>
</a>
</div> </ion-list>
<ion-infinite-scroll ng-if="!noMoreItemsAvailable" on-infinite="loadMore()" distance="1%"></ion-infinite-scroll>
</ion-content>
The tag <ion-view> was not required as such.
I think you should reconsider your approach and try to push the new content to your view.
The key is pushing the new content.
Fore example (from user DILIP on codepen:)
<ion-infinite-scroll distance="2"
on-infinite="loadMoreData()"
ng-if="!moredata" >
</ion-infinite-scroll>
var app = angular.module("ionicInfiniteScrollApp",['ionic']);
app.controller("InfiniteAppCntrl",function($scope)
{
$scope.moredata = false;
$scope.loadMoreData=function()
{
$scope.items.push({id: $scope.items.length});
if($scope.items.length==100)
{
$scope.moredata=true;
}
$scope.$broadcast('scroll.infiniteScrollComplete');
};
$scope.items=[];
});
Here's the link to the codepen:
http://codepen.io/d4dilip/pen/rkxyA

Categories

Resources