Ionic 4 Loadingcontroller overlay doesnt exist - ionic-framework

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

Related

Riverpod : future provider is stuck on loading

Describe the bug
when executing the provider with ref.read or ref.watch the result is the same , it is stuck on the loading block , while testing the api in postman works fine , the funny thing is that the api call gets executed and whenever i print something inside it it appears in the console
To Reproduce
in presentation layer
onpressed:()=>ref
.read(getPatientProvider(
r.api_token))
.when(data: (data) {
data.fold(
(l) => print(
"something wrong happened"),
(r) async {
print(r.id);
print("hello");
patient.value = patient.value
.copyWith(
name: r.name,
aliid: r.id,
appointments: r
.patient_appointments,
fcmtoken: token);
ref.read(docexist(r.id)).when(
loading: () =>
print("loading"),
error: (error, _) =>
print(error),
data: (data) async {
print("heloo");
if (data.isEmpty) {
print(
"data is not empty");
} else {
return print(
"logged in normally");
}
});
});
}, error: (error, _) {
print(error);
}, loading: () {
print("object");
})
Provider with riverpod generator
#riverpod
Future<Either<ApiFailures, dynamic>> getPatient(
GetPatientRef ref, String token) async {
final patientProvider = ref.watch(patientRepositoryProvider);
return patientProvider.getInfo(token);
}
infrastructure layer
#override
Future<Either<ApiFailures, dynamic>> getInfo(String token) {
var dio = Dio();
final result = TaskEither<ApiFailures, PatientModel>(() async {
try {
final response = await dio.get(
"https://xxxxxxxx/GetInfo?api_token=$token");
if (response.data == null) {
return const Left(ApiFailures.notfound());
} else {
PatientModel patientModel =
PatientModel.fromJson(response.data["User"]);
return Right(patientModel);
}
} catch (err, st) {
final message = 'error ${err.runtimeType}]';
if (kDebugMode) log(message, error: err, stackTrace: st);
if (err is DioError) {
return Left(ApiFailures.fromDioError(error: err));
}
return const Left(ApiFailures.internalError());
}
});
return result.map((r) => r).run();
}
Expected behavior
it should get the data as always
Calling when inside a click handler such as onPressed as you did does not make sense.
"when" does not wait for the future to complete. It executes immediately based on the current status of the future.
Considering that when you call it, you just triggered the future, then the future at that time will always be in a loading state.
What you want is something like async/await, where you can wait until the completion of your future.
You could do that with:
onPressed: () async {
final value = await ref.read(provider.future);
}

async function returns Promise { <pending> }

I am trying to write a function that takes a URL and returns the engagement stats from Facebook Graph API against that URL. But I am facing trouble as my function is just giving me Promise { <pending> } as output.
Here is my code:
const getFacebookStats = async (link, ACCESS_TOKEN) => {
try {
const resp = await axios.get(
`https://graph.facebook.com/v12.0/?id=${link}&fields=engagement&access_token=${ACCESS_TOKEN}`
);
return resp;
} catch (err) {
// Handle Error Here
console.error(err);
}
};
Any help would be much appreciated.
Call your function like this:
getFacebookStats(link, ACCESS_TOKEN).then(response => {
console.log(response);
}).catch(error => {
console.error(error);
});
Or you could call it using await inside an async function.
Check this answer for a more detailed explaination of Promises in javascript.

Loading controller await problem with Ionic

In my ngOnInit page I call a function to present a Loading and then call my service to load data.
The problem is that the service call ends before the loading starts.
How is it possibile with await?
loading: any;
...
ngOnInit() {
this.presentLoading();
this.myService.get().subscribe((item)=>{
console.log('dismiss');
this.loading.dismiss();
}, ()=>{
this.loading.dismiss();
})
}
async presentLoading() {
this.loading = await this.loadingController.create({
message: 'Loading...',
duration: 20000
});
console.log('presentLoading')
await this.loading.present();
}
In console i can see:
dismiss
ERROR TypeError: Cannot read property 'dismiss' of undefined....
presentLoading
I’m using Ionic4.
In your case (based on the code) you have presentLoading function that returns a promise (async), so even though inside of it you are using await statements - inside the ngOnInit hook nothing instructs execution to await for the presentLoading.
You could do:
async ngOnInit() {
await this.presentLoading();
this.myService.get().subscribe((item)=>{
console.log('dismiss');
this.loading.dismiss();
}, ()=>{
this.loading.dismiss();
})
}
Also since you are using Onservables it may makes sense to call dismiss inside "completed" function:
async ngOnInit() {
await this.presentLoading();
this.myService.get().subscribe((item)=>{
console.log('dismiss');
}, (error)=>{
console.log(error);
}, (completed)=>{
this.loading.dismiss();
}
})
A note - making ngOnInit an async method does not "hurt", but its best to know a bit more waht implications it has: async/await in Angular `ngOnInit`

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 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'));
}
}