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

@oneteme/jquery-table

v0.0.3

Published

jquery table lib

Downloads

127

Readme

@oneteme/jquery-table

Bibliothèque Angular qui encapsule Angular Material Table avec une API orientée configuration runtime.

Features

  • Configuration déclarative du tableau via TableProvider
  • Colonnes optionnelles ajoutables/supprimables à l'exécution via menu View
  • Réordonnancement des colonnes par glisser-déposer
  • Tri natif Material par colonne
  • Recherche textuelle temps réel
  • Pagination standard et pagination par groupe
  • Group by : regroupement des lignes par colonne, groupes pliables/dépliables, pagination indépendante par groupe
  • Slice panel : filtres catégoriels latéraux, statiques (prédéfinis) ou dynamiques (colonne valeurs uniques), multi-sélection configurable
  • Chargement paresseux (lazy) de cellules via Observable par colonne
  • Rendus de cellule personnalisés via directive jqtCellDef
  • État de chargement (isLoading) et état vide configurable
  • Événement de clic sur ligne (rowSelected)
  • CSS variables pour la personnalisation visuelle complète
  • Compatible mode allégé : [dataSource] + [displayedColumns] sans config
  • Intégration @oneteme/jquery-core (DataProvider)

Installation

npm install @oneteme/jquery-core @oneteme/jquery-table @angular/material @angular/cdk

Utilisation rapide

import { TableComponent, TableProvider, col } from '@oneteme/jquery-table';

interface Row {
  id: number;
  name: string;
  status: 'active' | 'inactive';
  team: string;
}

@Component({
  imports: [TableComponent],
  template: `<jquery-table [config]="table" [data]="rows" (rowSelected)="onRow($event)"></jquery-table>`,
})
export class DemoComponent {
  rows: Row[] = [];

  table: TableProvider<Row> = {
    title: 'Utilisateurs',
    columns: [
      col('id',     'ID'),
      col('name',   'Nom',    { sortable: true }),
      col('status', 'Statut', { sliceable: true }),
      col('team',   'Équipe', { groupable: true, optional: true }),
    ],
    slices: [
      {
        title: 'Statut',
        columnKey: 'status',
        categories: [
          { key: 'active',   label: 'Actif',   filter: r => r.status === 'active' },
          { key: 'inactive', label: 'Inactif', filter: r => r.status === 'inactive' },
        ],
      },
    ],
    search:     { enabled: true },
    pagination: { enabled: true, pageSize: 20 },
    view:       { enabled: true, enableColumnDragDrop: true },
    export:     { enabled: true, filename: 'utilisateurs' },
  };

  onRow(row: Row) { console.log(row); }
}

Mode allégé compatibilité dataSource / displayedColumns

Pour une migration minimale depuis une mat-table existante :

<jquery-table
  [dataSource]="rows"
  [displayedColumns]="['id', 'name', 'status']"
  [columnLabels]="{ id: 'ID', name: 'Nom', status: 'Statut' }"
  [isLoading]="loading"
></jquery-table>

Le config complet reste disponible pour activer les fonctionnalités avancées.


API TableComponent

Inputs

| Propriété | Type | Description | |-----------|------|-------------| | config | TableProvider<T> | Configuration principale (colonnes, données, comportements) | | data | T[] | Données en entrée directe (remplace config.data) | | dataSource | T[] \| { data: T[] } | Alias compatibilité Material | | displayedColumns | string[] | Alias compatibilité Material clés de colonnes à afficher | | columnsConfig | TableColumnProvider<T>[] | Configuration des colonnes (remplace config.columns) | | columnLabels | Record<string, string> | Labels des colonnes pour le mode allégé | | isLoading | boolean | Affiche l'état de chargement (défaut : false) | | view | TableViewConfig | Surcharge config.view si défini (mode HTML) |

Outputs

| Événement | Payload | Description | |-----------|---------|-------------| | rowSelected | T | Ligne cliquée | | columnAdded | TableColumnProvider<T> | Colonne ajoutée aux colonnes actives | | columnRemoved | TableColumnProvider<T> | Colonne retirée des colonnes actives | | categorySelected | string | Catégorie de slice sélectionnée | | addRequested | void | Clic sur le bouton d'ajout de colonne |


API — TableProvider<T>

interface TableProvider<T = any> {
  columns?:      TableColumnProvider<T>[];
  title?:        string;

  slices?:            SliceConfig<T>[];    // Filtres catégoriels (slice panel)
  enableSliceToggle?: boolean;             // Défaut : true

  search?:       TableSearchConfig;
  pagination?:   TablePaginationConfig;
  view?:         TableViewConfig;
  labels?:       TableLabelsConfig;
  export?:       TableExportConfig<T>;

  defaultSort?:   { active: string; direction: 'asc' | 'desc' };
  rowClass?:      (row: T, index: number) => string | string[] | Record<string, boolean>;
}

Note : les données (data) et l’état de chargement (isLoading) sont des @Input séparés sur le composant, pas des champs de TableProvider.


API — TableColumnProvider<T>

