Inline editor

The inline editor is used to make text editable.

The 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.

Inputs

Name Type Default Description
value string '' Value of the inline editor.
required boolean false To specify that the input field must not be left empty.
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.
errorStateMatcher ErrorStateMatcher DefaultErrorStateMatcher A class used to control when error messages are shown.
aria-label-save string - Takes precedence as the save buttons's text alternative.
aria-label-cancel string - Takes precedence as the cancel button's text alternative.

Outputs

Name Type Description
saved EventEmitter<string>() Emitted when value is saved.
cancelled EventEmitter<string>() Emitted when editing is cancelled.

Methods

Name Description Return type
enterEditing Enters the edit mode. void
saveAndQuitEditing Saves and quits the edit mode. void
cancelAndQuitEditing Cancels and quits the edit mode. void
focus Focuses the input or the button depending on the mode. void
´ 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'; }

Properties

Name Type Description
idle boolean Whether current mode is idle (readonly).
editing boolean Whether current mode is editing (readonly).
saving boolean Whether current mode is saving (readonly).

Error messages and validation

When a value for the input field is validated, 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'; }

By default 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. This behaviour can be customized by passing an ErrorStateMatcher to the inline editor.

An inline editor can have more than one error, it is up to the consumer to toggle which messages should be displayed. This can be done with ngIf or ngSwitch. You can use the Angular forms API with the inline editor and pass validators to it as you would with any other form field.

´ Loading interactive demo...
<form [formGroup]="queryTitleForm"> <em dt-inline-editor [(ngModel)]="value" formControlName="queryTitleControl" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" required > <dt-error *ngIf="queryTitleControl.hasError('required')"> The query title must not be empty. </dt-error> <dt-error *ngIf="queryTitleControl.hasError('minlength')"> The query title must be at least 4 characters long </dt-error> <dt-error *ngIf="hasCustomError"> Password must include the string 'barista' </dt-error> </em> </form> export class InlineEditorValidationExample { queryTitleControl = new FormControl('', [ // tslint:disable-next-line: no-unbound-method Validators.minLength(4), this.baristaValidator(), ]); queryTitleForm = new FormGroup({ queryTitleControl: this.queryTitleControl, }); value = '123'; get hasCustomError(): boolean { return this.queryTitleControl.hasError('barista'); } /** * Note that this validator function does not have to be part of the class * exporting/importing this function is preferred since it increases reusability */ baristaValidator(): ValidatorFn { // tslint:disable-next-line: no-any return (control: AbstractControl): { [key: string]: any } | null => { const required = !control.value.includes('barista'); return required ? { barista: { value: control.value } } : null; }; } } <form [formGroup]="queryTitleForm"> <em dt-inline-editor [(ngModel)]="value" formControlName="queryTitleControl" aria-label-save="Save text" aria-label-cancel="Cancel and discard changes" required > <dt-error *ngIf="queryTitleControl.hasError('required')"> The query title must not be empty. </dt-error> <dt-error *ngIf="queryTitleControl.hasError('minlength')"> The query title must be at least 4 characters long </dt-error> <dt-error *ngIf="hasCustomError"> Password must include the string 'barista' </dt-error> </em> </form> export class InlineEditorValidationExample { queryTitleControl = new FormControl('', [ // tslint:disable-next-line: no-unbound-method Validators.minLength(4), this.baristaValidator(), ]); queryTitleForm = new FormGroup({ queryTitleControl: this.queryTitleControl, }); value = '123'; get hasCustomError(): boolean { return this.queryTitleControl.hasError('barista'); } /** * Note that this validator function does not have to be part of the class * exporting/importing this function is preferred since it increases reusability */ baristaValidator(): ValidatorFn { // tslint:disable-next-line: no-any return (control: AbstractControl): { [key: string]: any } | null => { const required = !control.value.includes('barista'); return required ? { barista: { value: control.value } } : null; }; } }

Asynchronous operations

Success

´ 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); }); } }

Failure

´ 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); }); } }