How use setTimeout for *ngIf in angular 10 for the ionic spinner - settimeout

I'll have an ionic loading indicator that I'll want to show after 2 seconds of loading if the application still loading data from a server else don't show it. This is the html of the spinner.
<!-- Loading -->
<div class="ion-text-center" *ngIf="isLoading && timer == 0">
<ion-spinner name="dots" color="light"></ion-spinner>
</div>
In the page component I'll set isLoading to true each time new posts are loaded. In the setPostData I'll set it back to false. But combining this with the timer doesn't work.
posts: any = [];
timer: any = 0;
isLoading: boolean;
constructor(){...}
getPostData(){
this.timer = setTimeout(() => {}, 2000);
this.isLoading = true;
this.postService.getPosts().subscribe(
(result) => {
this.setPostData(result);
}
);
}
setPostData(data){
this.posts = data.posts;
this.isLoading = false;
}

I'll found another way to do it. Create a timer(setTimeout) and bind the toggleLoading function. In the setPostData function clear the created timer. So after 2500 miliseconds the loading starts. If 2500 miliseconds is not reached the timer is cleared and the loading dots are not displayed as wished.
posts: any = [];
timer
isLoading: boolean;
constructor(){...}
toggleLoading(){
this.isLoading = !this.isLoading;
}
getPostData(){
this.timer = setTimeout(this.toggleLoading.bind(this), 2500);
this.postService.getPosts().subscribe(
(result) => {
this.setPostData(result);
}
);
}
setPostData(data){
this.posts = data.posts;
if(this.timer) {
clearTimeout(this.timer);
}
this.isLoading = false;
}

Related

Infinite scroll is not triggered framework7