interface TableColumnProvider<T = any> {
  key:        string;
  header?:    string;                  // Label de l'entête
  icon?:      string;                  // Icône Material (affiché dans l'entête)
  value?:     DataProvider<any>;       // (row, index) => valeur affichée
  sortValue?: DataProvider<any>;       // Valeur pour le tri si différente de value
  sortable?:  boolean;
  width?:     string;                  // Largeur CSS en px uniquement pour le calcul min-width (ex: '120px')
                                       // Les unités %, em, rem sont ignorées dans le calcul de tableMinWidth

  optional?:  boolean;                 // Colonne masquée par défaut, ajoutables via View menu
  removable?: boolean;                 // Peut être retirée manuellement

  groupable?: boolean;                 // Disponible comme critère de regroupement dans View menu
  sliceable?: boolean;                 // Disponible comme slice dynamique dans View menu
  searchValue?: DataProvider<string>;  // Valeur utilisée par la recherche texte (si différente de value)

  lazy?: {
    fetchFn: () => Observable<any[]>;  // Retourne un tableau dans le même ordre que les lignes
  };
}

Helper col()

Raccourci pour déclarer une colonne sans verbosité :

import { col } from '@oneteme/jquery-table';

columns: [
  col('name',   'Nom'),
  col('status', 'Statut', { sortable: false, groupable: true }),
  col('team',   'Équipe', { optional: true }),
]

API — Sous-configurations

TableSearchConfig

interface TableSearchConfig {
  enabled?:       boolean;
  initialQuery?:  string;     // Terme de recherche pré-rempli au chargement
  searchColumns?: string[];   // Restreint la recherche à ces clés de colonnes
}

TablePaginationConfig

interface TablePaginationConfig {
  enabled?:                boolean;
  pageSize?:               number;
  pageSizeOptions?:        number[];
  pageSizeOptionsGroupBy?: number[];   // Options spécifiques au mode Group by
}

TableViewConfig

interface TableViewConfig {
  enabled?:              boolean;   // Défaut : false  active le bouton View
  enableColumnRemoval?:  boolean;   // Défaut : true   autorise la suppression de colonnes
  enableColumnDragDrop?: boolean;   // Défaut : false  active le réordonnancement drag & drop
}

TableLabelsConfig

interface TableLabelsConfig {
  empty?:   string;   // Défaut : 'Aucune donnée' (ou la valeur i18n injectée)
  loading?: string;   // Défaut : 'Chargement des données...' (ou la valeur i18n injectée)
}

TableExportConfig<T>

interface TableExportConfig<T = any> {
  enabled?:   boolean;                             // Affiche le bouton Export
  filename?:  string;                              // Nom du fichier sans extension (défaut : 'export')
  transform?: (row: T) => Record<string, string>;  // Transforme chaque ligne avant export
}

L’export ne porte que sur les données filtrées (slice + recherche) et les colonnes visibles. Le fichier est généré avec un BOM UTF-8 pour une compatibilité Excel correcte.


i18n

Tous les labels de l’interface sont personnalisables via un InjectionToken :

import { JQT_I18N } from '@oneteme/jquery-table';

// Dans AppModule ou un provider racine
providers: [
  {
    provide: JQT_I18N,
    useValue: {
      searchPlaceholder: 'Search…',
      emptyState:        'No data',
      loadingState:      'Loading…',
      viewNoneSelected:  'None',
      groupRemove:       'Remove grouping',
      exportButtonLabel: 'Export',
    },
  },
]

Seuls les champs fournis écrasent les défauts français. Voir JqtI18n pour la liste complète (24 labels).


Fonctionnalité — Group by

Le regroupement s'active en ajoutant groupable: true sur une ou plusieurs colonnes. L'utilisateur choisit ensuite la colonne de regroupement depuis le menu View.

columns: [
  { key: 'team',   header: 'Équipe',  groupable: true },
  { key: 'status', header: 'Statut',  groupable: true },
  { key: 'name',   header: 'Nom' },
],
view:       { enabled: true },
pagination: {
  enabled: true,
  pageSizeOptionsGroupBy: [5, 10, 25],
},

Comportements inclus :

  • Groupes pliables/dépliables individuellement
  • Pagination indépendante par groupe
  • Tri des entêtes de groupe (asc / desc)
  • Scroll automatique vers l'entête du groupe actif

Fonctionnalité — Slice panel

Le slice panel est un panneau latéral de filtres catégoriels.

Slices statiques (catégories prédéfinies)

slices: [
  {
    title:     'Statut',
    icon:      'circle',
    columnKey: 'status',
    categories: [
      { key: 'active',   label: 'Actif',   filter: r => r.status === 'active' },
      { key: 'inactive', label: 'Inactif', filter: r => r.status === 'inactive' },
    ],
  },
  {
    title:       'Priorité',
    columnKey:   'priority',
    multiSelect: true,
    bucket:      r => r.priority,   // Auto-génère les catégories depuis les valeurs uniques
  },
],

Slices dynamiques (depuis le menu View)

Une colonne avec sliceable: true peut être ajoutée dynamiquement comme slice depuis le menu View.

