Determine if all resources on a page in Angular 4 have finished loading by keeping a loader spinning until everything is fully loaded

As part of my work on an Angular app, I am developing a loader to enhance user experience.

While the typical approach involves utilizing a boolean parameter for subscribing to HTTP requests, in my case, the service's response consists of multiple image URLs since the page is heavily image-based.

However, I encountered an issue where the loader stops before all images finish loading due to slower network connections, causing frustration among users.

In an attempt to address this, I experimented with JavaScript's load event to monitor when all resources have completed loading and then stop the loader. Unfortunately, it seems I'm unable to modify the loader's status from within the listener function.

Below is a snippet of what I've tried:

// The TypeScript component 
isLoading: boolean;

ngOnInit() {
  this.isLoading = true;
  this.checkIfLoaded();
}

checkIfLoaded() {
  window.addEventListener("load", function (event) {
    console.log("All resources finished loading!");
    // At this point, I should take action like returning false or...
    // ...adjusting the isLoading value, but accessing isLoading here appears difficult.
  });
}


// The template
<ng-container *ngIf="isLoading">
  <app-spinner></app-spinner>
</ng-container>

Environment: Angular 4.4 Any assistance or insights on this matter would be greatly appreciated! Thank you.

Answer №1

To ensure your component is ready after initialization, simply have it implement AfterViewInit interface and within the ngAfterViewInit() method, set isLoading to false.

class YourComponent implements AfterViewInit {
    // ...
    ngAfterViewInit() {
        this.isLoading = false;
    }
}

No need to add extra event handlers as Angular takes care of that through its lifecycle callbacks.

Answer №2

The main issue you're facing is that you are not correctly binding to the necessary events in your code.

If your goal is to determine whether the images have loaded or not, you must first create them and then wait for them to finish loading.

To address this problem, start by fetching your images, create corresponding HTML elements to load them, ensure all images have loaded successfully, and eventually showcase them on your page:

hasImagesLoaded: boolean[];

this.myService.getImages().subscribe((urls: string[]) => {
  // Initialize all image loading statuses as false
  this.hasImagesLoaded = urls.map(url => false);

  // Process each image individually
  urls.forEach((url, index) => {
    let img = new Image(); // Create a new HTML image element
    img.onload = () => {
      // Mark the current image as loaded
      this.hasImagesLoaded[index] = true;
      
      // Check if all images are now loaded to update loading status
      this.isLoading = !this.hasImagesLoaded.some(loadedStatus => !loadedStatus);
    };
    
    // Trigger the image loading process
    img.src = url;
  });
});

Once this process is complete, you can proceed with displaying your images using any preferred method.

Answer №3

To stop the loading spinner, utilize the ngAfterViewInit lifecycle hook and update the isLoading variable to false within it.

TS

export class MyClass implements AfterViewInit {
  isLoading: boolean;

  constructor() {
    this.isLoading = true;
  }

  ngAfterViewInit() {
    this.isLoading = false;
  }
}

HTML

<app-spinner *ngIf="isLoading"></app-spinner>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What are the steps to executing a function that instantiates an object?

