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 🙏

© 2025 – Pkg Stats / Ryan Hefner

ng-firebase-table-kxp

v1.0.7

Published

Uma biblioteca Angular poderosa para criar tabelas dinâmicas com integração completa ao Firebase Firestore

Readme

NG Firebase Table KXP

License: MIT

NG Firebase Table KXP is a production-ready Angular data table created by KXP Tech to power enterprise dashboards backed by Firebase Firestore. It wraps complex Firestore querying, pagination, filtering, and material design styling into a plug-and-play module so teams can ship data-rich experiences faster.

Table of Contents

Why Firebase Table KXP

  • Built and battle-tested at KXP Tech across projects with thousands of active users
  • Eliminates weeks of custom table work; drop it in and configure
  • Handles Firestore quirks (pagination, missing indexes, fallbacks) automatically
  • Provides a strongly typed API that scales with project complexity
  • Plays nicely with Angular Material, Firebase, and Angular Fire

Core Features

  • Full Firestore integration with server-side and client-side pagination
  • Text, date, and custom filters with automatic index fallback when needed
  • Configurable columns for relations, custom renderers, actions, and exports
  • Built-in CSV export hooks and actionable buttons per row
  • Pagination, sorting, and filter state shared between tabs
  • Optional color theming, tabbed datasets, and custom navigation per row
  • Works seamlessly with Angular 15, Angular Material, Angular Fire, and RxJS

Installation & Setup

npm install @adryanmmm/ng-firebase-table-kxp

The host application should already depend on:

  • Angular 15 packages: @angular/common, @angular/core, @angular/forms, @angular/router, @angular/cdk, @angular/material
  • Firebase stack: @angular/fire (7.x) and firebase (9.x)
  • Utilities: ngx-toastr (16.x), moment (2.29.x), ngx-mask (15.x)
  1. Import the module
import { NgFirebaseTableKxpModule } from '@adryanmmm/ng-firebase-table-kxp';

@NgModule({
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFirestoreModule,
    ToastrModule.forRoot(),
    NgxMaskModule.forRoot(),
    NgFirebaseTableKxpModule
  ]
})
export class AppModule {}
  1. Drop the component
@Component({
  selector: 'app-users',
  template: `
    <lib-table
      [data]="table"
      [downloadTable]="downloadTable">
    </lib-table>
  `
})
export class UsersComponent {
  table: TableData = {
    name: 'users',
    collection: 'users',
    collectionRef: this.firestore.collection('users').ref,
    pagination: true,
    download: true,
    displayedColumns: [
      { property: 'name', title: 'Name', isFilterable: true, isSortable: true },
      { property: 'email', title: 'Email', isFilterable: true }
    ]
  };

  downloadTable = (arrange: any, conditions: any[]) => {
    // export logic
  };

  constructor(private firestore: AngularFirestore) {}
}
  1. Make sure global styles include
@import '@angular/material/prebuilt-themes/indigo-pink.css';
@import 'ngx-toastr/toastr';

Configuration Overview

  • TableData defines the table behavior: source collection, pagination, sorting, tabs, exported totals, and custom navigation.
  • Column describes each displayed column: filters, relations, custom templates, icon actions, download buttons, and data formatting.
  • Condition lets you predefine Firestore where clauses applied before any user filters.
  • Optional hooks like filterFn, actionButton, and tabs enable richer UX without duplicating logic.
  • Automatic client-side fallback when Firestore reports missing composite indexes, plus logging of the index link to a missingIndexes collection.
  • Support for joining related collections, counting related documents per row, and managing dialog-driven actions via iconClass or actionButton handlers.
  • Compatible with SSR, lazy-loaded modules, and Angular standalone components.

API Reference

This section provides detailed documentation for all configuration interfaces available in the library.

TableData

The main configuration object that defines the entire table behavior.

| Property | Type | Required | Description | |----------|------|----------|-------------| | name | string | ✅ | Unique identifier for the table. Used internally for caching and state management. | | collection | string | ✅ | Name of the Firestore collection to query. | | collectionRef | CollectionReference | ✅ | Reference to the Firestore collection. Use firestore.collection('name').ref. | | displayedColumns | Column[] | ✅ | Array of column definitions. Defines what data to display and how. See Column. | | pagination | boolean | ✅ | Enable or disable pagination. When true, data is loaded in batches. | | download | boolean | ✅ | Enable or disable the export/download functionality. | | sortBy | {field: string, order: OrderByDirection} | ❌ | Default sorting configuration. order can be 'asc' or 'desc'. | | conditions | Condition[] | ❌ | Array of Firestore where clauses applied before user filters. See Condition. | | filterFn | (item: any) => boolean | ❌ | Custom client-side filter function. Applied after Firestore queries. | | filterableOptions | FilterableOption[] | ❌ | Predefined filter options displayed as buttons. See FilterableOption. | | url | string | ❌ | Base URL for row navigation. Row clicks navigate to {url}/{row.id}. | | isNotClickable | boolean | ❌ | When true, disables row click navigation. | | color | {bg: string, text: string} | ❌ | CSS classes for custom table theming. bg for background, text for text color. | | totalRef | {ref: DocumentReference, field: string}[] | ❌ | References to documents containing total counts. Displayed in the table footer. | | actionButton | ActionButton | ❌ | Configuration for a primary action button (e.g., "Add New"). | | tabs | Tab | ❌ | Configuration for tabbed data views. See Tab & TabData. |

