npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hichchi/ngx-utils

v0.0.9

Published

A utility library for Angular applications with HTTP interceptors, authentication services, and state management

Readme


📦 Installation

npm install @hichchi/ngx-utils

🌟 Overview

This library provides a collection of utilities for Angular applications, including HTTP interceptors, authentication services, state management, and form utilities. It helps streamline common tasks in Angular development and promotes consistent implementation patterns.

✨ Key Features

  • 🌐 HTTP Interceptors: Pre-configured interceptors for API URLs, authentication, error handling, and response transformation
  • 🔐 Authentication Services: Services for handling user authentication and authorization
  • 📊 State Management: State management utilities for authentication and other application states
  • 📝 Form Utilities: Helper functions for working with Angular forms
  • 📋 Interface Definitions: TypeScript interfaces for consistent typing
  • 🛠️ Common Services: Reusable services for Angular applications

🚀 Usage

HTTP Interceptors

import { NgModule } from "@angular/core";
import { HTTP_INTERCEPTORS } from "@angular/common/http";
import {
  apiInterceptor,
  AuthInterceptor,
  ErrorInterceptor,
  ResponseInterceptor,
} from "@hichchi/ngx-utils/interceptors";

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: apiInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: ResponseInterceptor, multi: true },
  ],
})
export class AppModule {}

Authentication Service

import { Component } from "@angular/core";
import { AuthService } from "@hichchi/ngx-utils/services";

@Component({
  selector: "app-sign-in",
  template: `
    <form (submit)="signIn()">
      <input [(ngModel)]="username" name="username" placeholder="Username" />
      <input
        [(ngModel)]="password"
        name="password"
        type="password"
        placeholder="Password"
      />
      <button type="submit">Sign In</button>
    </form>
  `,
})
export class SignInComponent {
  username = "";
  password = "";

  constructor(private authService: AuthService) {}

  signIn() {
    this.authService
      .signIn({
        email: this.username,
        password: this.password,
      })
      .subscribe(
        (response) => console.log("Sign in successful", response),
        (error) => console.error("Sign in failed", error),
      );
  }
}

State Management

import { Component, OnInit } from "@angular/core";
import { AuthState } from "@hichchi/ngx-auth/state";

@Component({
  selector: "app-header",
  template: `
    <nav>
      <a routerLink="/">Home</a>
      <a *ngIf="isLoggedIn" routerLink="/profile">Profile</a>
      <button *ngIf="isLoggedIn" (click)="signOut()">Sign Out</button>
      <a *ngIf="!isLoggedIn" routerLink="/sign-in">Sign In</a>
    </nav>
  `,
})
export class HeaderComponent implements OnInit {
  isLoggedIn = false;

  constructor(private authState: AuthState) {}

  ngOnInit() {
    this.isLoggedIn = this.authState.signedIn();
  }

  signOut() {
    this.authState.signOut();
  }
}

🔧 Development

Building

nx build ngx-utils

Running unit tests

nx test ngx-utils

Tests are executed via Jest.



Made with ❤️ by Hichchi Dev

Hichchi Ecosystem Report Bug Request Feature

Building the future of Angular development, one commit at a time


📖 API Documentation

Complete technical reference for all classes, interfaces, methods, and types in this library.

Auto-generated by TypeDoc - Browse through detailed API references, code examples, and implementation guides below.


📋 API Table of Contents

Classes

abstract CrudHttpService

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:20

Type Parameters

Mdl extends Model

Model

Constructors

Constructor
new CrudHttpService<Mdl>(): CrudHttpService<Mdl>;
Returns

CrudHttpService<Mdl>

Methods

delete()
Call Signature
delete<Res>(url, options?): Observable<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:95

Type Parameters

Res

unknown

Parameters

url

string | string[]

options?

HttpOptions

Returns

Observable<Res>

Call Signature
delete<Res>(url, options?): Promise<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:97

Type Parameters

Res

unknown

Parameters

url

string | string[]

options?

HttpOptionsPromise

Returns

Promise<Res>

get()
Call Signature
get<Res>(url, options?): Observable<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:48

Type Parameters

Res

unknown

Parameters

url

string | string[]

options?

HttpGetOptions<Mdl>

Returns

Observable<Res>

Call Signature
get<Res>(url, options?): Promise<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:50

Type Parameters

Res

unknown

Parameters

url

string | string[]

options?

HttpGetOptionsPromise<Mdl>

Returns

Promise<Res>

patch()
Call Signature
patch<Res, B>(
   url,
   body,
options?): Observable<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:83

Type Parameters

Res

unknown

B

unknown

Parameters

url

string | string[]

body

B

options?

HttpOptions

Returns

Observable<Res>

Call Signature
patch<Res, B>(
   url,
   body,
options?): Promise<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:85

Type Parameters

Res

unknown

B

unknown

Parameters

url

string | string[]

body

B

options?

HttpOptionsPromise

Returns

Promise<Res>

post()
Call Signature
post<Res, B>(
   url,
   body,
options?): Observable<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:59

