npm package: @hichchi/ngx-utils
Description: A utility library for Angular applications with HTTP interceptors, authentication services, and state management
Author: Waruna Udayanga
Latest version: 0.0.12

<!--suppress ALL -->

<div align="center">
  <h1>🔧 @hichchi/ngx-utils</h1>
  <p>
    <strong>A utility library for Angular applications with HTTP interceptors, authentication services, and state management</strong>
  </p>
  <p>
    <a href="https://www.npmjs.com/package/@hichchi/ngx-utils">
      <img src="https://img.shields.io/npm/v/@hichchi/ngx-utils?style=flat-square&color=blue" alt="npm version">
    </a>
    <a href="https://www.npmjs.com/package/@hichchi/ngx-utils">
      <img src="https://img.shields.io/npm/dm/@hichchi/ngx-utils?style=flat-square&color=green" alt="npm downloads">
    </a>
    <a href="https://github.com/hichchidev/hichchi/blob/main/LICENSE">
      <img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License">
    </a>
    <img src="https://img.shields.io/badge/angular-19.0.0-red?style=flat-square" alt="Angular Version">
  </p>
  <p>
    <em>Part of the <a href="https://github.com/hichchidev/hichchi">Hichchi</a> ecosystem - A powerful, scalable application built with Nx workspace</em>
  </p>
</div>

---

## 📦 Installation

```bash
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

```typescript
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

```typescript
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

```typescript
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

```bash
nx build ngx-utils
```

### Running unit tests

```bash
nx test ngx-utils
```

