Is it possible to implement lazy loading for data in TypeScript classes?

Looking to optimize my Angular application's data structure when consuming a RESTful API. My goal is to only load necessary data from the server on demand.

For instance, if I have a collection of Building objects each with a set of tenant IDs in an array instead of full Tenant objects. This way, when listing buildings in the app, I can display basic details and fetch individual tenant information from the API asynchronously only when needed. It helps avoid fetching all tenants upfront for every building.

Is this a common approach in web applications? Struggling to find resources on this specific topic, especially implementations tailored for Angular.

Appreciate any insights or Angular-specific examples on implementing this strategy!

Answer №1

I've been pondering this same dilemma myself. Here are a few potential strategies:

  1. Load everything at once - Simply retrieve all the data from your REST server upfront, as you mentioned. While this is convenient, it may not scale well with nested data structures or large amounts of data. However, it could be suitable if the data is only used at a single nesting level and is relatively small for each object, or if performance and bandwidth concerns are minimal.

The other options explore asynchronous approaches to retrieving data, where the Building REST route returns the Building object along with a TenantsURL for accessing the tenant list.

  1. Lazy TypeScript getters: Conceal the variable behind a getter in your class:

    class Building {
    
        public constructor(private readonly httpService: HttpClient){}
    
        public get tenants(): Observable<Tenant[]> {
            return this.httpService.get<Tenant[]>([url here]);
        }
    
    }
    

    A drawback here is that using tenants in an HTML template will cause angular to call this getter function during each change detection step, potentially adding costs depending on latency and data size. Another downside is the requirement for the HttpClient Service (or a custom service) injected into your models, blurring the line between services and models.

  2. Standalone Get Function: A slight tweak to #2, creating a class method in your model that can be called:

    class Building {
    
        public constructor(){}
    
        public getTenants(httpService: HttpClient): Observable<Tenant[]> {
            return httpService.get<Tenant[]>([url here]);
        }
    
    }
    

    This shifts the responsibility for providing the "getter" service (HttpClient in this case) from model construction to whoever needs to access the tenants, such as an Angular component. You can then use an Async pipe in an HTML template to display the values, or subscribe in an Angular component. However, since this is a function, it will be invoked during every change detection cycle, impacting performance.

  3. Pipe: Create a custom async pipe, TenantPipe, allowing injection of necessary services to retrieve Tenant data from a Building (https://angular.io/guide/pipes). You can then apply the pipe on the Building in an HTML template to asynchronously fetch the list of tenants. By separating models from the async retrieval functionality, angular will execute the pipe only once per change detection cycle. While more focused on HTML templates, pipes can also be injected into component typescript for similar functionality.

  1. Service: Develop a service, TenantService, featuring a method
    getTenantFromBuilding(building: Building): Observable<Tenant[]>
    . Utilize this in your typescript components wherever needed. This approach mirrors #4 but encapsulates the functionality within a service rather than a pipe with injected services. More oriented towards Typescript, the returned value from the service can still be displayed in an HTML template.

Each approach carries its own advantages and drawbacks, so choosing the right one depends on the context at hand.

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

Issue with detecting window resize event in Angular 7 service

I have a unique service that utilizes a ReplaySubject variable for components, but strangely the WindowResize event isn't triggering. import { Injectable, HostListener } from '@angular/core'; import { ReplaySubject } from 'rxjs'; ...

Attempting to convert numerical data into a time format extracted from a database

Struggling with formatting time formats received from a database? Looking to convert two types of data from the database into a visually appealing format on your page? For example, database value 400 should be displayed as 04:00 and 1830 as 18:30. Here&apo ...

Angular2's use of promises, observables, and Dependency Injection (

If I have a service that looks like this import {Injectable} from 'angular2/core'; @Injectable() export class MyService { search(oSrchParams){ let promise = () => new Promise((resolve, reject) => Meteor.call('mockSe ...

Angular is unable to load additional routes

While working on building a web application with Angular 11, I encountered an issue with routing. When navigating from the initial route ( { path: '', component: HomeComponent } ) to other routes, everything functions as expected. However, when ...

Methods for assigning values to a formControl using an array

I have an array of objects and I am attempting to loop through the array, dynamically setting values to a formControl and not displaying anything if the value is null. I have searched for similar solutions but haven't found any references or examples ...

What is the best way to integrate Bootstrap v4 into the most recent version of Angular?

npm install --save bootstrap I find the new version of Bootstrap to be less user-friendly compared to v4. Is there a way to install a specific older version of Bootstrap in an Angular project without getting the latest one? ...

Looking for the final entry in a table using AngularJS

Hey everyone, I'm dealing with a table row situation here <tbody> <tr *ngFor="let data of List | paginate : { itemsPerPage: 10, currentPage: p }; let i = index"> <td>{{ d ...

Master the art of iterating through an Object in TypeScript

I need help with looping through an Object in TypeScript. While the following examples work in JavaScript, I understand why they pose a problem in TypeScript. Unfortunately, I am struggling to find the correct approach to solve this issue. Am I approaching ...

What are the benefits of maintaining a property as non-observable instead of observable in knockout.js?

In my TypeScript project utilizing Knockout.js, I have a class with several properties. One of these properties is 'description', which is not directly tied to the DOM but needs to be used in popups triggered by certain mouse events (such as butt ...

Tips for personalizing your Compodoc Angular documentation

I've been experimenting with adding extra side navigation menus to the current compodoc documentation. Here's an example of how I tried to accomplish this: menu-wc.js <li class="link"> <a href="dependencies.html" data-type="chapte ...

A guide to iterating over an array and displaying individual elements in Vue

In my application, there is a small form where users can add a date with multiple start and end times which are then stored in an array. This process can be repeated as many times as needed. Here is how the array structure looks: datesFinal: {meetingName: ...

Is there a source where I can locate type definitions for Promise objects?

In the process of creating a straightforward class called Primrose, I am extending the global Promise object in order to include additional methods like resolve and reject. export class Primrose<Resolution> extends Promise<Resolution>{ priv ...

Broadcasting events across the entire system

I'm trying to accomplish something specific in Angular2 - emitting a custom event globally and having multiple components listen to it, not just following the parent-child pattern. Within my event source component, I have: export class EventSourceCo ...

Tips for utilizing chodorowicz / ts-debounce effectively

Looking to utilize the debounce function provided by the ts-debounce package (available at here) in my typescript project. However, struggling to find a concrete example of its usage in typescript. Would greatly appreciate any help or guidance on this ma ...

Removing the enclosing HTML tag in Angular reactive Forms

I am utilizing a reactive custom control in my code: <div customFormControl formControlName="old"></div> In the component, the selector is defined as: selector: '[customFormControl]', Is there a way to remove the surrounding mar ...

Is fetching JSON API data in ReactJS done correctly?

Struggling with ES6 to perform a seemingly simple task, I am attempting to fetch JSON API data for Bitcoin from three different websites: The problem lies in the fact that all these sites provide only a single endpoint leading directly to the price value ...

Issue with Webpack Build Excluding JSON Resource Files

My Webpack build is not including the resources folder in the dist build, resulting in the translation files not being picked up and causing the translations to not take place... File structure: dist //The json files from src/resources need to be incl ...

Incorporating HTTP headers into Angular 6

Could someone confirm if this method is correct for adding headers to http requests in Angular 6? Upon inspecting the call through SwaggerUI, it appears that the required headers are: url -X GET --header 'Accept: application/json' --header &apo ...

How should I structure my MySQL tables for efficiently storing a user's preferences in a map format?

My current project involves developing a web application that provides administrators with the ability to manage user information and access within the system. While most user details like name, email, and workID are straightforward, I am facing difficulty ...

Develop a Typescript interface containing all the necessary properties for a specific JSX component

My goal is to create a ControlledInputComponent that consists of a label and an input inside a div. I aim to make it highly customizable as I plan on using it in various ways. At the moment, I have included all the necessary elements, but I would like to e ...