ActionButton Properties:

  • label (string): Button text
  • routerLink (string): Navigation route
  • icon (string): CSS class for icon (e.g., FontAwesome)
  • colorClass (string): CSS class for button styling
  • method ((row, event) => any): Custom click handler
  • condition ((row) => boolean): Function to conditionally show the button

Example:

const tableData: TableData = {
  name: 'products',
  collection: 'products',
  collectionRef: this.firestore.collection('products').ref,
  pagination: true,
  download: true,
  sortBy: { field: 'createdAt', order: 'desc' },
  conditions: [
    { operator: '==', firestoreProperty: 'active', dashProperty: true }
  ],
  displayedColumns: [/* ... */],
  actionButton: {
    label: 'Add Product',
    routerLink: '/products/new',
    icon: 'fa fa-plus',
    colorClass: 'bg-blue-500'
  }
};

Column

Defines how each column is displayed, filtered, and interacted with.

| Property | Type | Required | Description | |----------|------|----------|-------------| | property | string | ✅ | Name of the property in the data object to display. | | title | string | ❌ | Column header text. Defaults to property if not provided. | | charLimit | number | ❌ | Maximum characters to display. Shows tooltip with full text on hover. | | pipe | PipeTransform | ❌ | Angular pipe for formatting values (e.g., DatePipe, CurrencyPipe). | | calculateValue | (row: any) => any | ❌ | Function to compute the display value from the row data. | | isSortable | boolean | ❌ | Enable sorting for this column. | | isFilterable | boolean | ❌ | Enable text-based filtering for this column. | | isFilterableByDate | boolean | ❌ | Enable date range filtering. Shows date picker inputs. | | filterPredicates | string[] | ❌ | Additional properties to include when filtering this column. | | hasLink | boolean \| string | ❌ | Make the cell value a clickable link. If string, uses as the navigation path. | | hasDownload | boolean \| string | ❌ | Add download icon to the cell. If string, uses as the download URL property. | | arrayField | string | ❌ | When data is an array of objects, specify which field to display. | | method | (row: any, event?: any) => any | ❌ | Custom click handler for the cell. | | image | Image | ❌ | Configuration for displaying images. See Image. | | iconClass | IconClass[] | ❌ | Array of icon/button configurations for action buttons in the cell. | | relation | Relation | ❌ | Configuration for joining related collection data. | | queryLength | QueryLength | ❌ | Configuration for counting related documents. |

IconClass Properties:

  • class (string): CSS classes for the icon/button
  • text (string): Text to display alongside icon
  • condition ((row) => any): Function to conditionally show the icon
  • buttonMethod ((row, event) => any): Click handler for the icon

Relation Properties:

  • collection (string): Name of the related collection
  • property (string): Property in current row containing the related document ID
  • newProperty (string): Property from related document to fetch and display

QueryLength Properties:

  • collection (string): Collection to count documents from
  • property (string): Field to match in the query
  • operator (WhereFilterOp): Firestore operator (e.g., '==', '>')
  • value (string): Property from current row to use as query value

Example:

const columns: Column[] = [
  {
    property: 'name',
    title: 'Product Name',
    isFilterable: true,
    isSortable: true,
    charLimit: 50
  },
  {
    property: 'price',
    title: 'Price',
    pipe: new CurrencyPipe('en-US'),
    isSortable: true
  },
  {
    property: 'createdAt',
    title: 'Created',
    pipe: new DatePipe('en-US'),
    isFilterableByDate: true
  },
  {
    property: 'categoryName',
    title: 'Category',
    relation: {
      collection: 'categories',
      property: 'categoryId',
      newProperty: 'name'
    }
  },
  {
    property: 'actions',
    title: 'Actions',
    iconClass: [
      {
        class: 'fa fa-edit text-blue-500 cursor-pointer',
        buttonMethod: (row) => this.editProduct(row)
      },
      {
        class: 'fa fa-trash text-red-500 cursor-pointer',
        buttonMethod: (row) => this.deleteProduct(row),
        condition: (row) => row.canDelete === true
      }
    ]
  }
];