Type Parameters

Res

unknown

B

unknown

Parameters

url

string | string[]

body

B

options?

HttpOptions

Returns

Observable<Res>

Call Signature
post<Res, B>(
   url,
   body,
options?): Promise<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:61

Type Parameters

Res

unknown

B

unknown

Parameters

url

string | string[]

body

B

options?

HttpOptionsPromise

Returns

Promise<Res>

put()
Call Signature
put<Res, B>(
   url,
   body,
options?): Observable<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:71

Type Parameters

Res

unknown

B

unknown

Parameters

url

string | string[]

body

B

options?

HttpOptions

Returns

Observable<Res>

Call Signature
put<Res, B>(
   url,
   body,
options?): Promise<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:73

Type Parameters

Res

unknown

B

unknown

Parameters

url

string | string[]

body

B

options?

HttpOptionsPromise

Returns

Promise<Res>

request()
protected request<Res, Body>(
   type,
   url,
   body,
options?): Promise<Res> | Observable<Res>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:23

Type Parameters

Res

unknown

Body

unknown

Parameters

type

RequestType

url

string | string[]

body

Body

options?

| HttpGetOptions<Mdl> | HttpGetOptionsPromise<Mdl>

Returns

Promise<Res> | Observable<Res>

parseQuery()
static parseQuery<T>(options?): HttpQuery<Model>;

Defined in: libs/ngx-utils/src/lib/services/crud-http.service.ts:106

Type Parameters

T

Parameters

options?

| HttpGetOptions<T> | HttpGetOptionsPromise<T>

Returns

HttpQuery<Model>

Properties

http

protected

HttpClient

libs/ngx-utils/src/lib/services/crud-http.service.ts:21

Functions

apiInterceptor()

function apiInterceptor(apiBase, splitDomain?, tenant?): HttpInterceptorFn;

Defined in: libs/ngx-utils/src/lib/interceptors/api.interceptor.ts:87

Creates an HTTP interceptor that rewrites relative request URLs using a base API host and optionally attaches a tenant header for multi-tenant applications.

This interceptor allows Angular applications to:

  • Use relative request URLs in services and components
  • Automatically prepend a base API URL for consistency
  • Add a tenant identifier via a custom HTTP header (x-tenant) if provided or extracted from the current origin using splitDomain

How the interceptor works:

  • Requests that already start with the provided apiBase or with http:// or https:// are passed through unchanged
  • All other relative requests are rewritten as: ${apiBase}/${req.url}
  • If a tenant string is provided or a subdomain is extracted using splitDomain, it is added to the request headers using the TENANT_HEADER_KEY constant

Parameters

apiBase

string

The base API URL used to build relative request URLs (e.g., "https://api.example.com")

splitDomain?

string

Optional domain name used to extract subdomain from the current URL (e.g., "example.com")

tenant?

TenantSlug

Optional tenant identifier to attach via header (e.g., "tenant-a")

Returns

HttpInterceptorFn

An HttpInterceptorFn that can be registered with Angular's HttpClient

Examples

// Basic usage in app configuration
apiInterceptor("https://api.example.com");
// Using environment configuration
apiInterceptor(environment.apiUrl);
// With a static tenant
apiInterceptor("https://api.example.com", undefined, "tenant-a");
// Relative request 'users' -> 'https://api.example.com/users'
// Header 'x-tenant: tenant-a' is attached to the request
// Using splitDomain to automatically extract tenant from URL
// Current page URL: https://tenant123.example.com
apiInterceptor("https://api.example.com", "example.com");
// Relative request 'users' -> 'https://api.example.com/users'
// Header 'x-tenant: tenant123' is attached to the request
// In a service using relative URLs
@Injectable()
export class UserService {
  constructor(private http: HttpClient) {}

  getUsers() {
    // Relative URL becomes: https://api.example.com/users
    // Tenant header is added if specified or extracted
    return this.http.get("users");
  }

  getUserById(id: string) {
    return this.http.get(`users/${id}`);
  }

  // Absolute URLs are passed through unchanged
  getExternalData() {
    return this.http.get("https://external-api.com/data");
  }
}

See

  • HttpInterceptorFn Angular HTTP interceptor function type
  • HttpRequest Angular HTTP request interface
  • HEADER_TENANT_KEY Constant used to attach tenant header
  • extractSubdomain Utility function for extracting subdomains from URLs

createFormData()

function createFormData<T>(data): FormData;

Defined in: libs/ngx-utils/src/lib/form/form.utils.ts:404

Creates a FormData object from a plain JavaScript object

This utility function converts a plain object into a FormData object, which is required for multipart/form-data HTTP requests, particularly when uploading files or sending form data that includes binary content. The function handles different data types appropriately, preserving file names for File objects and converting other values to strings.

The function is particularly useful when working with Angular forms that need to submit both regular form fields and file uploads in a single request. It automatically handles the conversion of various data types to the format expected by FormData.

