The AOC Framework
github logodiscord logo

FRONTEND

<aoc-grid> #

This component is used to display a table (or list) of models, with pagination and a toolbar.

Inputs #

Name Type Description
modelConfig AocModelConfig The model-config
columns AocGridColumn[] Array of columns to define the grid
restOptions AocRestOptions The loading options for the rest api
where AocFilterQuery Search conditions that will be merged with restOptions
groupColumns AocGridGroupColumn[][] Headers for column groupings
addSearchInput boolean Add a text input for searching
searchInputPlaceholder string Text "Search..."
buttonConfig AocGridToolbarButtonConfig Toolbar button configuration
customSort (sortEvent: AocUiTableCustomSortEvent,
queryOrderMapArray: AocQueryOrderMap[]) => void
Function to define custom column sorting
rowLimits AocUiPaginatorRowLimitOptions Define row limits for the paginator
groupConfig AocGridGroupConfig Group configuration (groups are row groupings)
emptyGroupDescriptor string Label for rows not belonging to any group
autoExpandAllRows boolean Auto-expand all rows
rowNgStyle AocGridRowNgStyle Style for rows, can be a function
rowNgClass AocGridRowNgClass Class for rows, can be a function
selectMode 'single' or 'multiple' (default) or null/undefined Single selection, multiple selection, or no selection allowed
autoSelectFirst boolean (defaults to false) Autoselect first item after loading
selectionStyle 'normal' or 'checkbox' Selection style, normal with control and shift, or with checkboxes
modelEmitter AocModelEmitter Emitter for model selection
modelListener AocModelListener Structure for managing changes in the model
dynamicFormGroupConfig AocDynFormGroup Configuration of dynamic FormGroup

Outputs #

Name Type Description
whereChange AocFilterQuery Emits the change in the where condition
restOptionsChange AocRestOptions Emits the change in the restOptions
selectionChange Array Emits the change in the model selection
modelsChange Array Emits the change in models
loadingChange boolean Emits the change in the loading state

Example #

<aoc-grid [modelConfig]="modelConfig" [columns]="columns">
  <ng-template aocGridCell="current" let-isCurrent="value">
    <span *ngIf="isCurrent" class="material-symbols-rounded">check</span>
  </ng-template>
</aoc-grid>
protected modelConfig = inject(FiscalYearModelConfig);
protected columns: AocGridColumn<FiscalYear>[] = [
  {
    header: FiscalYear.i18n.IS_CURRENT,
    display: [ FiscalYear.field.IS_CURRENT, aocUiTplRef('current') ],
    size: '8rem',
    align: 'center'
  },
  {
    header: FiscalYear.i18n.YEAR,
    display: FiscalYear.field.YEAR,
    defaultSort: 'desc'
  }
];

Complete example at quest-client/src/app/features/schemas/common/fiscal-year/fiscal-year-grid.component.ts

Advanced Example #

In this example grid for clients (Customer), we have columns for code, legal name, trade name, phones, and email. Additionally, in the first column, we will draw a birthday cake if it's the client's birthday.

<aoc-grid [modelConfig]="modelConfig" [columns]="columns" [where]="where" [restOptions]="restOptions">
  <!-- Add some filters to the right of the toolbar -->
  <ng-template aocUiToolbar="right" [formGroup]="filterFormGroup">
    <aoc-ui-item>
      <input type="checkbox" aocUiInputCheckbox="Today's birthdate" formControlName="byBirthday">
    </aoc-ui-item>
    <aoc-ui-item>
      <app-gender-autocomplete allow="none" formControlName="byGender" placeholder="Filter by gender..."></app-gender-autocomplete>
    </aoc-ui-item>
  </ng-template>
  <!-- Draw cake icon if it's the customer birthday -->
  <ng-template aocGridCell="birthday" let-isBirthday="value">
    <span *ngIf="isBirthday" class="material-symbols-rounded" aocUiTooltip="Todays is his/her day...">cake</span>
  </ng-template>
  <!-- Email template to be able to send a mail via mailto -->
  <ng-template aocGridCell="email" let-email="value">
    <a *ngIf="email" href="mailto:{{email}}" target="_blank">{{email}}</a>
  </ng-template>
  <!-- Expander to show the full address -->
  <ng-template aocUiTableTemplate="rowExpansion" let-rowData>
    <p>{{rowData.addressTemplate.street_number ?? 'No number'}} {{rowData.addressTemplate.street_name}} {{rowData.addressTemplate.streetSuffix.name}}</p>
    <p>
      Additional data: {{rowData.addressTemplate.additional_data ?? 'None'}} |
      Floor: {{rowData.addressTemplate.floor ?? 'None'}} |
      Door: {{rowData.addressTemplate.door ?? 'None'}} |
      Block: {{rowData.addressTemplate.block ?? 'None'}} |
      Area: {{rowData.addressTemplate.area ?? 'None'}}
    </p>
    <p>{{rowData.addressTemplate.city}} - {{rowData.addressTemplate.state}} - {{rowData.addressTemplate.zip_code}} - {{rowData.addressTemplate.country.name}}</p>
  </ng-template>
</aoc-grid>
ngOnInit() {
  const today = new Date();
  this.columns = [
    {
      header: '',
      display: [
        Customer.field.BIRTHDATE,
        (birthdate: Date) => getDayOfYear(birthdate) === getDayOfYear(today),
        aocUiTplRef('birthday')
      ],
      size: '4rem',
      align: 'center',
      sortable: false
    },
    {
      header: 'Code',
      display: Customer.field.CODE,
      defaultSort: 'asc',
      size: '8rem',
      align: 'right'
    },
    {
      header: 'Legal name',
      display: [ Customer.embedded.LEGAL_DATA_TEMPLATE, (ldt: LegalDataTemplate) => `${ldt.legal_name} (${ldt.document_number})` ],
      orderBy: {
        legalDataTemplate: { legal_name: 'auto' }
      }
    },
    {
      header: 'Trade name',
      display: Customer.field.TRADE_NAME
    },
    {
      header: 'Phones',
      display: customer => [customer.phone1, customer.phone2].filter(p => p?.trim()).join(' - '),
      orderBy: {
        phone1: 'auto',
        phone2: 'auto'
      }
    },
    {
      header: 'Email',
      display: [ Customer.field.EMAIL, aocUiTplRef('email') ],
      orderBy: { email: 'auto' }
    }
  ];

  this.filterSubscription = this.filterFormGroup.valueChanges.subscribe(filters => {
    this.where = {};
    if (filters.byGender) {
      this.where.gender = filters.byGender;
    }
    if (filters.byBirthday) {
      this.restOptions.filters = { filterByBirthday: {} }
    } else {
      this.restOptions.filters = {};
    }
  });
}

Complete example at quest-client/src/app/features/schemas/customers/customer/customer-grid.component.ts

Api #

Full definition in the API.

Please note, browse Issues and Discussions in Github for more information

© 2025 Atlantis of Code. All rights reserved.
All trademarks are the property of their respective owners.