I am using framework7.In AJAX success function I am loading first 20 people and remaining to be loaded by infinite scroll.
This is the div element
<div class="page-content infinite-scroll" data-distance="50">
<div class="searchbar-backdrop"></div>
<div class="entry_content">
<div class="members_list list searchbar-found list-block">
<ul class="row22">
</ul>
</div>
<div class="block searchbar-not-found">
<div class="block-inner">Nothing found</div>
</div>
</div>
Also this is the script
$on('pageInit', () => {
app.request({
url: base_url+api_path+'/members_directory.php',
method: "POST",
timeout: 0,
dataType: "json",
beforeSend: function () {
app.preloader.show();
},
success: function(data) {
app.preloader.hide();
console.log(data);
for(var i=0;i<20;++i){
// for(var i=0;i<data.getEmployees.length;++i){
var user_id = data.getEmployees[i].user_id;
var username = data.getEmployees[i].username;
var profile_photo = data.getEmployees[i].profile_photo;
var employee_name = data.getEmployees[i].employee_name;
var employee_id = data.getEmployees[i].employee_id;
$('.page_members_dir .members_list ul').append(
'<li class="item-content member_item"><div class="item-title member_name">'+employee_name+'</div></li>'
);
};
/*infinite*/
var loading = false;
// Last loaded index
var lastIndex = $('.list-block li').length;
// Max items to load
var maxItems = 60;
// Append items per load
var itemsPerLoad = 20;
// Attach 'infinite' event handler
$('.infinite-scroll').on('infinite', function () {
// app.attachInfiniteScroll($('.infinite-scroll'));
console.log("inside");
// Exit, if loading in progress
if (loading) return;
// Set loading flag
loading = true;
// Emulate 1s loading
setTimeout(function () {
// Reset loading flag
loading = false;
if (lastIndex >= maxItems) {
// Nothing more to load, detach infinite scroll events to prevent unnecessary loadings
app.detachInfiniteScroll($('.infinite-scroll'));
// Remove preloader
$('.infinite-scroll-preloader').remove();
return;
}
// Generate new items HTML
var html = '';
for (var i = lastIndex + 1; i <= data.getEmployees.length; i++) {
var user_id = data.getEmployees[i].user_id;
var username = data.getEmployees[i].username;
var profile_photo = data.getEmployees[i].profile_photo;
var employee_name = data.getEmployees[i].employee_name;
var employee_id = data.getEmployees[i].employee_id;
html += '<li class="item-content member_item"><div class="item-title member_name">'+employee_name+'</div></li>';
}
console.log(html);
// Append new items
$('.list-block ul').append(html);
// Update last loaded index
lastIndex = $('.list-block li').length;
}, 1000);
});
},
error: function(data) {
//console.log('error');
console.log(data);
}
});
});//pageInit
return $render;
}
I am not getting any errors in console.
The list data is getting from ajax page.
If I console after $('.infinite-scroll').on('infinite', function () nothing is displayed.
Is this right way to infinite scroll use in AJAX success function.
Please help

How to stop functions when leaving the page in Ionic 4

I am working in my Ionic 4 app and I want to stop the functions when the page will leave.
This is my tab4.page.ts:
async getUserDetail(){
this.dataexists = false;
this.userActiveChallanges = [];
let me=this;
const loading = await this.loadingController.create({
message: '',
// duration: 2200,
translucent: true,
spinner: 'crescent',
showBackdrop: false,
cssClass: 'my-loading-class'
});
await loading.present();
this.userActiveChallanges=[];
this.storage.get('USERPROFILE').then(userObj => {
// console.log('User Profile :',userObj);
me.userprofile = userObj;
me.sendFitDatafunction(userObj);
me.myapi.apiCall('userActiveChallenges/'+userObj.id,'GET','').subscribe((data) => {
// console.log(data);
me.response=data;
loading.dismiss();
if(me.response.status === 'success'){
if(me.response && me.response.data && me.response.data.length>0){
this.userActiveChallanges=me.response.data;
this.flip(this.userActiveChallanges[0].challenge_id);
}
this.dataexists = true;
} else{
this.userActiveChallanges = '';
this.dataexists = true;
}
}, error => { loading.dismiss(); console.log(error); });
});
}
ionViewWillLeave() {
}
I want to stop this function when the page will leave because when I am not getting any response nor any error from the api the loader keeps running and when I move to the other page, it is showing there.
So, I want to stop the function when the page will leave.
Any help is much appreciated.
instead of local const loading, declare it as a property of your ts class (tab4).
now change your code and assign loader to it:
replace: const loading
with:
this.loading
Now inside ionViewWillLeave call:
ionViewWillLeave() {
if (this.loading) { this.loading.dismiss() }
}
Well, I don't know the function to stop your function, but to make something when you leave a page, you make it in IonViewDidLeave()

Ionic There is a Bug? ion-refresher and ion-infinite-scroll

I found an compatibility issue using the two mentioned components on same list, my html and js code below:
HTML:
<ion-content ng-controller="homeCtrl">
<ion-refresher on-refresh="loadNewContent()" pulling-text="LoadMore..." spinner="android"></ion-refresher>
<div ng-repeat="item in items">
<img ng-src="{{pathUrl+item['path']}}" style="height: auto;width:100%;">
</div>
<ion-infinite-scroll ng-if="hasMore" on-infinite="loadMoreContent()" spinner="spiral" distance="5" immediate-check="false"></ion-infinite-scroll>
</ion-content>
JavaScript:
JiCtrls.controller('homeCtrl', ['$scope', '$timeout', 'DbService', 'JsonService',
function ($scope, $timeout, DbService, JsonService) {
$scope.items = [];
$scope.hasMore = true;
var run = false;
loadData(0);
//下拉更新
$scope.loadNewContent = function () {
loadData(2);
// Stop the ion-refresher from spinning
$scope.$broadcast("scroll.refreshComplete");
};
//上拉更新
$scope.loadMoreContent = function () {
loadData(1);
$scope.$broadcast('scroll.infiniteScrollComplete');
};
function loadData(stateType) {
if (!run) {
run = true;
if ($scope.sql == undefined) {
$scope.sql = "select top 5 * from information ";
}
DbService.getData($scope.sql, '').success(function (data, status, headers, config) {
var convertData = JsonService.convertData(data);
if (stateType == 1 || stateType == 0) {
// $scope.items = $scope.items.concat(convertData);
for (var i = 0; i < convertData.length; i++) {
$scope.items.push(convertData[i]);
}
}
else {
for (var i = 0; i < convertData.length; i++) {
$scope.items.unshift(convertData[i]);
}
}
if (convertData == null || convertData.length <= 0) {
$scope.hasmore = false;
;
}
$timeout(function () {
run = false;
}, 500);
}).error(function (errorData, errorStatus, errorHeaders, errorConfig) {
console.log(errorData);
});
}
}
}
]);
Everything is normal in Chrome browser and Iphone, but in a part of the Android phone there is a big problem.When ion-refresher trigger on-refresh function,the on-infinite="loadMoreContent()" function will run indefinitely. So,What is the problem?
Try to put $scope.$broadcast("scroll.refreshComplete"); and $scope.$broadcast('scroll.infiniteScrollComplete'); into DbService.getData(...).success() callback, not in functions triggered by on-infinite and on-refresh.
Explanation:
When the user scrolls to the end of the screen, $scope.loadMoreContent which is registered with on-infinite is triggered. The spinner shows, and ion-infinite-scroll pauses checking whether the user has reached the end of the screen, until $scope.$broadcast('scroll.infiniteScrollComplete'); is broadcast, when it hides the spinner and resumes the checking.
In your code, imagine there's a 3s delay in network, no new item is added to the list in that 3s. As a result, the inner height of ion-content is never updated, so the check that determines whether the user has reached the end of the screen will always return true. And you effectively prevent ion-infinite-scroll from pausing this checking by broadcasting scroll.infiniteScrollComplete the moment on-infinite is triggered. That's why it will update indefinitely.
To improve your code quality and prevent future problems, you may need to call $scope.$apply in your DbService.getData().success() callback (depending on the implementation of getData) and manually notify ion-content to resize in the callback.
P.S. 来自中国的Ionic开发者你好 :-) 两个中国人讲英语真累啊
Update
I've made a codepen that combines both ion-refresher and ion-infinite-scroll, I think it's working pretty fine.
http://codepen.io/KevinWang15/pen/xVQLPP
HTML
<html ng-app="ionicApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title>ion-refresher + ion-infinite-scroll 2</title>
<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
</head>
<body ng-controller="MyCtrl">
<ion-header-bar class="bar-positive">
<h1 class="title">ion-refresher + ion-infinite-scroll 2</h1>
</ion-header-bar>
<ion-content delegate-handle="mainScroll">
<ion-refresher on-refresh="doRefresh()">
</ion-refresher>
<ion-list>
<ion-item ng-repeat="item in list">{{item}}</ion-item>
</ion-list>
<ion-infinite-scroll
ng-if="hasMore"
on-infinite="loadMore()"
distance="1%">
</ion-infinite-scroll>
</ion-content>
</body>
</html>
JS
angular.module('ionicApp', ['ionic'])
.controller('MyCtrl', function($scope, $timeout, $q, $ionicScrollDelegate) {
/*
list of items, used by ng-repeat
*/
$scope.list = [];
var itemOffset = 0,
itemsPerPage = 5;
/*
used by ng-if on ion-infinite-scroll
*/
$scope.hasMore = true;
/*
isRefreshing flag.
When set to true, on data arrive
it first empties the list
then appends new data to the list.
*/
var isRefreshing = false;
/*
introduce a custom dataFetcher instance
so that the old fetch process can be aborted
when the user refreshes the page.
*/
var dataFetcher=null;
/*
returns a "dataFetcher" object
with a promise and an abort() method
when abort() is called, the promise will be rejected.
*/
function fetchData(itemOffset, itemsPerPage) {
var list = [];
//isAborted flag
var isAborted = false;
var deferred = $q.defer();
//simulate async response
$timeout(function() {
if (!isAborted) {
//if not aborted
//assume there are 22 items in all
for (var i = itemOffset; i < itemOffset + itemsPerPage && i < 22; i++) {
list.push("Item " + (i + 1) + "/22");
}
deferred.resolve(list);
} else {
//when aborted, reject, and don't append the out-dated new data to the list
deferred.reject();
}
}, 1000);
return {
promise: deferred.promise,
abort: function() {
//set isAborted flag to true so that the promise will be rejected, and no out-dated data will be appended to the list
isAborted = true;
}
};
}
$scope.doRefresh = function() {
//resets the flags and counters.
$scope.hasMore = true;
itemOffset = 0;
isRefreshing = true;
//aborts previous data fetcher
if(!!dataFetcher) dataFetcher.abort();
//triggers loadMore()
$scope.loadMore();
}
$scope.loadMore = function() {
//aborts previous data fetcher
if(!!dataFetcher) dataFetcher.abort();
//fetch new data
dataFetcher=fetchData(itemOffset, itemsPerPage);
dataFetcher.promise.then(function(list) {
if (isRefreshing) {
//clear isRefreshing flag
isRefreshing = false;
//empty the list (delete old data) before appending new data to the end of the list.
$scope.list.splice(0);
//hide the spin
$scope.$broadcast('scroll.refreshComplete');
}
//Check whether it has reached the end
if (list.length < itemsPerPage) $scope.hasMore = false;
//append new data to the list
$scope.list = $scope.list.concat(list);
//hides the spin
$scope.$broadcast('scroll.infiniteScrollComplete');
//notify ion-content to resize after inner height has changed.
//so that it will trigger infinite scroll again if needed.
$timeout(function(){
$ionicScrollDelegate.$getByHandle('mainScroll').resize();
});
});
//update itemOffset
itemOffset += itemsPerPage;
};
});
The correct Javscript is as follows:
JiCtrls.controller('homeCtrl', ['$scope', '$timeout', '$ionicScrollDelegate', 'DbService', 'JsonService',
function ($scope, $timeout, $ionicScrollDelegate, DbService, JsonService) {
$scope.items = [];
$scope.hasMore = true;
loadData(0);
//下拉更新
$scope.loadNewContent = function () {
loadData(2);
};
//上拉更新
$scope.loadMoreContent = function () {
loadData(1);
};
function loadData(stateType) {
if ($scope.sql == undefined) {
$scope.sql = "select top 5 * from information”;
}
DbService.getData($scope.sql, '').success(function (data, status, headers, config) {
var convertData = JsonService.convertData(data);
if (stateType == 0) {
for (var i = 0; i < convertData.length; i++) {
$scope.items.push(convertData[i]);
}
}
else if (stateType == 1) {
// $scope.items = $scope.items.concat(convertData);
for (var i = 0; i < convertData.length; i++) {
$scope.items.push(convertData[i]);
}
$timeout(function () {
$scope.$broadcast('scroll.infiniteScrollComplete');
}, 500);
}
else {
for (var i = 0; i < convertData.length; i++) {
$scope.items.unshift(convertData[i]);
}
// Stop the ion-refresher from spinning
$timeout(function () {
$scope.$broadcast("scroll.refreshComplete");
}, 500);
}
$ionicScrollDelegate.resize();
if (convertData == null || convertData.length <= 0) {
$scope.hasmore = false;
}
}).error(function (errorData, errorStatus, errorHeaders, errorConfig) {
console.log(errorData);
});
}
}
]);