Here is an object with filter values: const filters = ref<filterType>({ date: { value: '', }, user: { value: '', }, userId: { value: '', }, ... There is a data sending function that takes an obje ...

I'm noticing that my CSS is behaving differently than expected. Despite setting position: absolute, the output is displaying as inline-block instead of block. Why is this happening

div { width:200px; height:200px; position: absolute; } .first-container { background-color: #9AD0EC; } .second-container { background-color: red; left: 200px; } .third-container { background-color: blue; left:400px; } Despite setting th ...

Is it possible to attach a mouse click event to styled text?

Is there a way to specify a mouse click event for an element with a decoration applied to the text, matched with regex? The option to specify a hoverMessage is available, but I would like to find a way to execute a function based on which decorated text ...

Update the list upon creation of an item

In my Angular 7 project, I have a CreatePostComponent with the following code: export class CreatePostComponent { form: FormGroup; onSubmit() { this.postService.create(request).subscribe( (response) => { this.form.reset(); }, (err ...

Creating a dynamic image gallery with varying image dimensions using JavaScript and Bootstrap

Struggling with aligning an image gallery featuring images of varying sizes? I don't want to set the size programmatically as it may not look good on different screens. The additional challenge is dealing with white spaces between images and not knowi ...

What is the proper way to utilize environment variables on Heroku for my Angular application?

Currently, I am facing difficulties setting up environment variables (or Config Vars in the Heroku world) such as production=true for my angular app on Heroku. I'm struggling to configure the postinstall and build scripts to make use of them effective ...

Sanitize input data prior to using express-validator in a Node.js application

In my Node.js project, I am utilizing the V4 syntax of express-validator as recommended: const { check, validationResult } = require('express-validator/check'); const { matchedData } = require('express-validator/filter'); Additionally ...

How can I ensure that Redux-saga waits for API calls to resolve instead of returning promises continuously? Is there a way to make "yield call" wait for API calls to complete?

Where I'm initiating the API request: function fetchCharacter(value){ return axios.get(`https://www.breakingbadapi.com/api/characters?name=${value}`) .then(res=>{ console.log(res.data) }) .cat ...

What are the steps for adding node packages to sublime text?

Is there a way to install node packages directly from Sublime Text instead of using the command line? If so, what is the process for doing this? I'm not referring to Package Control; I'm specifically interested in installing npm packages like th ...

Showing fixed values inside directive view after successful injection

Looking for some answers about using constants in angularjs. Here are the constants defined in my app.js: ... angular .module('blocTime', ['firebase', 'ui.router']) .config(config) .constant(&apos ...

Activate Jquery to display the submenu when clicked and conceal any other open submenus at the same time

I'm trying to create a responsive menu with menus and submenus using JQuery. However, as a newbie to JQuery, I'm struggling to hide a previous submenu when displaying another one. Here's the CodePen link Below is the HTML code: <nav cl ...

Leveraging JavaScript within a Polymer component

I have an object made with polymer: <newfolder-element id="newfolderelement" popupStyle="width: 362px; height: 100px;"> <span class="title">Create a new folder</span> <input type="text" class="ginput" style="width: 350px; padd ...

Using JavaScript, generate table rows and cells

Hey there, I'm struggling with formatting my table correctly within the designated section. Currently, it's printing the rows one below the other instead of creating a 'tr' and multiple 'td' elements for each input field. The ...

Using Promise.all for multiple function calls

I have several functions set up like this: private async p1(): Promise<Result> { let p1; // Do some operations. return p1; } private async p5(): Promise<void> { // Make a call to an external API. } Some of these functions c ...

I encounter an error in my JavaScript function indicating that it is not defined

let element = document.querySelector("#value"); let buttons = document.querySelectorAll(".btn"); buttons.forEach(function (button) { button.addEventListener("click", function(event){ console.log(event.currentTarge ...

Angular HTML Component Refactor causes compatibility issues with BS4 classes

Currently, I am working on Angular components and I have a specific section that I would like to refactor into a separate component for reusability. Initially, when the HTML block with only Bootstrap 4 classes is placed in the parent component, the user in ...

"Exploring the power of Node.js by utilizing ObjectArray and implementing

Can I compare two arrays of objects in JavaScript? My goal is to find the common objects between these two arrays: First object array: [ { id_0: 356, name_0: 'xxxxx', id_1: 33, name_1: 'yyyyyy', id_ ...

I was anticipating only one request, but unexpectedly uncovered two requests. Now I need to figure out how to test for multiple requests

I am currently developing an Angular application and implementing Jasmine for testing purposes. My goal is to test for two similar HTTP requests within a single method, such as ngOnInit(). In my ngOnInit() method, there are two HTTP requests being called ...

JavaScript functions triggered upon page reload or refresh

How can I trigger a function from a FireFox extension/GM Script every time a page reloads or refreshes? Imagine this scenario: I visit a website that prompts for a username and password. My code fills in the credentials and submits them. The page reload ...

The NextJS API route functions flawlessly when tested locally, generating over 200 records. However, upon deployment to Vercel, the functionality seems to

Here is the API route that I am using: https://i.stack.imgur.com/OXaEx.png Below is the code snippet: import type { NextApiRequest, NextApiResponse } from "next"; import axios from "axios"; import prisma from "../../../lib/prisma ...