src/app/text-display/text-display.component.ts
The text display component shows text in a labeled box, and if desired, allows the user to edit and save the text
selector | app-text-display |
styleUrls | ./text-display.component.scss |
templateUrl | ./text-display.component.html |
Properties |
|
Methods |
Inputs |
Accessors |
labelText | |
Type : string
|
|
The title text. |
onEditFinished | |
Type : TextDisplayEditCallbackFn
|
|
A callback function. |
placeholder | |
Type : string
|
|
Default value : ''
|
|
The placeholder will be shown if the content is empty |
readonly | |
Type : boolean
|
|
If true, the edit button is not shown |
text | |
Type : string
|
|
Sets the content of the text display, and shows the placeholder if the text is empty |
finishEditing | ||||||
finishEditing(saved: boolean)
|
||||||
Parameters :
Returns :
void
|
startEditing |
startEditing()
|
Returns :
void
|
editMode |
Default value : false
|
editText |
Type : string
|
Default value : ''
|
showPlaceholder |
Default value : false
|
Private value |
Type : string
|
text | ||||||
gettext()
|
||||||
settext(value: string)
|
||||||
Sets the content of the text display, and shows the placeholder if the text is empty
Parameters :
Returns :
void
|
import {Component, Input} from '@angular/core';
/**
* A callback function that is called once the user finishes editing the text.
* @param saved true if the user clicked save, false if the user cancelled the editing
*/
export type TextDisplayEditCallbackFn = (saved: boolean) => void;
/**
* The text display component shows text in a labeled box, and if desired, allows the user to edit and save the
* text
*/
@Component({
selector: 'app-text-display',
templateUrl: './text-display.component.html',
styleUrls: ['./text-display.component.scss']
})
export class TextDisplayComponent {
private value: string;
editMode = false;
editText = '';
showPlaceholder = false;
/** A callback function. */
@Input() onEditFinished: TextDisplayEditCallbackFn;
/** The title text. */
@Input() labelText: string;
/** Sets the content of the text display, and shows the placeholder if the text is empty */
@Input() set text(value: string) {
this.value = value;
this.showPlaceholder = !value || value.length === 0;
}
get text(): string {
return this.value;
}
/** If true, the edit button is not shown */
@Input() readonly: boolean;
/** The placeholder will be shown if the content is empty */
@Input() placeholder = '';
finishEditing(saved: boolean): void {
this.editMode = false;
if (saved) {
this.text = this.editText;
}
if (this.onEditFinished) {
this.onEditFinished(saved);
}
}
startEditing(): void {
this.editText = this.text;
this.editMode = true;
}
}
<ng-container *ngIf="editMode; else readOnlyDisplay">
<mat-form-field appearance="outline" class="text-edit-container">
<mat-label>{{ labelText }}</mat-label>
<textarea [(ngModel)]="editText" matInput autofocus cdkTextareaAutosize style="margin-bottom: 8px"></textarea>
<div matSuffix style="display: flex">
<button mat-icon-button color="primary" (click)="finishEditing(true)">
<mat-icon>save</mat-icon>
</button>
<button mat-icon-button color="warn" (click)="finishEditing(false)">
<mat-icon>cancel</mat-icon>
</button>
</div>
</mat-form-field>
</ng-container>
<ng-template #readOnlyDisplay>
<div class="text-display-container">
<div class="text-display-label-container">
<span class="text-display-label">{{ labelText }}</span>
</div>
<button *ngIf="readonly === undefined" mat-icon-button style="float: right; margin: 0" color="primary" (click)="startEditing()">
<mat-icon>edit</mat-icon>
</button>
<div
[ngClass]="{
'text-content-container': !showPlaceholder,
'text-content-container-placeholder': showPlaceholder
}"
>
<ng-container *ngFor="let line of (showPlaceholder ? placeholder : text).split('\n')">
{{ line.replace("\n", "") }}<br />
</ng-container>
</div>
</div>
</ng-template>
./text-display.component.scss
@import "src/styles/variables";
.text-display-label-container {
position: relative;
width: fit-content;
height: 0.8em;
line-height: 0.8em;
padding: 0 2px 0 2px;
top: -0.5em;
left: -1px;
background-color: #fafafa; // FIXME: Hardcoded background color
color: rgba(0, 0, 0, 0.6);
text-align: center;
}
.text-display-label {
display: inline-block;
vertical-align: middle;
font-size: 0.8em;
}
.text-display-container {
margin-top: 10px;
padding: 0 8px 16px 8px;
width: 100%;
height: 100%;
border: 1px rgba(0, 0, 0, 0.2) solid;
border-radius: 4px;
word-break: break-all;
min-height: 60px;
}
.text-content-container {
padding-top: 8px;
}
.text-content-container-placeholder {
padding-top: 8px;
color: gray;
font-style: italic;
}
.text-edit-container {
width: 100%;
height: 100%;
}