Skip to content

Commit f913590

Browse files
committed
feat: add custom annotation renderer for demo purposes
1 parent eb63b7f commit f913590

File tree

6 files changed

+167
-8
lines changed

6 files changed

+167
-8
lines changed

src/app/app.component.html

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@ <h1 class="mb-5 display-4">ngx-annotate-text demo</h1>
44

55
<ngx-annotate-text
66
[(annotations)]="annotations"
7-
[removable]="true"
7+
[removable]="areAnnotationsRemovable"
88
[text]="text"
99
annotationClass="my-annotation"
1010
(clickAnnotation)="onClickAnnotation($event)"
1111
(removeAnnotation)="onRemoveAnnotation($event)"
12+
[annotationRenderComponent]="selectedRendererComponent"
1213
#annotateText
1314
>
1415
</ngx-annotate-text>
1516
</div>
1617
</div>
1718

18-
<div class="row mt-3">
19+
<div class="row mt-3 mb-5">
1920
<div class="col-12">
2021
<button type="button" class="btn btn-primary me-2" (click)="addAnnotation('Date', '#0d6efd')">Date</button>
2122
<button type="button" class="btn btn-secondary me-2" (click)="addAnnotation('Time', '#6c757d')">Time</button>
@@ -24,6 +25,32 @@ <h1 class="mb-5 display-4">ngx-annotate-text demo</h1>
2425
</div>
2526
</div>
2627

28+
<div class="row mb-5">
29+
<div class="col-12">
30+
<h2 class="mb-3 display-5">Settings</h2>
31+
32+
<label for="annotation-renderer-select">Annotation renderer:</label>
33+
<select class="form-control mb-3" id="annotation-renderer-select" [(ngModel)]="selectedRendererComponent">
34+
@for (renderer of rendererComponents; track $index) {
35+
<option [ngValue]="renderer" [selected]="renderer.name === selectedRendererComponent.name">
36+
{{ renderer.name.split("_")[1] }}
37+
</option>
38+
}
39+
</select>
40+
41+
<div class="form-check form-switch">
42+
<input
43+
class="form-check-input"
44+
type="checkbox"
45+
role="switch"
46+
id="flexSwitchCheckDefault"
47+
[(ngModel)]="areAnnotationsRemovable"
48+
/>
49+
<label class="form-check-label" for="flexSwitchCheckDefault">Removable annotations</label>
50+
</div>
51+
</div>
52+
</div>
53+
2754
<div class="row mb-5">
2855
<div class="col-12 col-lg-6 mt-3">
2956
<h2 class="mb-3 display-5">Annotations</h2>

src/app/app.component.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,39 @@
1-
import { Component, ViewChild } from '@angular/core';
1+
import { Component, Type, ViewChild } from '@angular/core';
22
import { RouterOutlet } from '@angular/router';
33
import { NgxAnnotateTextModule } from '../../projects/ngx-annotate-text/src/lib/ngx-annotate-text.module';
4-
import { NgxAnnotateTextComponent } from '../../dist/ngx-annotate-text/public-api';
5-
import { Annotation } from '../../projects/ngx-annotate-text/src/public-api';
4+
import { Annotation, NgxAnnotateTextComponent } from '../../projects/ngx-annotate-text/src/public-api';
5+
import { MyAnnotationRendererComponent } from './my-annotation-renderer/my-annotation-renderer.component';
6+
import { NgxAnnotationRendererComponent } from '../../projects/ngx-annotate-text/src/lib/components/annotation/annotation-renderer.components';
7+
import { FormsModule } from '@angular/forms';
68