Key features:

  • Preserves original file names for File objects
  • Converts primitive values to strings
  • Maintains type safety with generic constraints
  • Handles Blob objects correctly
  • Creates multipart/form-data compatible output

Type Parameters

T extends object

Object type with string keys and values that can be converted to FormData

Parameters

data

T

Object containing the data to convert to FormData

Returns

FormData

A FormData object ready for HTTP submission

Examples

// Basic usage with mixed data types
const formData = createFormData({
  name: "John Doe",
  age: 30,
  isActive: true,
  avatar: fileInput.files[0], // File object
});

// Submit via HTTP
this.http.post("/api/users", formData).subscribe();
// File upload with metadata
export class FileUploadComponent {
  onFileUpload(file: File, description: string, isPublic: boolean) {
    const uploadData = createFormData({
      file: file,
      description: description,
      isPublic: isPublic,
      uploadedAt: new Date().toISOString(),
    });

    this.fileService.upload(uploadData).subscribe({
      next: (response) => console.log("Upload successful"),
      error: (error) => console.error("Upload failed", error),
    });
  }
}
// Using with form validation
export class ProfileFormComponent {
  profileForm = this.fb.group({
    name: ["", Validators.required],
    bio: [""],
    profilePicture: [null],
  });

  onSubmit() {
    const formValue = validatedFormData(this.profileForm);
    if (!formValue) return;

    // Convert to FormData for file upload
    const formData = createFormData({
      name: formValue.name,
      bio: formValue.bio || "",
      profilePicture: formValue.profilePicture,
      timestamp: Date.now(),
    });

    this.profileService.updateProfile(formData);
  }
}
// Multiple file upload
interface UploadRequest {
  title: string;
  category: string;
  document: File;
  thumbnail: File;
  isPrivate: boolean;
}

const uploadRequest: UploadRequest = {
  title: "My Document",
  category: "reports",
  document: documentFile,
  thumbnail: thumbnailFile,
  isPrivate: false,
};

const formData = createFormData(uploadRequest);
// FormData will contain:
// - title: "My Document"
// - category: "reports"
// - document: [File object with original name]
// - thumbnail: [File object with original name]
// - isPrivate: "false"

See

  • FormData Web API interface for form data
  • File Web API interface for file objects
  • Blob Web API interface for binary data
  • validatedFormData Function for getting validated form data to use with this utility

errorResponseInterceptor()

function errorResponseInterceptor(
  providerWithNotify,
  providerWithSignOut,
): HttpInterceptorFn;

Defined in: libs/ngx-utils/src/lib/interceptors/error.interceptor.ts:140

Creates an HTTP error response interceptor for Angular applications

This function creates an HTTP interceptor that handles error responses from API calls. It provides centralized error handling with support for authentication error detection, automatic user sign-out on unauthorized access, and configurable error notifications. The interceptor integrates with notification services and authentication services to provide a seamless error handling experience.

The interceptor distinguishes between different types of errors and handles them appropriately. It can detect known authentication errors, handle unauthorized access by automatically signing out users, and show error notifications based on request context configuration.

Key features:

  • Centralized HTTP error handling for all API requests
  • Authentication error detection and handling
  • Automatic user sign-out on unauthorized access
  • Configurable error notifications per request
  • Integration with notification and authentication services
  • Support for both client-side and server-side errors
  • Context-aware error handling based on request configuration

Parameters

providerWithNotify

Type<{ error: (message) => void; }>

Service provider type that implements error notification functionality

providerWithSignOut

Type<{ signOut: () => Observable<any>; }>

Service provider type that implements user sign-out functionality

Returns

HttpInterceptorFn

HttpInterceptorFn that can be used in Angular HTTP interceptor configuration

Examples

// Basic usage in app configuration
import { provideHttpClient, withInterceptors } from "@angular/common/http";
import { NotificationService } from "./services/notification.service";
import { AuthService } from "./services/auth.service";

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(
      withInterceptors([
        errorResponseInterceptor(NotificationService, AuthService),
      ]),
    ),
  ],
};
// Using with custom notification and auth services
import { ToastService } from "./services/toast.service";
import { UserAuthService } from "./services/user-auth.service";

const errorInterceptor = errorResponseInterceptor(
  ToastService,
  UserAuthService,
);

export const appConfig: ApplicationConfig = {
  providers: [provideHttpClient(withInterceptors([errorInterceptor]))],
};
// Service implementations that work with the interceptor
@Injectable()
export class NotificationService {
  error(message: string): void {
    // Show error notification to user
    this.toastr.error(message);
  }
}

@Injectable()
export class AuthService {
  signOut(): void {
    // Clear user session and redirect to login
    this.clearTokens();
    this.router.navigate(["/login"]);
  }
}
// Making HTTP requests with error notification control
import { HttpClient } from "@angular/common/http";
import { skipNotifyContext } from "@hichchi/ngx-utils";

@Injectable()
export class DataService {
  constructor(private http: HttpClient) {}

  // Request with error notifications enabled (default)
  getData() {
    return this.http.get("/api/data");
  }