ionic2 + angular2 - disable button on click

I have list of rows, and each one row has 2 more more buttons. I want to disable button on click event, so once its done ajax call then I can reenable it or hide it completely.
So I'm wondering how can I disable this single button on click event.
how can I disable from event?
<button [disabled]="buttonDisabled" (click)="trigger($event)">
trigger ($event)
{
$event.buttonDisabled = true; // ?
}
<div *ngfor="#row of rows">
<button [disabled]="awaitingAjaxCall[row] ? true : null" (click)="trigger($event, row)">
</div>
rows: [0,1,2];
awaitingAjaxCall:boolean[] = [false, false, false];
trigger ($event, row)
{
this.awaitingAjaxCall[row] = true;
this.http.get(...).map(...).subscribe(value => {
this.value = value;
// or here
// this.awaitingAjaxCall[row] = false;
}, error => {},
() => this.awaitingAjaxCall[row] = false);
}

Keeping the accordion menu open to show selected menu item

I have the following code for an accordion menu (see below).
How would I keep the current page menu item showing as at the moment whenever I move onto the page the menu closes down to only the top level?
I was also wondering if it's possible to have the accordion menu open up on click AND a page open at the same time??)
Thanks for any help anyone can give!
function initMenu() {
$(".sub-menu").hide();
$(".current_page_item .sub-menu").show();
$('#menu li a').click(
function() {
var checkElement = $(this).next();
if ((checkElement.is('ul')) && (checkElement.is(':visible'))) {
checkElement.slideUp('normal');
return false;
}
if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
$('#menu ul:visible').not(checkElement.parentsUntil('#menu')).slideUp('normal');
checkElement.slideDown('normal');
return false;
}
});
$('.current-menu-item').parentsUntil('#menu').slideDown('normal');
}
$(function() {
initMenu();
});
The initMenu() function, should look like this:
function initMenu() {
$(".sub-menu").hide();
$(".current_page_item .sub-menu").show();
$('#menu li a').click(
function() {
var checkElement = $(this).next();
if ((checkElement.is('ul')) && (checkElement.is(':visible'))) {
checkElement.slideUp('normal');
return false;
}
if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
$('#menu ul:visible').not(checkElement.parentsUntil('#menu')).slideUp('normal');
checkElement.slideDown('normal');
return false;
}
});
$('.current-menu-item').parentsUntil('#menu').slideDown('normal');
var FullCurrentURL = window.location.href;
var CurrentURLparts = FullCurrentURL.split("/");
var CurrentURLindex = CurrentURLparts.length - 1;
var CurrentURL = CurrentURLparts[CurrentURLindex];
$('#menu li a').each(function () {
var fullLinkURL = $(this).attr('href');
var LinkURLparts = fullLinkURL.split("/");
var LinkURLindex = LinkURLparts.length - 1;
var LinkURL = LinkURLparts[LinkURLindex];
if (LinkURL === CurrentURL){
$(this).parents("li").addClass("current-menu-item");
$(this).closest("ul").css('display', 'block');
}
});
}
$(function() {
initMenu();
});