columns: [
  { key: 'team', header: 'Équipe', sliceable: true },
],
view: { enabled: true },

SliceConfig<T>

interface SliceConfig<T = any> {
  title?:       string;
  icon?:        string;
  columnKey?:   string;
  multiSelect?: boolean;                     // Défaut : false
  hidden?:      boolean;                     // Masqué par défaut dans le panel
  categories?:  SliceCategory<T>[];
  bucket?:      (row: T) => string;          // Auto-génère les catégories (ignoré si categories défini)
}

interface SliceCategory<T = any> {
  key:    string;
  label:  string;
  filter: (row: T) => boolean;
}

Fonctionnalité — lazy columns

columns: [
  {
    key:    'details',
    header: 'Détails',
    lazy: {
      fetchFn: () => this.api.getDetails(),
    },
  },
],

Le composant gère l'état idle | loading | loaded | error par colonne, avec possibilité de relancer la requête en cas d'erreur.


Fonctionnalité — Cellules personnalisées (jqtCellDef)

<jquery-table [config]="table">

  <ng-template jqtCellDef="status" let-row>
    <span [class]="'badge badge-' + row.status">{{ row.status }}</span>
  </ng-template>

  <ng-template jqtCellDef="actions" let-row let-index="index">
    <button (click)="edit(row)">Éditer</button>
  </ng-template>

</jquery-table>

Contexte du template :

  • $implicit la ligne brute (T)
  • index index global de la ligne

Fonctionnalité — Clic sur ligne

<jquery-table [config]="table" (rowSelected)="onRow($event)"></jquery-table>

La ligne brute T est émise via l'Output (rowSelected). Pour appliquer une classe conditionnelle aux lignes, utiliser rowClass dans config :

config: TableProvider<Row> = {
  rowClass: (row) => row.status === 'error' ? 'row-error' : '',
};

Usage standalone — SlicePanelComponent

SlicePanelComponent est exporté et utilisable indépendamment du tableau, par exemple pour filtrer les données d'un graphique :

<jqt-slice-panel
  [sliceConfigs]="slices"
  [columns]="columns"
  [data]="rows"
  [showCounts]="true"
  (filterChange)="applyFilter($event)"
></jqt-slice-panel>

Inputs SlicePanelComponent

| Propriété | Type | Description | |-----------|------|-------------| | sliceConfigs | SliceConfig<T>[] | Configurations des slices | | columns | SliceColumnDef<T>[] | Définitions des colonnes pour la résolution des valeurs | | data | T[] | Données source | | lazyData | Map<string, Map<any,any>> | Valeurs lazy chargées | | lazyStatus | Map<string, 'idle'\|'loading'\|'loaded'\|'error'> | État par colonne lazy | | showToggle | boolean | Affiche le bouton collapse du panel (défaut : true) | | showCounts | boolean | Affiche le nombre de lignes par catégorie (défaut : true) | | collapsedByDefault | boolean | Les slices démarrent repliés (défaut : false) | | alwaysShow | boolean | Affiche le panel même si vide (défaut : false) |

Outputs SlicePanelComponent

| Événement | Payload | Description | |-----------|---------|-------------| | filterChange | (row: T) => boolean | Prédicat de filtre à appliquer | | activeKeysChange | string[][] | Clés actives par slice | | dynamicSliceKeysChange | string[] | Clés des slices dynamiques actives | | collapsedChange | boolean | État replié/déplié du panel |


Personnalisation visuelle — CSS variables

jquery-table {
  /* Texte */
  --jqt-title-color:       #1f2937;
  --jqt-text-color:        #111827;
  --jqt-text-secondary:    #6b7280;
  --jqt-text-muted:        #9ca3af;

  /* Surfaces */
  --jqt-surface-color:     #ffffff;
  --jqt-surface-alt-color: #f9fafb;
  --jqt-row-hover-bg:      #f3f4f6;

  /* Bordures */
  --jqt-border-color:      #e5e7eb;

  /* Group by */
  --jqt-group-bg:          #eef2f7;
  --jqt-group-bg-hover:    #e4ecf4;
  --jqt-group-accent:      #94a3b8;
  --jqt-group-border:      #d1d9e4;

  /* Accent & danger */
  --jqt-primary-color:     #1d4ed8;
  --jqt-danger-color:      #dc2626;
}

Utilitaires exportés

import { normalizeCellValue, humanizeKey, getFrenchPaginatorIntl } from '@oneteme/jquery-table';

| Fonction | Description | |----------|-------------| | normalizeCellValue(value) | Convertit n'importe quelle valeur de cellule en string affichable (gère null, Date, Array, objet {label} / {name}) | | humanizeKey(key) | Transforme camelCase / snake_case en label lisible (createdAt"Created at") | | col(key, header, overrides?) | Raccourci pour créer un TableColumnProvider en une ligne | | getFrenchPaginatorIntl() | Retourne un MatPaginatorIntl avec les labels en français |

normalizeCellValue utilise la locale navigateur (et non fr-FR) pour les dates.


Build

ng build @oneteme/jquery-table

Publishing

cd dist/oneteme/jquery-table
npm publish