  // Request with error notifications disabled
  getDataSilently() {
    return this.http.get("/api/data", skipNotifyContext(true));
  }
}
// Advanced usage with multiple interceptors
import { AuthInterceptor } from "./interceptors/auth.interceptor";
import { LoadingInterceptor } from "./interceptors/loading.interceptor";

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(
      withInterceptors([
        AuthInterceptor,
        LoadingInterceptor,
        errorResponseInterceptor(NotificationService, AuthService),
      ]),
    ),
  ],
};

See

  • HttpInterceptorFn Angular HTTP interceptor function type
  • HttpError Interface for HTTP error objects
  • NOTIFY_ERRORS Token for controlling error notification context
  • AuthErrorResponseCode Enum of known authentication error codes
  • HttpClientErrorStatus Enum of HTTP client error status codes

extractSubdomain()

function extractSubdomain(splitDomain?): string | undefined;

Defined in: libs/ngx-utils/src/lib/utils/http.utils.ts:69

Extract a subdomain from the current origin URL

This utility function parses the current page's URL (window.location.href) and extracts the subdomain portion relative to the provided main domain.

Behavior:

  • Returns the subdomain if the hostname contains one before the splitDomain
  • Returns undefined for single-label hostnames (e.g., localhost), IP addresses, or if no subdomain exists

Parameters

splitDomain?

string

The main domain used as reference for extraction (e.g., "example.com")

Returns

string | undefined

The extracted subdomain if found, or undefined otherwise

Examples

extractSubdomain("example.com");
// On "admin.example.com" -> returns "admin"
extractSubdomain("example.com");
// On "localhost:3000" -> returns undefined
extractSubdomain("example.com");
// On "example.com" -> returns undefined (no subdomain)

getClosestScrollableElement()

function getClosestScrollableElement(el): HTMLElement | null;

Defined in: libs/ngx-utils/src/lib/utils/html.utils.ts:257

Finds the closest scrollable ancestor element in the DOM tree

This utility function traverses up the DOM tree from a given element to find the nearest ancestor that is scrollable. It uses the isScrollable function to determine scrollability and returns the first scrollable parent element found.

This is useful for implementing scroll-related functionality that needs to work with the appropriate scrollable container, such as:

  • Implementing custom scroll behaviors
  • Adding scroll event listeners to the correct container
  • Calculating scroll positions relative to the scrollable parent
  • Implementing scroll-to-element functionality

Parameters

el

HTMLElement

The starting HTML element to search from

Returns

HTMLElement | null

The closest scrollable ancestor element, or null if none is found

Examples

// Find the scrollable container for a specific element
const targetElement = document.querySelector(".target-element");
if (targetElement) {
  const scrollableParent = getClosestScrollableElement(targetElement);

  if (scrollableParent) {
    console.log("Found scrollable parent:", scrollableParent);
    // Add scroll event listener to the correct container
    scrollableParent.addEventListener("scroll", handleScroll);
  } else {
    console.log("No scrollable parent found");
  }
}
// Implement scroll-to-element functionality
function scrollToElement(
  element: HTMLElement,
  behavior: ScrollBehavior = "smooth",
) {
  const scrollableContainer = getClosestScrollableElement(element);

  if (scrollableContainer) {
    // Calculate the position relative to the scrollable container
    const containerRect = scrollableContainer.getBoundingClientRect();
    const elementRect = element.getBoundingClientRect();
    const relativeTop =
      elementRect.top - containerRect.top + scrollableContainer.scrollTop;

    scrollableContainer.scrollTo({
      top: relativeTop,
      behavior,
    });
  } else {
    // Fallback to window scroll
    element.scrollIntoView({ behavior });
  }
}
// Use in Angular directive for scroll-based functionality
@Directive({
  selector: "[appScrollSpy]",
})
export class ScrollSpyDirective implements OnInit, OnDestroy {
  private scrollContainer: HTMLElement | null = null;
  private scrollListener?: () => void;

  constructor(private elementRef: ElementRef<HTMLElement>) {}

  ngOnInit() {
    this.scrollContainer = getClosestScrollableElement(
      this.elementRef.nativeElement,
    );

    if (this.scrollContainer) {
      this.scrollListener = () => this.onScroll();
      this.scrollContainer.addEventListener("scroll", this.scrollListener);
    }
  }

  ngOnDestroy() {
    if (this.scrollContainer && this.scrollListener) {
      this.scrollContainer.removeEventListener("scroll", this.scrollListener);
    }
  }

  private onScroll() {
    // Implement scroll spy logic
    if (
      this.scrollContainer &&
      isElementInView(this.elementRef.nativeElement, this.scrollContainer)
    ) {
      // Element is in view
      console.log("Element is visible in scroll container");
    }
  }
}

See

  • isScrollable Function used internally to determine scrollability
  • isElementInView Function that can be used with the returned scrollable element
  • HTMLElement.parentElement DOM property used for tree traversal

isElementInView()

function isElementInView(el, container, threshold?): boolean;