Tests are executed via [Jest](https://jestjs.io).

---

---

<div align="center">

**Made with ❤️ by [Hichchi Dev](https://github.com/hichchidev)**

[![Hichchi Ecosystem](https://img.shields.io/badge/🏠_Hichchi_Ecosystem-blue)](https://github.com/hichchidev/hichchi)
[![Report Bug](https://img.shields.io/badge/🐛_Report_Bug-red)](https://github.com/hichchidev/hichchi/issues)
[![Request Feature](https://img.shields.io/badge/✨_Request_Feature-green)](https://github.com/hichchidev/hichchi/issues)

_Building the future of Angular development, one commit at a time_

</div>

---

# 📖 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.

<!-- TypeDoc generated documentation will be appended below this point -->

---

## 📋 API Table of Contents

- [Classes](#classes)
  - [`abstract` CrudHttpService](#abstract-crudhttpservice)
- [Functions](#functions)
  - [apiInterceptor()](#apiinterceptor)
  - [createFormData()](#createformdata)
  - [errorResponseInterceptor()](#errorresponseinterceptor)
  - [extractSubdomain()](#extractsubdomain)
  - [getClosestScrollableElement()](#getclosestscrollableelement)
  - [isElementInView()](#iselementinview)
  - [isScrollable()](#isscrollable)
  - [isSuccessResponse()](#issuccessresponse)
  - [markFormDirty()](#markformdirty)
  - [replaceNulls()](#replacenulls)
  - [saveAsFile()](#saveasfile)
  - [skipNotify()](#skipnotify)
  - [skipNotifyContext()](#skipnotifycontext)
  - [validatedFormData()](#validatedformdata)
- [Interfaces](#interfaces)
  - [DataFormGroup](#dataformgroup)
  - [Patch the value for a form group](#patch-the-value-for-a-form-group)
  - [Reset the form group values](#reset-the-form-group-values)
  - [Reset the form group values and disabled status](#reset-the-form-group-values-and-disabled-status)
  - [Manually set the errors for a control](#manually-set-the-errors-for-a-control)
  - [Set the complete value for the form group](#set-the-complete-value-for-the-form-group)
  - [HttpError](#httperror)
  - [HttpGetOptions](#httpgetoptions)
  - [HttpGetOptionsPromise](#httpgetoptionspromise)
  - [HttpOptions](#httpoptions)
  - [HttpOptionsPromise](#httpoptionspromise)
- [Type Aliases](#type-aliases)
  - [DataFormControls](#dataformcontrols)
  - [DataFormValues](#dataformvalues)

## Classes

### `abstract` CrudHttpService

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:20](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L20)

#### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Mdl` _extends_ `Model`

</td>
<td>

`Model`

</td>
</tr>
</tbody>
</table>

#### Constructors

##### Constructor

```ts
new CrudHttpService<Mdl>(): CrudHttpService<Mdl>;
```

###### Returns

[`CrudHttpService`](#abstract-crudhttpservice)<`Mdl`>

#### Methods

##### delete()

###### Call Signature

```ts
delete<Res>(url, options?): Observable<Res>;
```

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:97](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L97)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

[`HttpOptions`](#httpoptions)

</td>
</tr>
</tbody>
</table>

###### Returns

`Observable`<`Res`>

###### Call Signature

```ts
delete<Res>(url, options?): Promise<Res>;
```

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:99](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L99)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

[`HttpOptionsPromise`](#httpoptionspromise)

</td>
</tr>
</tbody>
</table>

###### Returns

`Promise`<`Res`>

##### get()

###### Call Signature

```ts
get<Res>(url, options?): Observable<Res>;
```

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:50](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L50)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

[`HttpGetOptions`](#httpgetoptions)<`Mdl`>

</td>
</tr>
</tbody>
</table>

###### Returns

`Observable`<`Res`>

###### Call Signature

```ts
get<Res>(url, options?): Promise<Res>;
```

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:52](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L52)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

[`HttpGetOptionsPromise`](#httpgetoptionspromise)<`Mdl`>

</td>
</tr>
</tbody>
</table>

###### Returns

`Promise`<`Res`>

##### patch()

###### Call Signature

```ts
patch<Res, B>(
   url,
   body,
options?): Observable<Res>;
```

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:85](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L85)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
<tr>
<td>

`B`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`body`

</td>
<td>

`B`

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

[`HttpOptions`](#httpoptions)

</td>
</tr>
</tbody>
</table>

###### Returns

`Observable`<`Res`>

###### Call Signature

```ts
patch<Res, B>(
   url,
   body,
options?): Promise<Res>;
```

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:87](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L87)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
<tr>
<td>

`B`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`body`

</td>
<td>

`B`

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

[`HttpOptionsPromise`](#httpoptionspromise)

</td>
</tr>
</tbody>
</table>

###### Returns

`Promise`<`Res`>

##### post()

###### Call Signature

```ts
post<Res, B>(
   url,
   body,
options?): Observable<Res>;
```

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:61](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L61)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
<tr>
<td>

`B`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`body`

</td>
<td>

`B`

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

[`HttpOptions`](#httpoptions)

</td>
</tr>
</tbody>
</table>

###### Returns

`Observable`<`Res`>

###### Call Signature

```ts
post<Res, B>(
   url,
   body,
options?): Promise<Res>;
```

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:63](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L63)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
<tr>
<td>

`B`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`body`

</td>
<td>

`B`

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

[`HttpOptionsPromise`](#httpoptionspromise)

</td>
</tr>
</tbody>
</table>

###### Returns

`Promise`<`Res`>

##### put()

###### Call Signature

```ts
put<Res, B>(
   url,
   body,
options?): Observable<Res>;
```

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:73](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L73)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
<tr>
<td>

`B`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`body`

</td>
<td>

`B`

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

[`HttpOptions`](#httpoptions)

</td>
</tr>
</tbody>
</table>

###### Returns

`Observable`<`Res`>

###### Call Signature

```ts
put<Res, B>(
   url,
   body,
options?): Promise<Res>;
```

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:75](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L75)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
<tr>
<td>

`B`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`body`

</td>
<td>

`B`

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

[`HttpOptionsPromise`](#httpoptionspromise)

</td>
</tr>
</tbody>
</table>

###### Returns

`Promise`<`Res`>

##### request()

```ts
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](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L23)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Default type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`Res`

</td>
<td>

`unknown`

</td>
</tr>
<tr>
<td>

`Body`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`type`

</td>
<td>

`RequestType`

</td>
</tr>
<tr>
<td>

`url`

</td>
<td>

`string` | `string`\[]

</td>
</tr>
<tr>
<td>

`body`

</td>
<td>

`Body`

</td>
</tr>
<tr>
<td>

`options?`

</td>
<td>

| [`HttpGetOptions`](#httpgetoptions)<`Mdl`> | [`HttpGetOptionsPromise`](#httpgetoptionspromise)<`Mdl`>

</td>
</tr>
</tbody>
</table>

###### Returns

`Promise`<`Res`> | `Observable`<`Res`>

##### parseQuery()

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

Defined in: [libs/ngx-utils/src/lib/services/crud-http.service.ts:108](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L108)

###### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`T`

</td>
</tr>
</tbody>
</table>

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`options?`

</td>
<td>

| [`HttpGetOptions`](#httpgetoptions)<`T`> | [`HttpGetOptionsPromise`](#httpgetoptionspromise)<`T`>

</td>
</tr>
</tbody>
</table>

###### Returns

`HttpQuery`<`Model`>

#### Properties

<table>
<thead>
<tr>
<th>Property</th>
<th>Modifier</th>
<th>Type</th>
<th>Defined in</th>
</tr>
</thead>
<tbody>
<tr>
<td>

<a id="property-http"></a> `http`

</td>
<td>

`protected`

</td>
<td>

`HttpClient`

</td>
<td>

[libs/ngx-utils/src/lib/services/crud-http.service.ts:21](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/services/crud-http.service.ts#L21)

</td>
</tr>
</tbody>
</table>

## Functions

### apiInterceptor()

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

Defined in: [libs/ngx-utils/src/lib/interceptors/api.interceptor.ts:87](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/interceptors/api.interceptor.ts#L87)

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

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`apiBase`

</td>
<td>

`string`

</td>
<td>

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

</td>
</tr>
<tr>
<td>

`splitDomain?`

</td>
<td>

`string`

</td>
<td>

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

</td>
</tr>
<tr>
<td>

`tenant?`

</td>
<td>

`TenantSlug`

</td>
<td>

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

</td>
</tr>
</tbody>
</table>

#### Returns

`HttpInterceptorFn`

An `HttpInterceptorFn` that can be registered with Angular's `HttpClient`

#### Examples

```typescript
// Basic usage in app configuration
apiInterceptor("https://api.example.com");
```

```typescript
// Using environment configuration
apiInterceptor(environment.apiUrl);
```

```typescript
// 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
```

```typescript
// 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
```

```typescript
// 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](#extractsubdomain) Utility function for extracting subdomains from URLs

---

### createFormData()

```ts
function createFormData<T>(data): FormData;
```

Defined in: [libs/ngx-utils/src/lib/form/form.utils.ts:404](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/form/form.utils.ts#L404)

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

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`T` _extends_ `object`

</td>
<td>

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

</td>
</tr>
</tbody>
</table>

#### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`data`

</td>
<td>

`T`

</td>
<td>

Object containing the data to convert to FormData

</td>
</tr>
</tbody>
</table>

#### Returns

`FormData`

A FormData object ready for HTTP submission

#### Examples

```typescript
// 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();
```

```typescript
// 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),
    });
  }
}
```

```typescript
// 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);
  }
}
```

```typescript
// 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](#validatedformdata) Function for getting validated form data to use with this utility

---

### errorResponseInterceptor()

```ts
function errorResponseInterceptor(
  providerWithNotify,
  providerWithSignOut,
): HttpInterceptorFn;
```

Defined in: [libs/ngx-utils/src/lib/interceptors/error.interceptor.ts:140](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/interceptors/error.interceptor.ts#L140)

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

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`providerWithNotify`

</td>
<td>

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

</td>
<td>

Service provider type that implements error notification functionality

</td>
</tr>
<tr>
<td>

`providerWithSignOut`

</td>
<td>

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

</td>
<td>

Service provider type that implements user sign-out functionality

</td>
</tr>
</tbody>
</table>

#### Returns

`HttpInterceptorFn`

HttpInterceptorFn that can be used in Angular HTTP interceptor configuration

#### Examples

```typescript
// 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),
      ]),
    ),
  ],
};
```

```typescript
// 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]))],
};
```

```typescript
// 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"]);
  }
}
```

```typescript
// 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));
  }
}
```

```typescript
// 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](#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()

```ts
function extractSubdomain(splitDomain?): string | undefined;
```

Defined in: [libs/ngx-utils/src/lib/utils/http.utils.ts:69](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/utils/http.utils.ts#L69)

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

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`splitDomain?`

</td>
<td>

`string`

</td>
<td>

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

</td>
</tr>
</tbody>
</table>

#### Returns

`string` | `undefined`

The extracted subdomain if found, or `undefined` otherwise

#### Examples

```ts
extractSubdomain("example.com");
// On "admin.example.com" -> returns "admin"
```

```ts
extractSubdomain("example.com");
// On "localhost:3000" -> returns undefined
```

```ts
extractSubdomain("example.com");
// On "example.com" -> returns undefined (no subdomain)
```

---

### getClosestScrollableElement()

```ts
function getClosestScrollableElement(el): HTMLElement | null;
```

Defined in: [libs/ngx-utils/src/lib/utils/html.utils.ts:257](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/utils/html.utils.ts#L257)

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

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`el`

</td>
<td>

`HTMLElement`

</td>
<td>

The starting HTML element to search from

</td>
</tr>
</tbody>
</table>

#### Returns

`HTMLElement` | `null`

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

#### Examples

```typescript
// 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");
  }
}
```

```typescript
// 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 });
  }
}
```

```typescript
// 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](#isscrollable) Function used internally to determine scrollability
- [isElementInView](#iselementinview) Function that can be used with the returned scrollable element
- HTMLElement.parentElement DOM property used for tree traversal

---

### isElementInView()

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

Defined in: [libs/ngx-utils/src/lib/utils/html.utils.ts:153](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/utils/html.utils.ts#L153)

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

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`el`

</td>
<td>

`HTMLElement`

</td>
<td>

`undefined`

</td>
<td>

The target element to check for visibility

</td>
</tr>
<tr>
<td>

`container`

</td>
<td>

`HTMLElement`

</td>
<td>

`undefined`

</td>
<td>

The container element that defines the visible area

</td>
</tr>
<tr>
<td>

`threshold`

</td>
<td>

`number`

</td>
<td>

`0`

</td>
<td>

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

</td>
</tr>
</tbody>
</table>

#### Returns

`boolean`

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

#### Examples

```typescript
// 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
}
```

```typescript
// 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);
}
```

```typescript
// 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](#isscrollable) Function to check if an element is scrollable
- [getClosestScrollableElement](#getclosestscrollableelement) Function to find the nearest scrollable ancestor
- getBoundingClientRect DOM method used internally for position calculation

---

### isScrollable()

```ts
function isScrollable(el): boolean;
```

Defined in: [libs/ngx-utils/src/lib/utils/html.utils.ts:64](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/utils/html.utils.ts#L64)

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

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`el`

</td>
<td>

`HTMLElement`

</td>
<td>

The HTML element to check for scrollability

</td>
</tr>
</tbody>
</table>

#### Returns

`boolean`

True if the element is scrollable, false otherwise

#### Examples

```typescript
// 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
}
```

```typescript
// 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,
    );
  }
}
```

```typescript
// 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

- [getClosestScrollableElement](#getclosestscrollableelement) Function to find the nearest scrollable ancestor
- [isElementInView](#iselementinview) Function to check if an element is visible within a container

---

### isSuccessResponse()

```ts
function isSuccessResponse(body): body is SuccessResponse;
```

Defined in: [libs/ngx-utils/src/lib/utils/http.utils.ts:17](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/utils/http.utils.ts#L17)

#### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`body`

</td>
<td>

`unknown`

</td>
</tr>
</tbody>
</table>

#### Returns

`body is SuccessResponse`

---

### markFormDirty()

```ts
function markFormDirty(form): void;
```

Defined in: [libs/ngx-utils/src/lib/form/form.utils.ts:75](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/form/form.utils.ts#L75)

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

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`form`

</td>
<td>

`FormGroup`

</td>
<td>

The FormGroup to process recursively

</td>
</tr>
</tbody>
</table>

#### Returns

`void`

#### Examples

```typescript
// 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...
  }
}
```

```typescript
// 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](#validatedformdata) Function that uses this utility for validation

---

### replaceNulls()

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

Defined in: [libs/ngx-utils/src/lib/form/form.utils.ts:166](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/form/form.utils.ts#L166)

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

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`T`

</td>
<td>

The type of the object being processed

</td>
</tr>
</tbody>
</table>

#### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`obj`

</td>
<td>

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

</td>
<td>

Object that may contain null values to be removed

</td>
</tr>
</tbody>
</table>

#### Returns

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

A new object with null properties removed

#### Examples

```typescript
// Remove null values from form data
const formData = {
  name: "John Doe",
  email: "john@example.com",
  phone: null,
  address: null,
  age: 30,
};

const cleanData = replaceNulls(formData);
// Result: { name: 'John Doe', email: 'john@example.com', age: 30 }
```

```typescript
// 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
```

```typescript
// 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](#validatedformdata) Function that uses this utility to clean form data

---

### saveAsFile()

```ts
function saveAsFile(blob, filename): void;
```

Defined in: [libs/ngx-utils/src/lib/utils/file.utils.ts:36](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/utils/file.utils.ts#L36)

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

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`blob`

</td>
<td>

`Blob`

</td>
<td>

Blob to save.

</td>
</tr>
<tr>
<td>

`filename`

</td>
<td>

`string`

</td>
<td>

File name with extension.

</td>
</tr>
</tbody>
</table>

#### Returns

`void`

#### Throws

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

#### Examples

```TypeScript
// Save a text file
const textBlob = new Blob(['Hello, World!'], { type: 'text/plain' });
saveAsFile(textBlob, 'hello.txt');
```

```TypeScript
// Save a JSON file
const data = { name: 'John', age: 30 };
const jsonBlob = new Blob([JSON.stringify(data)], { type: 'application/json' });
saveAsFile(jsonBlob, 'user.json');
```

```TypeScript
// Save a file from an API response
fetch('https://example.com/api/document')
  .then(response => response.blob())
  .then(blob => {
    saveAsFile(blob, 'document.pdf');
  });
```

---

### skipNotify()

```ts
function skipNotify(value?): HttpContext;
```

Defined in: [libs/ngx-utils/src/lib/utils/http.utils.ts:9](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/utils/http.utils.ts#L9)

#### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Default value</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`value`

</td>
<td>

`boolean`

</td>
<td>

`false`

</td>
</tr>
</tbody>
</table>

#### Returns

`HttpContext`

---

### skipNotifyContext()

```ts
function skipNotifyContext(value?): object;
```

Defined in: [libs/ngx-utils/src/lib/utils/http.utils.ts:13](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/utils/http.utils.ts#L13)

#### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Default value</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`value`

</td>
<td>

`boolean`

</td>
<td>

`false`

</td>
</tr>
</tbody>
</table>

#### Returns

`object`

<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Defined in</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`context`

</td>
<td>

`HttpContext`

</td>
<td>

[libs/ngx-utils/src/lib/utils/http.utils.ts:13](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/utils/http.utils.ts#L13)

</td>
</tr>
</tbody>
</table>

---

### validatedFormData()

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

Defined in: [libs/ngx-utils/src/lib/form/form.utils.ts:278](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/form/form.utils.ts#L278)

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

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`T`

</td>
<td>

The type of the data structure represented by the form

</td>
</tr>
</tbody>
</table>

#### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`form`

</td>
<td>

[`DataFormGroup`](#dataformgroup)<`T`>

</td>
<td>

The DataFormGroup to validate and extract data from

</td>
</tr>
</tbody>
</table>

#### Returns

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

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

#### Examples

```typescript
// 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");
    }
  }
}
```

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

```typescript
// 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

- [DataFormGroup](#dataformgroup) Type-safe form group interface
- [markFormDirty](#markformdirty) Function used internally to mark invalid controls
- [replaceNulls](#replacenulls) Function used internally to clean the data

## Interfaces

### DataFormGroup

Defined in: [libs/ngx-utils/src/lib/form/form.interfaces.ts:254](https://github.com/hichchidev/hichchi/blob/451086b0863c82a6952d5ee0c05bf458abaaa227/libs/ngx-utils/src/lib/form/form.interfaces.ts#L254)

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

```typescript
// 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);
    }
  }
}
```

```typescript
// 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;
  }
}
```

```typescript
// 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

- [DataFormValues](#dataformvalues) Type for form values structure
- [DataFormControls](#dataformcontrols) Type for form controls structure
- UntypedFormGroup Angular's base form group class
- [validatedFormData](#validatedformdata) Function for extracting validated form data
- [markFormDirty](#markformdirty) Function for marking form controls as dirty

#### Extends

- `UntypedFormGroup`

#### Type Parameters

<table>
<thead>
<tr>
<th>Type Parameter</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`T`

</td>
<td>

The data type that the form represents

</td>
</tr>
</tbody>
</table>

#### Accessors

##### asyncValidator

###### Get Signature

```ts
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

```ts
set asyncValidator(asyncValidatorFn): void;
```

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

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`asyncValidatorFn`

</td>
<td>

`AsyncValidatorFn` | `null`

</td>
</tr>
</tbody>
</table>

###### Returns

`void`

###### Inherited from

```ts
UntypedFormGroup.asyncValidator;
```

##### dirty

###### Get Signature

```ts
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

```ts
UntypedFormGroup.dirty;
```

##### disabled

###### Get Signature

```ts
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

```ts
UntypedFormGroup.disabled;
```

##### enabled

###### Get Signature

```ts
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

```ts
UntypedFormGroup.enabled;
```

##### invalid

###### Get Signature

```ts
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

```ts
UntypedFormGroup.invalid;
```

##### parent

###### Get Signature

```ts
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

```ts
UntypedFormGroup.parent;
```

##### pending

###### Get Signature

```ts
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

```ts
UntypedFormGroup.pending;
```

##### pristine

###### Get Signature

```ts
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

```ts
set pristine(value): void;
```

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

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`value`

</td>
<td>

`boolean`

</td>
</tr>
</tbody>
</table>

###### Returns

`void`

###### Inherited from

```ts
UntypedFormGroup.pristine;
```

##### root

###### Get Signature

```ts
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

```ts
UntypedFormGroup.root;
```

##### status

###### Get Signature

```ts
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

```ts
set status(value): void;
```

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

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`value`

</td>
<td>

`FormControlStatus`

</td>
</tr>
</tbody>
</table>

###### Returns

`void`

###### Inherited from

```ts
UntypedFormGroup.status;
```

##### touched

###### Get Signature

```ts
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

```ts
set touched(value): void;
```

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

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`value`

</td>
<td>

`boolean`

</td>
</tr>
</tbody>
</table>

###### Returns

`void`

###### Inherited from

```ts
UntypedFormGroup.touched;
```

##### untouched

###### Get Signature

```ts
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

```ts
UntypedFormGroup.untouched;
```

##### updateOn

###### Get Signature

```ts
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

```ts
UntypedFormGroup.updateOn;
```

##### valid

###### Get Signature

```ts
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

```ts
UntypedFormGroup.valid;
```

##### validator

###### Get Signature

```ts
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

```ts
set validator(validatorFn): void;
```

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

###### Parameters

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>

`validatorFn`

</td>
<td>

`ValidatorFn` | `n