@myrmidon/cadmus-ui 15.1.2 → 15.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,3 +20,115 @@ This library contains shared UI components, services and validators for Cadmus:
20
20
  - user lookup.
21
21
  - custom validators.
22
22
  - JSON validators.
23
+
24
+ ## Thesaurus Entries Picker
25
+
26
+ - class: `ThesEntriesPickerComponent`
27
+ - selector: `cadmus-thes-entries-picker`
28
+
29
+ 1. import `ThesEntriesPickerComponent` from `@myrmidon/cadmus-ui` and add it to your component's `imports`. It is assumed that your component has thesauri entries properties in (usually input) signals, like:
30
+
31
+ ```ts
32
+ public readonly posEntries = input.required<ThesaurusEntry[] | undefined>();
33
+ public readonly tagEntries = input<ThesaurusEntry[] | undefined>();
34
+ ```
35
+
36
+ 2. add these utility function to map thesaurus ID/IDs to the corresponding thesaurus entry/entries (remove the one you do not need):
37
+
38
+ ```ts
39
+ public mapIdToEntry(
40
+ id: string | null,
41
+ entries: ThesaurusEntry[] | undefined
42
+ ): ThesaurusEntry | null {
43
+ if (!id) return null;
44
+ if (!entries) return { id, value: id };
45
+ return entries.find((e) => e.id === id) || { id, value: id };
46
+ }
47
+
48
+ private mapIdsToEntries(ids: string[], entries: ThesaurusEntry[] | undefined): ThesaurusEntry[] {
49
+ if (!entries) return ids.map((id) => ({ id, value: id }));
50
+ return ids.map((id) => entries.find((e) => e.id === id) || { id, value: id });
51
+ }
52
+ ```
53
+
54
+ 3. add form controls for entries. In this example `pos` is for a single entry, `tags` is for an array of entries.
55
+
56
+ ```ts
57
+ public pos: FormControl<ThesaurusEntry>;
58
+ public tags: FormControl<ThesaurusEntry[]>;
59
+
60
+ // ... in constructor:
61
+
62
+ // single entry (required)
63
+ this.pos = formBuilder.control(
64
+ { id: '', value: '' },
65
+ {
66
+ nonNullable: true,
67
+ validators: Validators.required,
68
+ }
69
+ );
70
+ // multiple entries (optional)
71
+ this.tags = formBuilder.control([], { nonNullable: true });
72
+ ```
73
+
74
+ 4. when setting the UI from data, follow this example:
75
+
76
+ ```ts
77
+ private updateForm(data: WordForm | undefined | null): void {
78
+ if (!data) {
79
+ this.formCtl.reset();
80
+ } else {
81
+ this.pos.setValue(this.mapIdToEntry(data.pos, this.posEntries()) || this.posEntries()?.[0]!);
82
+ this.tags.setValue(this.mapIdsToEntries(data.tags || [], this.tagEntries()));
83
+ // ...
84
+ this.formCtl.markAsPristine();
85
+ }
86
+ }
87
+
88
+ public onPosEntriesChange(entries: ThesaurusEntry[]): void {
89
+ this.pos.setValue(entries[0]);
90
+ this.pos.markAsDirty();
91
+ this.pos.updateValueAndValidity();
92
+ }
93
+
94
+ public onTagEntriesChange(entries: ThesaurusEntry[]): void {
95
+ this.tags.setValue(entries);
96
+ this.tags.markAsDirty();
97
+ this.tags.updateValueAndValidity();
98
+ }
99
+
100
+ private getData(): WordForm {
101
+ return {
102
+ pos: this.pos.value.id,
103
+ tags: this.tags.value.map((e) => e.id),
104
+ // ...
105
+ };
106
+ }
107
+ ```
108
+
109
+ 5. add the corresponding components in the HTML template. Here the first example (`pos`) refers to the above mentioned situation, where entries might be present or not, for a single thesaurus ID to pick; the second one (`tags`) to an array of IDs to pick from a thesaurus:
110
+
111
+ ```html
112
+ <!-- pos (always bound) -->
113
+ <cadmus-thes-entries-picker
114
+ [availableEntries]="posEntries()!"
115
+ [entries]="[this.pos.value]"
116
+ [hierarchicLabels]="true"
117
+ [minEntries]="1"
118
+ [maxEntries]="1"
119
+ (entriesChange)="onPosEntriesChange($event!)"
120
+ />
121
+
122
+ @if (tagEntries()?.length) {
123
+ <div>
124
+ <fieldset>
125
+ <legend>tags</legend>
126
+ <cadmus-thes-entries-picker
127
+ [availableEntries]="tagEntries()!"
128
+ [entries]="tags.value"
129
+ (entriesChange)="onTagEntriesChange($event!)"
130
+ />
131
+ </fieldset>
132
+ </div>
133
+ }
134
+ ```