Dismiss Ionic 4 loading (spinner) when the data is ready - ionic-framework

How to dismiss my simple Ionic 4 loader (spinner), when the data is ready?
There must be a simple way to do that, but somehow I cannot find a good example.
Spinner:
async runSpinner(loadingId: string) {
const loading = await this.loadingController.create({
id: loadingId,
message: 'Loading...'
});
await loading.present();
const { role, data } = await loading.onDidDismiss();
}
Data (when this is loaded, spinner should stop)
this.someService
.getCustomizationResult(requestData)
.subscribe(data => {
// if (data) {
// ...
});
I've tried to do it with setting a boolean, but it didn't work. Thanks in advance!

You could go for this approach:
use a boolean value to show/hide a loading spinner
set the spinner as active when you enter the page with ionViewWillEnter
when your data loads, set the spinner to false
don't forget to hide the spinner when your service sends an error, otherwise the spinner won't hide to show an error msg for example.
Example
<ion-content>
<ion-grid>
<ion-row *ngIf="spinner">
<ion-col size="12">
// You can customize this the way you want
<ion-spinner></ion-spinner>
</ion-col>
</ion-row>
<ion-row *ngIf="!spinner">
// When the data loads, show this ...
</ion-row>
</ion-grid>
</ion-content>
spinner: boolean;
ionViewWillEnter() {
this.spinner = true;
}
getCustomizationResult() {
this.someService
.getCustomizationResult()
.subscribe({
next: (data) => {
// data
this.spinner = false;
},
error: (error) => {
// error
this.spinner = false;
}
});
}

Check this one
const loading = await this.loadingController.create({
message: 'Loading...'
});
}
// start working
loading.present().then( async ()=> {
/////Call your services to get data
}).then( async() => {
loading.dissmiss();
});

Related

Ionic 4 LoadingController

I am trying to add a LoadingController to my Ionic 5 app.
With the below code, the loading spinner is appearing:
async presentLoading() {
const loading = await this.loadingCtrl.create({
message: 'Please wait...',
});
await loading.present();
}
getPosts() {
this.posts = [];
this.presentLoading();
query.get()
.then((docs) => {
docs.forEach((doc) => {
this.posts.push(doc);
})
}).catch((err) => {
console.log(err)
})
}
But I don't know how to dismiss the LoadingController once the posts array has been populated.
Can someone please show me how this is done?
You have to dismiss the controller. For that you will have to keep a reference to it, something like this,
async presentLoading() {
this.loading = await this.loadingCtrl.create({
message: 'Please wait...',
});
await this.loading.present();
}
getPosts() {
this.posts = [];
this.presentLoading();
query.get()
.then((docs) => {
docs.forEach((doc) => {
this.posts.push(doc);
this.loading.dismiss();
})
}).catch((err) => {
console.log(err)
})
}
If you need to get notice when the dismiss occurs, you can listen to onDidDismiss event.
Links:
Ionic Docs - LoadingController

Ionic 4 Loadingcontroller overlay doesnt exist

I created a simple function of creating a loading like this
async presentLoading() {
const loading = await this.loadingController.create({
message: 'Please Wait...',
});
await loading.present();
}
And i am closing the loader when the data is fetch like this
getUserData(){
console.log(this.userID);
this.api.getCompanyEmploye(this.userID).subscribe(res => {
this.loadingController.dismiss(); //closing here
console.log(res);
this.user = res.records[0];
this.familyMembers = res.records[0].family_members;
});
}
I am calling both function in constructor
constructor(public loadingController: LoadingController){
this.presentLoading();
this.getUserData();
}
Its showing error of ERROR Error: Uncaught (in promise): overlay does not exist
The issue is that your API call responds sooner than the loading controller gets instantiated. Instead of parallel calls, you should try to serialize those this way:
Make your presentLoading method to return Promise:
async presentLoading() {
const loading = await this.loadingController.create({
message: 'Please Wait...',
});
return loading.present();
}
Now you can call it this way:
getUserData(){
this.presentLoading().then(()=>{
this.api.getCompanyEmploye(this.userID).subscribe(res => {
this.loadingController.dismiss(); //closing here
console.log(res);
this.user = res.records[0];
this.familyMembers = res.records[0].family_members;
});
})
}
And in your constructor you need only to call for the API
for me, the issue is simply because I don't have .catch() for the promise. As#Sergey suggested, this is because the loader is not ready when you calling the ionic loader
this.loadingController.dismiss()
.then(async () => {
await this.setStorageForLocalData(data);
})
.catch(console.error);
where .catch() will dismiss the error

Ionic 4 Loading Controller continues after dismissing