Tab & TabData

Configure tabbed views for switching between different data sets within the same table.

Tab Interface:

| Property | Type | Required | Description | |----------|------|----------|-------------| | method | (tab: any, event?: any) => any | ✅ | Function called when a tab is clicked. Use to switch data or apply filters. | | tabsData | TabData[] | ✅ | Array of tab configurations. |

TabData Interface:

| Property | Type | Required | Description | |----------|------|----------|-------------| | label | string | ✅ | Text displayed on the tab. | | counter | number | ❌ | Optional counter badge displayed next to the label. | | counterClass | string | ❌ | CSS class for styling the counter badge. |

Example:

const tableData: TableData = {
  // ... other config
  tabs: {
    method: (tab, event) => {
      if (tab.label === 'Active') {
        this.loadActiveProducts();
      } else if (tab.label === 'Inactive') {
        this.loadInactiveProducts();
      }
    },
    tabsData: [
      { label: 'Active', counter: 42, counterClass: 'bg-green-500' },
      { label: 'Inactive', counter: 8, counterClass: 'bg-gray-500' },
      { label: 'All' }
    ]
  }
};

FilterableOption

Predefined filter buttons that users can click to apply common filters.

| Property | Type | Required | Description | |----------|------|----------|-------------| | title | string | ✅ | Label for the filter group. | | items | FilterItem[] | ✅ | Array of individual filter options. |

FilterItem Properties:

  • property (string): Property to filter on
  • value (string | boolean): Value to filter by
  • label (string): Text displayed on the filter button

Example:

const filterableOptions: FilterableOption[] = [
  {
    title: 'Status',
    items: [
      { property: 'status', value: 'active', label: 'Active' },
      { property: 'status', value: 'pending', label: 'Pending' },
      { property: 'status', value: 'archived', label: 'Archived' }
    ]
  },
  {
    title: 'Category',
    items: [
      { property: 'category', value: 'electronics', label: 'Electronics' },
      { property: 'category', value: 'clothing', label: 'Clothing' }
    ]
  }
];

Condition

Firestore where clauses that are always applied to queries, before any user filters.

| Property | Type | Required | Description | |----------|------|----------|-------------| | operator | WhereFilterOp | ✅ | Firestore comparison operator: '==', '!=', '<', '<=', '>', '>=', 'array-contains', 'in', 'array-contains-any', 'not-in'. | | firestoreProperty | string | ✅ | Name of the field in Firestore to filter on. | | dashProperty | string \| string[] | ✅ | Value or array of values to compare against. Can be a static value or a property name from your component. |

Example:

const conditions: Condition[] = [
  {
    operator: '==',
    firestoreProperty: 'tenantId',
    dashProperty: this.currentTenantId
  },
  {
    operator: '>=',
    firestoreProperty: 'createdAt',
    dashProperty: this.startDate
  },
  {
    operator: 'in',
    firestoreProperty: 'status',
    dashProperty: ['active', 'pending']
  }
];

Arrange

Internal interface used for managing sort and filter state. Automatically handled by the table component.

| Property | Type | Description | |----------|------|-------------| | filters | FilterState[] | Array of active filters per column. | | sortBy | {field: string, order: OrderByDirection} | Current sort configuration. | | elementId | {property: string, value: string} | Optional identifier for highlighting a specific row. |

FilterState Properties:

  • arrange ('ascending' | 'descending' | 'filter' | 'filterByDate' | 'equals' | ''): Type of filter/sort applied
  • filter ({property: string, filtering: string}): Text filter configuration
  • dateFilter ({initial: Date, final: Date}): Date range filter

Image

Configuration for displaying images in table cells.

| Property | Type | Required | Description | |----------|------|----------|-------------| | class | string | ✅ | CSS classes for styling the image element. | | path | string | ❌ | Property name containing the image path/URL in the row data. | | url | boolean | ❌ | If true, treats the value as a complete URL. Otherwise, constructs path from storage. | | default | string | ❌ | Default image URL if the actual image is missing or fails to load. |

Example:

const column: Column = {
  property: 'avatar',
  title: 'Photo',
  image: {
    class: 'w-10 h-10 rounded-full object-cover',
    path: 'photoURL',
    url: true,
    default: '/assets/default-avatar.png'
  }
};

Data Export (Download)

The library provides a flexible export system that allows you to download table data with the currently applied filters, sorting, and conditions.