Defined in: libs/ngx-utils/src/lib/utils/html.utils.ts:153

Determines if an element is fully visible within a container element

This utility function checks whether a target element is completely visible within the bounds of a container element. It compares the bounding rectangles of both elements and optionally applies a threshold for more flexible visibility detection.

This is particularly useful for implementing features like:

  • Lazy loading of content when elements come into view
  • Scroll-based animations and transitions
  • Virtual scrolling implementations
  • Accessibility features that track visible content

Parameters

el

HTMLElement

undefined

The target element to check for visibility

container

HTMLElement

undefined

The container element that defines the visible area

threshold

number

0

Optional threshold in pixels for more flexible visibility detection (default: 0)

Returns

boolean

True if the element is fully visible within the container, false otherwise

Examples

// Check if a list item is visible in a scrollable container
const listItem = document.querySelector(".list-item");
const scrollContainer = document.querySelector(".scroll-container");

if (listItem && scrollContainer && isElementInView(listItem, scrollContainer)) {
  console.log("List item is fully visible");
  // Trigger animations or load additional content
}
// Use with a threshold for partial visibility detection
const image = document.querySelector(".lazy-image");
const viewport = document.querySelector(".viewport");

// Check if image is visible with 50px threshold
if (image && viewport && isElementInView(image, viewport, 50)) {
  // Load the image when it's within 50px of being visible
  loadImage(image);
}
// Implement scroll-based visibility tracking in Angular
@Component({
  selector: "app-scroll-tracker",
  template: `
    <div #container class="scroll-container" (scroll)="onScroll()">
      <div
        #item
        *ngFor="let item of items; trackBy: trackByFn"
        class="scroll-item"
        [class.visible]="item.isVisible"
      >
        {{ item.content }}
      </div>
    </div>
  `,
})
export class ScrollTrackerComponent {
  @ViewChild("container") container!: ElementRef<HTMLElement>;
  @ViewChildren("item") itemElements!: QueryList<ElementRef<HTMLElement>>;

  items = [
    { id: 1, content: "Item 1", isVisible: false },
    { id: 2, content: "Item 2", isVisible: false },
    // ... more items
  ];

  onScroll() {
    this.itemElements.forEach((itemRef, index) => {
      this.items[index].isVisible = isElementInView(
        itemRef.nativeElement,
        this.container.nativeElement,
        20, // 20px threshold
      );
    });
  }
}

See

  • isScrollable Function to check if an element is scrollable
  • getClosestScrollableElement Function to find the nearest scrollable ancestor
  • getBoundingClientRect DOM method used internally for position calculation

isScrollable()

function isScrollable(el): boolean;

Defined in: libs/ngx-utils/src/lib/utils/html.utils.ts:64

Determines if an HTML element is scrollable

This utility function checks whether an HTML element has scrollable content by examining its computed CSS overflow-y property and comparing its scroll height to its client height. An element is considered scrollable if it has overflow set to 'scroll' or 'auto' and its content exceeds the visible area.

This is useful for implementing scroll-related functionality, such as infinite scrolling, scroll position tracking, or determining whether scroll indicators should be shown.

Parameters

el

HTMLElement

The HTML element to check for scrollability

Returns

boolean

True if the element is scrollable, false otherwise

Examples

// Check if a container element is scrollable
const container = document.getElementById("content-container");
if (container && isScrollable(container)) {
  console.log("Container has scrollable content");
  // Add scroll event listeners or show scroll indicators
}
// Use in a component to conditionally show scroll indicators
@Component({
  selector: "app-scrollable-content",
  template: `
    <div #contentContainer class="content">
      <!-- content -->
    </div>
    <div *ngIf="showScrollIndicator" class="scroll-indicator">
      Scroll for more content
    </div>
  `,
})
export class ScrollableContentComponent implements AfterViewInit {
  @ViewChild("contentContainer") contentContainer!: ElementRef<HTMLElement>;
  showScrollIndicator = false;

  ngAfterViewInit() {
    this.showScrollIndicator = isScrollable(
      this.contentContainer.nativeElement,
    );
  }
}
// Check multiple elements for scrollability
const elements = document.querySelectorAll(".potential-scroll-container");
const scrollableElements = Array.from(elements).filter((el) =>
  isScrollable(el as HTMLElement),
);

console.log(`Found ${scrollableElements.length} scrollable elements`);

See


isSuccessResponse()

function isSuccessResponse(body): body is SuccessResponse;

Defined in: libs/ngx-utils/src/lib/utils/http.utils.ts:17

Parameters

body

unknown

Returns

body is SuccessResponse


markFormDirty()

function markFormDirty(form): void;

Defined in: libs/ngx-utils/src/lib/form/form.utils.ts:75

Recursively marks invalid form controls as dirty and touched

This utility function traverses a form hierarchy and marks all invalid controls as dirty and touched, which triggers validation error display in the UI. It works recursively through nested FormGroups and FormArrays to ensure all invalid controls are properly marked for error display.