79
@Component({
810
// eslint-disable-next-line @angular-eslint/component-selector
911
selector: 'app-root',
1012
standalone: true,
11-
imports: [RouterOutlet, NgxAnnotateTextModule],
13+
imports: [RouterOutlet, NgxAnnotateTextModule, FormsModule],
1214
templateUrl: './app.component.html',
1315
styleUrl: './app.component.css',
1416
})
1517
export class AppComponent {
1618
@ViewChild('annotateText') ngxAnnotateText?: NgxAnnotateTextComponent;
1719

18-
text = 'On August 1, we went on vacation to Barcelona, Spain. Our flight took off at 11:00 am.';
19-
2020
annotations: Annotation[] = [
2121
new Annotation(3, 11, 'Date', '#0d6efd'),
2222
new Annotation(36, 45, 'City', '#dc3545'),
2323
new Annotation(47, 52, 'Country', '#198754'),
2424
new Annotation(77, 85, 'Time', '#6c757d'),
2525
];
2626

27+
areAnnotationsRemovable = true;
28+
2729
events: string[] = [];
2830

31+
rendererComponents: Type<any>[] = [NgxAnnotationRendererComponent, MyAnnotationRendererComponent];
32+
33+
selectedRendererComponent: Type<any> = NgxAnnotationRendererComponent;
34+
35+
text = 'On August 1, we went on vacation to Barcelona, Spain. Our flight took off at 11:00 am.';
36+
2937
addAnnotation(label: string, color: string): void {
3038
if (!this.ngxAnnotateText) {
3139
return;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
span.container {
2+
display: flex;
3+
flex-direction: column;
4+
5+
button.text {
6+
background-color: transparent;
7+
border: none;
8+
border-bottom: 3px solid;
9+
}
10+
11+
span.label {
12+
user-select: none;
13+
text-align: center;
14+
font-weight: bold;
15+
}
16+
17+
span.popup {
18+
position: absolute;
19+
color: white;
20+
padding: 1rem;
21+
width: 25rem;
22+
box-shadow: 5px 5px 10px gainsboro;
23+
border-radius: 0.5rem;
24+
25+
span.chip-list {
26+
display: flex;
27+
flex-direction: row;
28+
flex-wrap: wrap;
29+
gap: 0.5rem;
30+
}
31+
32+
button {
33+
margin-top: 1rem;
34+
}
35+
}
36+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<span class="container" (mouseenter)="onMouseEnter()" (mouseleave)="onMouseLeave()">
2+
<button class="text" (click)="clickAnnotation(annotation)" [style]="{ 'border-color': annotation.color }">
3+
{{ annotation.text }}
4+
</button>
5+
<span class="label" [style]="{ color: annotation.color }">
6+
{{ annotation.label }}
7+
</span>
8+
@if (popupEnabled) {
9+
<span class="popup" [style]="{ 'background-color': annotation.color }">
10+
<h2>{{ annotation.text }}</h2>
11+
<span class="chip-list">
12+
<span class="badge text-bg-light">Label: {{ annotation.label }}</span>
13+
<span class="badge text-bg-light">Color: {{ annotation.color }}</span>
14+
<span class="badge text-bg-light">Start index: {{ annotation.startIndex }}</span>
15+
<span class="badge text-bg-light">End index: {{ annotation.endIndex }}</span>
16+
</span>
17+
@if (removable) {
18+
<button
19+
type="button"
20+
class="d-flex justify-content-center align-items-center btn btn-outline-light"
21+
(click)="removeAnnotation(annotation)"
22+
>
23+
<svg
24+
xmlns="http://www.w3.org/2000/svg"
25+
width="16"
26+
height="16"
27+
fill="currentColor"
28+
class="bi bi-trash3-fill"
29+
viewBox="0 0 16 16"
30+
>
31+
<path
32+
d="M11 1.5v1h3.5a.5.5 0 0 1 0 1h-.538l-.853 10.66A2 2 0 0 1 11.115 16h-6.23a2 2 0 0 1-1.994-1.84L2.038 3.5H1.5a.5.5 0 0 1 0-1H5v-1A1.5 1.5 0 0 1 6.5 0h3A1.5 1.5 0 0 1 11 1.5m-5 0v1h4v-1a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5M4.5 5.029l.5 8.5a.5.5 0 1 0 .998-.06l-.5-8.5a.5.5 0 1 0-.998.06m6.53-.528a.5.5 0 0 0-.528.47l-.5 8.5a.5.5 0 0 0 .998.058l.5-8.5a.5.5 0 0 0-.47-.528M8 4.5a.5.5 0 0 0-.5.5v8.5a.5.5 0 0 0 1 0V5a.5.5 0 0 0-.5-.5"
33+
/>
34+
</svg>
35+
Remove annotation
36+
</button>
37+
}
38+
</span>
39+
}
40+
</span>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { MyAnnotationRendererComponent } from './my-annotation-renderer.component';
4+
5+
describe('MyAnnotationRendererComponent', () => {
6+
let component: MyAnnotationRendererComponent;
7+
let fixture: ComponentFixture<MyAnnotationRendererComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
imports: [MyAnnotationRendererComponent]
12+
})
13+
.compileComponents();
14+
15+
fixture = TestBed.createComponent(MyAnnotationRendererComponent);
16+
component = fixture.componentInstance;
17+
fixture.detectChanges();
18+
});
19+
20+
it('should create', () => {
21+
expect(component).toBeTruthy();
22+
});
23+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Component, Input } from '@angular/core';
2+
import { Annotation } from '../../../dist/ngx-annotate-text/public-api';
3+
4+
@Component({
5+
selector: 'app-my-annotation-renderer',
6+
standalone: true,
7+
imports: [],
8+
templateUrl: './my-annotation-renderer.component.html',
9+
styleUrl: './my-annotation-renderer.component.css',
10+
})
11+
export class MyAnnotationRendererComponent {
12+
@Input({ required: true }) annotation!: Annotation;
13+
@Input() removable = true;
14+
@Input() clickAnnotation!: (annotation: Annotation) => void;
15+
@Input() removeAnnotation!: (annotation: Annotation) => void;
16+
17+
protected popupEnabled: boolean = false;
18+
19+
onMouseEnter(): void {
20+
this.popupEnabled = true;
21+
}
22+
onMouseLeave(): void {
23+
this.popupEnabled = false;
24+
}
25+
}

0 commit comments

Comments
 (0)