# BaseGridEditor

> _Since v0.5.0_

Base class for grid cell editors.

Provides common functionality for Angular cell editors:
- Automatic value resolution from FormControl or value input
- Common inputs (value, row, column, control)
- Common outputs (commit, cancel)
- Validation state helpers

## Usage

```typescript
import { Component } from '@angular/core';
import { BaseGridEditor } from '@toolbox-web/grid-angular';

@Component({
  selector: 'app-my-editor',
  template: `
    <input
      [value]="currentValue()"
      [class.is-invalid]="isInvalid()"
      (input)="commitValue($event.target.value)"
      (keydown.escape)="cancelEdit()"
    />
    @if (hasErrors()) {
      <div class="error">{{ firstErrorMessage() }}</div>
    }
  `
})
export class MyEditorComponent extends BaseGridEditor<MyRow, string> {
  // Override to customize error messages
  protected override getErrorMessage(errorKey: string): string {
    if (errorKey === 'required') return 'This field is required';
    if (errorKey === 'minlength') return 'Too short';
    return super.getErrorMessage(errorKey);
  }
}
```

## Template Syntax

When using the base class, you only need to pass the control:

```html
<tbw-grid-column field="name">
  <app-my-editor *tbwEditor="let _; control as control" [control]="control" />
</tbw-grid-column>
```

Or without FormArray binding (fallback to value):

```html
<tbw-grid-column field="name">
  <app-my-editor *tbwEditor="let value" [value]="value" />
</tbw-grid-column>
```

## Properties

| Property | Type | Description |
| -------- | ---- | ----------- |
| `elementRef` | <code>ElementRef&lt;any&gt;</code> |  |
| `value` | <code>InputSignal&lt;TValue &#124; undefined&gt;</code> | The cell value. Used when FormControl is not available. When a FormControl is provided, value is derived from control.value instead. |
| `row` | <code>InputSignal&lt;TRow &#124; undefined&gt;</code> | The full row data object. |
| `column` | <code>InputSignal&lt;<a href="/grid/angular/api/types/columnconfig/">ColumnConfig</a>&lt;TRow&gt; &#124; undefined&gt;</code> | The column configuration. |
| `control` | <code>InputSignal&lt;AbstractControl&lt;any, any, any&gt; &#124; undefined&gt;</code> | The FormControl for this cell, if the grid is bound to a FormArray. When provided, the editor uses control.value instead of the value input. |
| `commit` | <code>OutputEmitterRef&lt;TValue &#124; unknown&gt;</code> | Emits when the user commits a new value. Emits `null` when a nullable field is cleared. |
| `cancel` | <code>OutputEmitterRef&lt;void&gt;</code> | Emits when the user cancels editing. |
| `currentValue` | <code>Signal&lt;TValue &#124; undefined&gt;</code> | The current value, derived from FormControl if available, otherwise from value input. This is the recommended way to get the current value in your editor template. |
| `isInvalid` | <code>Signal&lt;boolean&gt;</code> | Whether the control is invalid (has validation errors). Returns false if no FormControl is available. |
| `isDirty` | <code>Signal&lt;boolean&gt;</code> | Whether the control is dirty (has been modified). Returns false if no FormControl is available. |
| `isTouched` | <code>Signal&lt;boolean&gt;</code> | Whether the control has been touched. Returns false if no FormControl is available. |
| `hasErrors` | <code>Signal&lt;boolean&gt;</code> | Whether the control has any validation errors. |
| `firstErrorMessage` | <code>Signal&lt;string&gt;</code> | The first error message from the control's validation errors. Returns an empty string if no errors. |
| `allErrorMessages` | <code>Signal&lt;string[]&gt;</code> | All error messages from the control's validation errors. |

## Methods

### isCellFocused()

Whether this editor's cell is the currently focused cell.

In row editing mode the grid creates editors for every editable cell
in the row simultaneously. Use this to conditionally auto-focus inputs
or open panels only in the active cell.

Performs a synchronous DOM check — safe to call from `ngAfterViewInit`.

```ts
isCellFocused(): boolean
```

***

### onBeforeEditClose()

Called **before** the grid clears editing state and destroys editor DOM.

At this point the commit callback is still active, so subclasses can
call commitValue to flush any pending/deferred values.

This fires only on the **commit** path (not on revert/cancel).
Use onEditClose for cleanup that should happen on both paths.

```ts
onBeforeEditClose(): void
```

***

### onEditClose()

Called when the grid ends the editing session for this cell.

Override to perform cleanup such as closing overlay panels, autocomplete
dropdowns, or other floating UI that lives at `<body>` level and would
otherwise persist after the editor DOM is removed.

The listener is set up automatically via `afterNextRender` — no manual
wiring required.

```ts
onEditClose(): void
```

***

### onExternalValueChange()

Called by the grid adapter when the cell value changes externally
(e.g., via `updateRow()` cascade or undo/redo).

Override in subclasses to reset internal state (search text, selection
flags, etc.) so the editor displays the updated value.

This runs **synchronously** before the value input is updated, giving
the editor a chance to clear stale state before the next change-detection
pass re-reads the template.

```ts
onExternalValueChange(_newVal: TValue): void
```

#### Parameters

| Name | Type | Description |
| ---- | ---- | ----------- |
| `_newVal` | <code>TValue</code> | The new cell value being pushed from the grid |

***

### commitValue()

Commit a new value. Emits the commit output AND dispatches a DOM event.
The DOM event enables the grid's auto-wiring to catch the commit.
Call this when the user confirms their edit.

```ts
commitValue(newValue: TValue | null): void
```

#### Parameters

| Name | Type | Description |
| ---- | ---- | ----------- |
| `newValue` | <code>TValue &#124; unknown</code> |  |

***

### cancelEdit()

Cancel editing. Emits the cancel output AND dispatches a DOM event.
Call this when the user cancels (e.g., presses Escape).

```ts
cancelEdit(): void
```

***

### getErrorMessage()

Get a human-readable error message for a validation error.
Override this method to customize error messages for your editor.

```ts
getErrorMessage(errorKey: string, errorValue: unknown): string
```

#### Parameters

| Name | Type | Description |
| ---- | ---- | ----------- |
| `errorKey` | <code>string</code> | The validation error key (e.g., 'required', 'minlength') |
| `errorValue` | <code>unknown</code> | The error value (e.g., \{ requiredLength: 5, actualLength: 3 \}) |

#### Returns

`string` - A human-readable error message

***