The function is particularly useful when you want to show all validation errors at once, such as when a user attempts to submit a form. It only marks invalid controls, leaving valid controls unchanged.

Key features:

  • Recursive traversal of form hierarchy
  • Only marks invalid controls as dirty/touched
  • Handles nested FormGroups and FormArrays
  • Updates validation state after marking controls
  • Non-destructive (doesn't affect valid controls)

Parameters

form

FormGroup

The FormGroup to process recursively

Returns

void

Examples

// Mark all invalid controls in a form for error display
export class UserFormComponent {
  userForm = this.fb.group({
    name: ["", Validators.required],
    email: ["", [Validators.required, Validators.email]],
    address: this.fb.group({
      street: ["", Validators.required],
      city: ["", Validators.required],
    }),
  });

  onSubmit() {
    if (this.userForm.invalid) {
      // Mark all invalid fields to show errors
      markFormDirty(this.userForm);
      return;
    }
    // Process valid form...
  }
}
// Using with form arrays
export class DynamicFormComponent {
  form = this.fb.group({
    items: this.fb.array([
      this.fb.group({
        name: ["", Validators.required],
        quantity: [0, Validators.min(1)],
      }),
    ]),
  });

  validateAll() {
    markFormDirty(this.form);
    // All invalid controls in the array will be marked
  }
}

See

  • FormGroup Angular reactive form group
  • FormArray Angular reactive form array
  • validatedFormData Function that uses this utility for validation

replaceNulls()

function replaceNulls<T>(obj): { [K in string | number | symbol]?: T[K] };

Defined in: libs/ngx-utils/src/lib/form/form.utils.ts:166

Removes null values from an object by deleting properties with null values

This utility function creates a new object with all null properties removed. It's particularly useful when working with form data where null values should be omitted from API requests or when preparing data for processing that doesn't handle null values well.

The function performs a shallow copy of the object and removes any properties that have null values. Properties with undefined values are preserved, as they represent different semantic meaning (missing vs explicitly null).

Type Parameters

T

The type of the object being processed

Parameters

obj

{ [K in string | number | symbol]?: T[K] | null }

Object that may contain null values to be removed

Returns

{ [K in string | number | symbol]?: T[K] }

A new object with null properties removed

Examples

// Remove null values from form data
const formData = {
  name: "John Doe",
  email: "[email protected]",
  phone: null,
  address: null,
  age: 30,
};

const cleanData = replaceNulls(formData);
// Result: { name: 'John Doe', email: '[email protected]', age: 30 }
// Using with API request data
interface UserUpdate {
  name?: string | null;
  email?: string | null;
  phone?: string | null;
}

const updateData: UserUpdate = {
  name: "Jane Smith",
  email: null, // Don't update email
  phone: "555-1234",
};

const apiPayload = replaceNulls(updateData);
// Result: { name: 'Jane Smith', phone: '555-1234' }
// API receives only the fields to update
// Difference between null and undefined
const data = {
  field1: "value",
  field2: null, // Will be removed
  field3: undefined, // Will be preserved
};

const result = replaceNulls(data);
// Result: { field1: 'value', field3: undefined }

See

validatedFormData Function that uses this utility to clean form data


saveAsFile()

function saveAsFile(blob, filename): void;

Defined in: libs/ngx-utils/src/lib/utils/file.utils.ts:36

Save a Blob as a file by triggering a download in the browser. This function creates a temporary download link and triggers a click event to download the file.

Parameters

blob

Blob

Blob to save.

filename

string

File name with extension.

Returns

void

Throws

Throws an error if used in a Node.js environment.

Examples

// Save a text file
const textBlob = new Blob(['Hello, World!'], { type: 'text/plain' });
saveAsFile(textBlob, 'hello.txt');
// Save a JSON file
const data = { name: 'John', age: 30 };
const jsonBlob = new Blob([JSON.stringify(data)], { type: 'application/json' });
saveAsFile(jsonBlob, 'user.json');
// Save a file from an API response
fetch('https://example.com/api/document')
  .then(response => response.blob())
  .then(blob => {
    saveAsFile(blob, 'document.pdf');
  });

skipNotify()

function skipNotify(value?): HttpContext;

Defined in: libs/ngx-utils/src/lib/utils/http.utils.ts:9

Parameters

value

boolean

false

Returns

HttpContext


skipNotifyContext()

function skipNotifyContext(value?): object;

Defined in: libs/ngx-utils/src/lib/utils/http.utils.ts:13

Parameters

value

boolean

false

Returns

object

context

HttpContext

libs/ngx-utils/src/lib/utils/http.utils.ts:13


validatedFormData()

function validatedFormData<T>(
  form,
): { [K in string | number | symbol]: T[K] } | null;

Defined in: libs/ngx-utils/src/lib/form/form.utils.ts:278

Validates a form and returns clean data if valid, or null if invalid

This utility function combines form validation with data cleaning in a single operation. It first marks all invalid controls as dirty (to show validation errors), then checks if the form is valid. If valid, it returns the form data with null values removed. If invalid, it returns null.

This is particularly useful for form submission handlers where you want to:

  1. Show all validation errors if the form is invalid
  2. Get clean, validated data if the form is valid
  3. Handle both cases with a simple null check

The function uses the DataFormGroup type to ensure type safety between the form structure and the returned data type.

Type Parameters

T

The type of the data structure represented by the form

Parameters

form

DataFormGroup<T>

The DataFormGroup to validate and extract data from

Returns

{ [K in string | number | symbol]: T[K] } | null

The validated and cleaned form data, or null if the form is invalid

Examples

// Basic form validation and submission
export class UserFormComponent {
  userForm: DataFormGroup<UserData> = this.fb.group({
    name: ["", Validators.required],
    email: ["", [Validators.required, Validators.email]],
    phone: [null], // Optional field
    age: [null, Validators.min(18)],
  });

  onSubmit() {
    const validData = validatedFormData(this.userForm);
    if (validData) {
      // Form is valid, submit clean data
      this.userService.createUser(validData);
    } else {
      // Form is invalid, errors are now visible
      console.log("Please fix form errors");
    }
  }
}
// Using with async operations
export class ProfileComponent {
  profileForm: DataFormGroup<ProfileUpdate> = this.fb.group({
    firstName: ['', Validators.required],
    lastName: ['', Validators.required],
    bio: [null], // Optional
    website: [null, Validators.pattern(/^https?://.+/)]
  });

  async updateProfile() {
    const updateData = validatedFormData(this.profileForm);
    if (!updateData) {
      this.showErrorMessage('Please fix the form errors');
      return;
    }

    try {
      await this.profileService.update(updateData);
      this.showSuccessMessage('Profile updated successfully');
    } catch (error) {
      this.showErrorMessage('Failed to update profile');
    }
  }
}
// Type-safe form data extraction
interface ContactForm {
  name: string;
  email: string;
  message: string;
  newsletter?: boolean;
}

const contactForm: DataFormGroup<ContactForm> = this.fb.group({
  name: ["", Validators.required],
  email: ["", [Validators.required, Validators.email]],
  message: ["", [Validators.required, Validators.minLength(10)]],
  newsletter: [null],
});

const formData = validatedFormData(contactForm);
if (formData) {
  // TypeScript knows formData is ContactForm with null values removed
  console.log(formData.name); // string
  console.log(formData.email); // string
  console.log(formData.newsletter); // boolean | undefined (null was removed)
}

See

Interfaces

DataFormGroup

Defined in: libs/ngx-utils/src/lib/form/form.interfaces.ts:254

Interface for a type-safe Angular reactive form group

This interface extends Angular's UntypedFormGroup to provide strong typing for both form controls and form values. It ensures that the form structure matches the data type it represents, providing compile-time type safety and better developer experience.

The interface bridges the gap between Angular's form system and TypeScript's type system, allowing developers to work with forms in a type-safe manner while maintaining compatibility with Angular's reactive forms API.

Key benefits:

  • Type-safe access to form controls
  • Type-safe access to form values
  • IntelliSense support for form properties
  • Compile-time error detection for form structure mismatches
  • Seamless integration with form utility functions

Examples

// Define the data structure
interface ContactForm {
  firstName: string;
  lastName: string;
  email: string;
  phone?: string;
  message: string;
}

// Create a type-safe form
export class ContactComponent {
  contactForm: DataFormGroup<ContactForm> = this.fb.group({
    firstName: ["", Validators.required],
    lastName: ["", Validators.required],
    email: ["", [Validators.required, Validators.email]],
    phone: [null],
    message: ["", [Validators.required, Validators.minLength(10)]],
  });

  onSubmit() {
    // Type-safe form validation and data extraction
    const formData = validatedFormData(this.contactForm);
    if (formData) {
      // formData is properly typed as ContactForm
      this.contactService.sendMessage(formData);
    }
  }
}
// Advanced usage with nested forms
interface UserProfile {
  personal: {
    firstName: string;
    lastName: string;
    birthDate: Date;
  };
  contact: {
    email: string;
    phone: string;
  };
  preferences: {
    newsletter: boolean;
    notifications: boolean;
  };
}

export class ProfileComponent {
  profileForm: DataFormGroup<UserProfile> = this.fb.group({
    personal: this.fb.group({
      firstName: ["", Validators.required],
      lastName: ["", Validators.required],
      birthDate: [null, Validators.required],
    }),
    contact: this.fb.group({
      email: ["", [Validators.required, Validators.email]],
      phone: ["", Validators.required],
    }),
    preferences: this.fb.group({
      newsletter: [false],
      notifications: [true],
    }),
  });

  // Type-safe access to nested controls
  get emailControl() {
    return this.profileForm.controls.contact.controls.email;
  }
}
// Using with dynamic forms
interface DynamicField {
  id: string;
  label: string;
  value: string;
  required: boolean;
}

export class DynamicFormComponent {
  dynamicForm: DataFormGroup<Record<string, string>> = this.fb.group({});

  addField(field: DynamicField) {
    const validators = field.required ? [Validators.required] : [];
    this.dynamicForm.addControl(
      field.id,
      new FormControl(field.value, validators),
    );
  }

  getFormData() {
    return validatedFormData(this.dynamicForm);
  }
}

See

Extends

  • UntypedFormGroup

Type Parameters

T

The data type that the form represents

Accessors

asyncValidator
Get Signature
get asyncValidator(): AsyncValidatorFn | null;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2571

Returns the function that is used to determine the validity of this control asynchronously. If multiple validators have been added, this will be a single composed function. See Validators.compose() for additional information.

Returns

AsyncValidatorFn | null

Set Signature
set asyncValidator(asyncValidatorFn): void;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2572

Parameters

asyncValidatorFn

AsyncValidatorFn | null

Returns

void

Inherited from
UntypedFormGroup.asyncValidator;
dirty
Get Signature
get dirty(): boolean;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2659

A control is dirty if the user has changed the value in the UI.

Returns

boolean

True if the user has changed the value of this control in the UI; compare pristine. Programmatic changes to a control's value do not mark it dirty.

Inherited from
UntypedFormGroup.dirty;
disabled
Get Signature
get disabled(): boolean;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2626

A control is disabled when its status is DISABLED.

Disabled controls are exempt from validation checks and are not included in the aggregate value of their ancestor controls.

See

AbstractControl.status

Returns

boolean

True if the control is disabled, false otherwise.

Inherited from
UntypedFormGroup.disabled;
enabled
Get Signature
get enabled(): boolean;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2636

A control is enabled as long as its status is not DISABLED.

See

AbstractControl.status

Returns

boolean

True if the control has any status other than 'DISABLED', false if the status is 'DISABLED'.

Inherited from
UntypedFormGroup.enabled;
invalid
Get Signature
get invalid(): boolean;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2605

A control is invalid when its status is INVALID.

See

AbstractControl.status

Returns

boolean

True if this control has failed one or more of its validation checks, false otherwise.

Inherited from
UntypedFormGroup.invalid;
parent
Get Signature
get parent(): FormGroup<any> | FormArray<any> | null;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2576

The parent control.

Returns

FormGroup<any> | FormArray<any> | null

Inherited from
UntypedFormGroup.parent;
pending
Get Signature
get pending(): boolean;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2614

A control is pending when its status is PENDING.

See

AbstractControl.status

Returns

boolean

True if this control is in the process of conducting a validation check, false otherwise.

Inherited from
UntypedFormGroup.pending;
pristine
Get Signature
get pristine(): boolean;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2649

A control is pristine if the user has not yet changed the value in the UI.

Returns

boolean

True if the user has not yet changed the value in the UI; compare dirty. Programmatic changes to a control's value do not mark it dirty.

Set Signature
set pristine(value): void;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2650

Parameters

value

boolean

Returns

void

Inherited from
UntypedFormGroup.pristine;
root
Get Signature
get root(): AbstractControl;

Defined in: node_modules/@angular/forms/types/forms.d.ts:3201

Retrieves the top-level ancestor of this control.

Returns

AbstractControl

Inherited from
UntypedFormGroup.root;
status
Get Signature
get status(): FormControlStatus;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2585

The validation status of the control.

See

FormControlStatus

These status values are mutually exclusive, so a control cannot be both valid AND invalid or invalid AND disabled.

Returns

FormControlStatus

Set Signature
set status(value): void;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2586

Parameters

value

FormControlStatus

Returns

void

Inherited from
UntypedFormGroup.status;
touched
Get Signature
get touched(): boolean;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2666

True if the control is marked as touched.

A control is marked touched once the user has triggered a blur event on it.

Returns

boolean

Set Signature
set touched(value): void;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2667

Parameters

value

boolean

Returns

void

Inherited from
UntypedFormGroup.touched;
untouched
Get Signature
get untouched(): boolean;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2675

True if the control has not been marked as touched

A control is untouched if the user has not yet triggered a blur event on it.

Returns

boolean

Inherited from
UntypedFormGroup.untouched;
updateOn
Get Signature
get updateOn(): FormHooks;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2716

Reports the update strategy of the AbstractControl (meaning the event on which the control updates itself). Possible values: 'change' | 'blur' | 'submit' Default value: 'change'

Returns

FormHooks

Inherited from
UntypedFormGroup.updateOn;
valid
Get Signature
get valid(): boolean;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2596

A control is valid when its status is VALID.

See

AbstractControl.status

Returns

boolean

True if the control has passed all of its validation tests, false otherwise.

Inherited from
UntypedFormGroup.valid;
validator
Get Signature
get validator(): ValidatorFn | null;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2564

Returns the function that is used to determine the validity of this control synchronously. If multiple validators have been added, this will be a single composed function. See Validators.compose() for additional information.

Returns

ValidatorFn | null

Set Signature
set validator(validatorFn): void;

Defined in: node_modules/@angular/forms/types/forms.d.ts:2565

Parameters

validatorFn

ValidatorFn | `n