Inline editor

The inline editor is used to make text editable. It uses nested buttons and the input field component.

´ Loading interactive demo...
<em dt-inline-editor [(ngModel)]="sampleModel" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" ></em> <span> model: <code>{{ sampleModel }}</code> </span> export class InlineEditorDefaultExample { sampleModel = 'text content'; } <em dt-inline-editor [(ngModel)]="sampleModel" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" ></em> <span> model: <code>{{ sampleModel }}</code> </span> export class InlineEditorDefaultExample { sampleModel = 'text content'; }

Inline editing is indicated by the edit icon used in the nested button next to the editable text. The checkmark icon and abort icon used in the nested button save/discard the changes.

Behavior

While the cursor is in the input field, the enter key triggers saving it. On focus loss of the inline editing input field, the typed input will be autosaved.

dt-inline-editor is a directive that makes any text containing HTML element editable.

´ Loading interactive demo...
<em dt-inline-editor [(ngModel)]="sampleModel" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" ></em> <span> model: <code>{{ sampleModel }}</code> </span> export class InlineEditorDefaultExample { sampleModel = 'text content'; } <em dt-inline-editor [(ngModel)]="sampleModel" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" ></em> <span> model: <code>{{ sampleModel }}</code> </span> export class InlineEditorDefaultExample { sampleModel = 'text content'; }

Imports

You have to import the DtInlineEditorModule when you want to use the dt-inline-editor directive:

@NgModule({
  imports: [DtInlineEditorModule],
})
class MyModule {}

Initialization

To apply, add the dt-inline-editor attribute to the HTML element.

Options & Properties

Name Type Default Description
ngModel string - The two-way data-binding to set the content and handle changes.
@Input() required boolean false To specify that the input field must not be left empty.
@Input() onRemoteSave function - A callback returning an Observable that will be triggered when the (potentially async) saving of the new value has finished. The inline editor needs to be notified so it can go back to idle state if ok or stay in editing mode if failed.
@Input() errorStateMatcher ErrorStateMatcher DefaultErrorStateMatcher A class used to control when error messages are shown.
@Input() ariaLabelSave string - Takes precedence as the save buttons's text alternative.
@Input() ariaLabelCancel string - Takes precedence as the cancel button's text alternative.
@Output() saved EventEmitter<string>() - Emitted when value is saved.
@Output() cancelled EventEmitter<string>() - Emitted when editing is cancelled.
value() string '' Value of the inline editor.
idle() boolean - Whether current mode is idle (readonly).
editing() boolean - Whether current mode is editing (readonly).
saving() boolean - Whether current mode is saving (readonly).

Required field validation

When a value for the input field is required, an error message must be provided by adding a <dt-error> element inside the inline editor.

´ Loading interactive demo...
<em dt-inline-editor required [(ngModel)]="sampleModel" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" > <dt-error>Empty value not accepted!</dt-error> </em> <span> model: <code>{{ sampleModel }}</code> </span> export class InlineEditorRequiredExample { sampleModel = 'text content'; } <em dt-inline-editor required [(ngModel)]="sampleModel" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" > <dt-error>Empty value not accepted!</dt-error> </em> <span> model: <code>{{ sampleModel }}</code> </span> export class InlineEditorRequiredExample { sampleModel = 'text content'; }

Errors are hidden initially and will be displayed on invalid form fields, after the user has interacted with the element or the parent form has been submitted. The errors will appear on top of the hint labels and will overlap them.

If a form field can have more than one error state, it is up to the consumer to toggle which messages should be displayed. This can be done with ngIf or ngSwitch.

Examples

JavaScript API

´ Loading interactive demo...
<em #sampleEditor dt-inline-editor [(ngModel)]="sampleModel" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" ></em> <button (click)="sampleEditor.enterEditing()">open editor</button> <button (click)="sampleEditor.saveAndQuitEditing()">save changes</button> <button (click)="sampleEditor.cancelAndQuitEditing()"> cancel changes </button> export class InlineEditorApiExample { @ViewChild('sampleEditor', { static: true }) sampleEditor: DtInlineEditor; sampleModel = 'text content'; } <em #sampleEditor dt-inline-editor [(ngModel)]="sampleModel" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" ></em> <button (click)="sampleEditor.enterEditing()">open editor</button> <button (click)="sampleEditor.saveAndQuitEditing()">save changes</button> <button (click)="sampleEditor.cancelAndQuitEditing()"> cancel changes </button> export class InlineEditorApiExample { @ViewChild('sampleEditor', { static: true }) sampleEditor: DtInlineEditor; sampleModel = 'text content'; }

Successful asynchronous operation

´ Loading interactive demo...
<em dt-inline-editor [(ngModel)]="sampleModel" [onRemoteSave]="successfulSaveFunction" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" ></em> export class InlineEditorSuccessfulExample { sampleModel = 'text content'; successfulSaveFunction(): Observable<void> { return new Observable<void>(observer => { setTimeout(() => { observer.next(); observer.complete(); }, TIMEOUT_MS); }); } } <em dt-inline-editor [(ngModel)]="sampleModel" [onRemoteSave]="successfulSaveFunction" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" ></em> export class InlineEditorSuccessfulExample { sampleModel = 'text content'; successfulSaveFunction(): Observable<void> { return new Observable<void>(observer => { setTimeout(() => { observer.next(); observer.complete(); }, TIMEOUT_MS); }); } }

Failing asynchronous operation

´ Loading interactive demo...
<em dt-inline-editor [(ngModel)]="sampleModel" [onRemoteSave]="failingSaveFunction" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" ></em> export class InlineEditorFailingExample { sampleModel = 'text content'; failingSaveFunction(): Observable<void> { return new Observable<void>(observer => { setTimeout(() => { observer.error(); }, TIMEOUT_MS); }); } } <em dt-inline-editor [(ngModel)]="sampleModel" [onRemoteSave]="failingSaveFunction" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" ></em> export class InlineEditorFailingExample { sampleModel = 'text content'; failingSaveFunction(): Observable<void> { return new Observable<void>(observer => { setTimeout(() => { observer.error(); }, TIMEOUT_MS); }); } }