I am using Ionic 4 and the Loading Controller.
async presentLoading() {
const loading = await this.loadingCtrl.create({
message: 'wait. . .'
});
return await loading.present();
}
Works great. But now I want to dismiss the loader programatically.
this.loadingCtrl.dismiss().then(a => console.log('dismissed'));
Even though I see 'dismissed' on my console (logging worked) the loading overlay continues. Any idea what might be the reason?
You not dismissing the actual loader that is displayed. You have to dismiss it with loading variable like below :
loading.dismiss().then(a => console.log('dismissed'));
Notice that I have used variable loading that you have declared for current loader.
If you want to dismiss programmatically use this in your service.
export class LoaderService {
private isLoading = false;
constructor(private loadingController: LoadingController) {
}
async presentLoading() {
// issue generated! so we used Boolean value to set loader dismissed call
firstly so we used this logic
this.isLoading = true;
let loading = await this.loadingController.create({
message: 'Please Wait',
spinner: 'bubbles'
}).then((res) => {
res.present();
if (!this.isLoading) {
// res.dismiss().then(()=> console.log('abort presenting'));
this.loadingController.dismiss().then(() =>
console.log('Dismissed'));
}
});
return loading;
}
async hideLoading() {
this.isLoading = false;
return await this.loadingController.dismiss().then(() => console.log('Dismissed'));
}
}

Loading controller css in not working in ionic 4?

Is anyone know how to give css of loading controller in ionic 4? I have tried all the solution which is availbale online but none of its working,so please help me.
I have made one service called loadingService for loading controller then i give css in gloabal.scss or variable.scss is still not working.here is my code.
loadingService.ts
async present() {
this.isLoading = true;
return await this.loadingController.create({
spinner: "lines-small",
duration: 10000,
cssClass:'loader',
}).then(a => {
a.present().then(() => {
console.log('presented');
if (!this.isLoading) {
a.dismiss().then(() => console.log('abort presenting'));
}
});
});
}
async dismiss() {
this.isLoading = false;
return await this.loadingController.dismiss().then(() => console.log('dismissed'));
}
gloabal.scss
.loader {
--background: #600001;
--spinner-color: yellow;
}
Please help me on it, and yes i am using ionic 4 so please give me ionic 4 solution not ionic 3.

fetching data from api and shows on Render Method

I am fetched data from api but the problem is
when i am show data in render method then it showing "Undefine"
Please Help me to fix it
This is my code:-
var ProductData=''
export default class ApiProduct extends Component {
FetchProduct=()=>{
fetch('https://drawtopic.in/projects/wordpress/wp- json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b',{
method:'GET',
})
.then((response) => response.json())
.then((res) =>{
ProductData= res;
})
}
render() {
{this.FetchProduct()}
{console.warn(ProductData)}
return (
<View/>
)}
i Want to Show All data in render method
Here is a quick Expo example that should show you how to render a simple list. It is not a good idea to call fetch inside the render method, as every re-render will call the fetch.
Here is an expo snack https://snack.expo.io/S1-LKIyQE
import React from 'react';
import { Text, View, StyleSheet, FlatList, SafeAreaView } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
productData: []
}
}
async componentDidMount () {
await this.getData();
}
async getData() {
try {
let url ='https://drawtopic.in/projects/wordpress/wp-json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b'
let response = await fetch(url, { method:'GET' });
let responseJson = await response.json();
this.setState({productData: responseJson});
} catch (err) {
console.warn(err);
}
}
renderItem = ({item}) => {
return (
<View style={styles.mainItem}>
<Text>{item.name}</Text>
</View>
);
}
keyExtractor = (item, index) => {
return index.toString();
}
render() {
return (
<SafeAreaView style={styles.container}>
<FlatList
extraData={this.state}
data={this.state.productData}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
/>
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
},
mainItem: {
width:200,
height: 80,
justifyContent: 'center',
alignItems: 'center',
margin: 10,
backgroundColor: 'yellow',
borderColor: 'black',
borderWidth: 1
},
});
Here I have used async/await as it can make for much cleaner and clearer code. This is a great article on the differences between promises and async/await https://medium.com/#bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8.
I have also given you a quick example on how to use a FlatList to display your data. You should check the docs on how to use it properly https://facebook.github.io/react-native/docs/flatlist
If you want to edit how each item is displayed on the screen then you need to update the renderItem method.
Try this way, if you have a question of how it works makes me to know.
let self;
export default class ApiProduct extends Component {
constructor(){
super();
self = this;
this.state = {
productData: null;
};
}
FetchProduct=()=>{
fetch('https://drawtopic.in/projects/wordpress/wp- json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b',{
method:'GET',
})
.then((response) => response.json())
.then((res) =>{
self.setState({ productData: res});
});
}
render() {
this.FetchProduct();
console.warn(self.state.productData);
return (
<View/>
);
}
I'll try to make order in your code.
Fetching data in the render method is not a good idea, it's better to use lifecycle methods, like componentDidMount. In order to handle your request result, set a state field and in your render read data from that field. So:
export default class ApiProduct extends Component {
constructor(){
super();
this.state = {
productData: undefined;
};
}
async componentDidMount(){
await this.fetchProduct();
}
fetchProduct = () => {
fetch('https://drawtopic.in/projects/wordpress/wp- json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b',{
method:'GET',
})
.then((response) => response.json())
.then((res) =>{
this.setState({
productData: res
})
})
}
render() {
const {productData} = this.state;
console.log(productData);
return (
<View/> // add here your code to render data properly
)
}}