How It Works

  1. Pass a download handler to the table component via the [downloadTable] input
  2. User clicks the download button in the table UI
  3. Library calls your handler with current arrange (filters/sort state) and conditions (where clauses)
  4. Your handler fetches all data using TableService.getItemsData(), transforms it, and generates the file

Basic Example

import { TableService } from '@adryanmmm/ng-firebase-table-kxp';
import * as XLSX from 'xlsx';
import moment from 'moment';

export class UsersComponent {
  constructor(private tableService: TableService) {}

  // Pass this method to [downloadTable]
  downloadTable = async (arrange: Arrange, conditions: Condition[]) => {
    // 1. Fetch all data with current filters
    const rawData = await this.tableService.getItemsData(
      'users',           // collection name
      arrange,           // current sort/filter state
      conditions         // optional where conditions
    );

    // 2. Transform data to desired format
    const xlsxData = rawData.map(user => ({
      'Name': user.fullName,
      'Email': user.email,
      'Phone': user.phoneNumber,
      'Created': new Date(user.createdAt.seconds * 1000).toLocaleDateString()
    }));

    // 3. Generate Excel file
    const worksheet = XLSX.utils.json_to_sheet(xlsxData);
    const workbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, worksheet, 'Users');
    
    // 4. Download file
    const fileName = `Users_${moment().format('DD-MM-YYYY-HH-mm-ss')}.xlsx`;
    XLSX.writeFile(workbook, fileName);
  }
}

Advanced Example with Totals

downloadOrdersTable = async (arrange: Arrange, conditions: Condition[]) => {
  const rawData = await this.tableService.getItemsData(
    'orders',
    arrange,
    conditions
  );

  let totalAmount = 0;

  // Map data and calculate totals
  const xlsxData = rawData.map(order => {
    totalAmount += order.amount;
    return {
      'Order ID': order.id,
      'Customer': order.customerName,
      'Amount': order.amount,
      'Date': new Date(order.createdAt.seconds * 1000).toLocaleDateString(),
      'Status': order.status
    };
  });

  // Add totals row
  xlsxData.push({
    'Order ID': '',
    'Customer': '',
    'Amount': totalAmount,
    'Date': 'TOTAL',
    'Status': ''
  });

  const worksheet = XLSX.utils.json_to_sheet(xlsxData);
  const workbook = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Orders');
  
  const fileName = `Orders_${moment().format('DD-MM-YYYY-HH-mm-ss')}.xlsx`;
  XLSX.writeFile(workbook, fileName);
}

Filtering Data Before Export

You can apply additional client-side filters based on user permissions:

downloadTable = async (arrange: Arrange, conditions: Condition[]) => {
  const rawData = await this.tableService.getItemsData('orders', arrange, conditions);

  // Filter based on user permissions
  const filteredData = rawData.filter(order => {
    if (this.currentUser.role === 'Admin') return true;
    if (this.currentUser.storeId === order.storeId) return true;
    return false;
  });

  // ... continue with export
}

Using Custom Pipes for Formatting

Apply Angular pipes to format data in the export:

import { DatePipe, CurrencyPipe } from '@angular/common';

downloadTable = async (arrange: Arrange, conditions: Condition[]) => {
  const rawData = await this.tableService.getItemsData('products', arrange);
  
  const datePipe = new DatePipe('en-US');
  const currencyPipe = new CurrencyPipe('en-US');

  const xlsxData = rawData.map(product => ({
    'Product': product.name,
    'Price': currencyPipe.transform(product.price),
    'Created': datePipe.transform(product.createdAt.toDate(), 'short'),
    'Status': product.active ? 'Active' : 'Inactive'
  }));

  // ... continue with export
}

CSV vs XLSX Format

// Export as XLSX (default)
XLSX.writeFile(workbook, 'data.xlsx');

// Export as CSV
XLSX.writeFile(workbook, 'data.csv', { bookType: 'csv', type: 'binary' });

Important Notes

  • The download property in TableData must be true to show the download button
  • TableService.getItemsData() returns all data matching filters (ignores pagination)
  • The method is async because it fetches data from Firestore
  • You control the final file format, column names, and data transformations
  • The library provides the current filter/sort state; you handle the actual file generation

Powered by KXP Tech

Firebase Table KXP was designed inside KXP Tech to accelerate data-heavy application development. If you are looking for expert consultancy on Firebase, Angular, or enterprise dashboards, reach out at kxptech.com.

Contributing & License

Contributions, feedback, and feature requests are welcome. Fork the repository, open a pull request, or start a discussion on GitHub.

This project is released under the MIT License. See the LICENSE file for details.

Support the Project

If this library saves you time, please star the repository and share it with your team.