iss-ctrl 0.0.9 → 0.0.11

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.
Files changed (283) hide show
  1. package/fesm2022/{iss-ctrl-iss-ctrl-BN7L4PtW.mjs → iss-ctrl-iss-ctrl-hz0ibyPg.mjs} +11 -11
  2. package/fesm2022/{iss-ctrl-iss-ctrl-BN7L4PtW.mjs.map → iss-ctrl-iss-ctrl-hz0ibyPg.mjs.map} +1 -1
  3. package/fesm2022/{iss-ctrl-load-event-CGgv6kpn.mjs → iss-ctrl-load-event-BW5dKG8R.mjs} +3 -3
  4. package/fesm2022/{iss-ctrl-load-event-CGgv6kpn.mjs.map → iss-ctrl-load-event-BW5dKG8R.mjs.map} +1 -1
  5. package/fesm2022/{iss-ctrl-load-options-event-ClRozxct.mjs → iss-ctrl-load-options-event-ClX9TiiD.mjs} +3 -3
  6. package/fesm2022/{iss-ctrl-load-options-event-ClRozxct.mjs.map → iss-ctrl-load-options-event-ClX9TiiD.mjs.map} +1 -1
  7. package/fesm2022/{iss-ctrl-load-value-event-3zloE5y4.mjs → iss-ctrl-load-value-event-DThpI9BA.mjs} +3 -3
  8. package/fesm2022/{iss-ctrl-load-value-event-3zloE5y4.mjs.map → iss-ctrl-load-value-event-DThpI9BA.mjs.map} +1 -1
  9. package/fesm2022/{iss-ctrl-note.field-BmQkVu8o.mjs → iss-ctrl-note.field-4uLl0oS_.mjs} +2 -2
  10. package/fesm2022/{iss-ctrl-note.field-BmQkVu8o.mjs.map → iss-ctrl-note.field-4uLl0oS_.mjs.map} +1 -1
  11. package/fesm2022/{iss-ctrl-replace-api-keys-CkdiTxRe.mjs → iss-ctrl-replace-api-keys-BQL9zimJ.mjs} +2 -2
  12. package/fesm2022/{iss-ctrl-replace-api-keys-CkdiTxRe.mjs.map → iss-ctrl-replace-api-keys-BQL9zimJ.mjs.map} +1 -1
  13. package/fesm2022/{iss-ctrl-set-value-event-OrkUS2nT.mjs → iss-ctrl-set-value-event-BbEYFBe3.mjs} +2 -2
  14. package/fesm2022/{iss-ctrl-set-value-event-OrkUS2nT.mjs.map → iss-ctrl-set-value-event-BbEYFBe3.mjs.map} +1 -1
  15. package/fesm2022/{iss-ctrl-table.field-B42zKves.mjs → iss-ctrl-table.field-kPIwve-M.mjs} +315 -171
  16. package/fesm2022/iss-ctrl-table.field-kPIwve-M.mjs.map +1 -0
  17. package/fesm2022/{iss-ctrl-trigger-based-on-json-value-C6jf7SSW.mjs → iss-ctrl-trigger-based-on-json-value-DuLD4SOS.mjs} +2 -2
  18. package/fesm2022/{iss-ctrl-trigger-based-on-json-value-C6jf7SSW.mjs.map → iss-ctrl-trigger-based-on-json-value-DuLD4SOS.mjs.map} +1 -1
  19. package/fesm2022/{iss-ctrl-user-picker.field-D5slkCaX.mjs → iss-ctrl-user-picker.field-l-0bW6lP.mjs} +2 -2
  20. package/fesm2022/{iss-ctrl-user-picker.field-D5slkCaX.mjs.map → iss-ctrl-user-picker.field-l-0bW6lP.mjs.map} +1 -1
  21. package/fesm2022/iss-ctrl.mjs +1 -1
  22. package/flags/ad.svg +282 -0
  23. package/flags/ae.svg +6 -0
  24. package/flags/af.svg +9 -0
  25. package/flags/ag.svg +15 -0
  26. package/flags/ai.svg +35 -0
  27. package/flags/al.svg +7 -0
  28. package/flags/am.svg +5 -0
  29. package/flags/ao.svg +19 -0
  30. package/flags/aq.svg +45 -0
  31. package/flags/ar.svg +66 -0
  32. package/flags/as.svg +225 -0
  33. package/flags/at.svg +4 -0
  34. package/flags/au.svg +32 -0
  35. package/flags/aw.svg +11 -0
  36. package/flags/ax.svg +11 -0
  37. package/flags/az.svg +11 -0
  38. package/flags/ba.svg +18 -0
  39. package/flags/bb.svg +11 -0
  40. package/flags/bd.svg +4 -0
  41. package/flags/be.svg +5 -0
  42. package/flags/bf.svg +14 -0
  43. package/flags/bg.svg +5 -0
  44. package/flags/bh.svg +4 -0
  45. package/flags/bi.svg +26 -0
  46. package/flags/bj.svg +5 -0
  47. package/flags/bl.svg +5 -0
  48. package/flags/bm.svg +374 -0
  49. package/flags/bn.svg +70 -0
  50. package/flags/bo.svg +3625 -0
  51. package/flags/bq.svg +5 -0
  52. package/flags/br.svg +92 -0
  53. package/flags/bs.svg +5 -0
  54. package/flags/bt.svg +487 -0
  55. package/flags/bv.svg +11 -0
  56. package/flags/bw.svg +5 -0
  57. package/flags/by.svg +15 -0
  58. package/flags/bz.svg +629 -0
  59. package/flags/ca.svg +7 -0
  60. package/flags/cc.svg +33 -0
  61. package/flags/cd.svg +5 -0
  62. package/flags/cf.svg +7 -0
  63. package/flags/cg.svg +5 -0
  64. package/flags/ch.svg +4 -0
  65. package/flags/ci.svg +5 -0
  66. package/flags/ck.svg +29 -0
  67. package/flags/cl.svg +14 -0
  68. package/flags/cm.svg +15 -0
  69. package/flags/cn.svg +11 -0
  70. package/flags/co.svg +5 -0
  71. package/flags/cr.svg +1332 -0
  72. package/flags/cu.svg +6 -0
  73. package/flags/cv.svg +24 -0
  74. package/flags/cw.svg +16 -0
  75. package/flags/cx.svg +24 -0
  76. package/flags/cy.svg +13 -0
  77. package/flags/cz.svg +5 -0
  78. package/flags/de.svg +5 -0
  79. package/flags/dj.svg +6 -0
  80. package/flags/dk.svg +5 -0
  81. package/flags/dm.svg +198 -0
  82. package/flags/do.svg +238 -0
  83. package/flags/dz.svg +5 -0
  84. package/flags/ec.svg +1292 -0
  85. package/flags/ee.svg +5 -0
  86. package/flags/eg.svg +125 -0
  87. package/flags/eh.svg +12 -0
  88. package/flags/er.svg +9 -0
  89. package/flags/es.svg +445 -0
  90. package/flags/et.svg +16 -0
  91. package/flags/eu.svg +28 -0
  92. package/flags/fi.svg +5 -0
  93. package/flags/fj.svg +203 -0
  94. package/flags/fk.svg +922 -0
  95. package/flags/flags.png +0 -0
  96. package/flags/flags@2x.png +0 -0
  97. package/flags/fm.svg +16 -0
  98. package/flags/fo.svg +11 -0
  99. package/flags/fonts.css +271 -0
  100. package/flags/fr.svg +5 -0
  101. package/flags/ga.svg +5 -0
  102. package/flags/gb-eng.svg +7 -0
  103. package/flags/gb-nir.svg +15 -0
  104. package/flags/gb-sct.svg +11 -0
  105. package/flags/gb-wls.svg +16 -0
  106. package/flags/gb.svg +15 -0
  107. package/flags/gd.svg +11 -0
  108. package/flags/ge.svg +17 -0
  109. package/flags/gf.svg +5 -0
  110. package/flags/gg.svg +8 -0
  111. package/flags/gh.svg +6 -0
  112. package/flags/gi.svg +69 -0
  113. package/flags/gl.svg +4 -0
  114. package/flags/gm.svg +7 -0
  115. package/flags/gn.svg +5 -0
  116. package/flags/gp.svg +5 -0
  117. package/flags/gq.svg +88 -0
  118. package/flags/gr.svg +4 -0
  119. package/flags/gs.svg +693 -0
  120. package/flags/gt.svg +317 -0
  121. package/flags/gu.svg +58 -0
  122. package/flags/gw.svg +13 -0
  123. package/flags/gy.svg +7 -0
  124. package/flags/hk.svg +17 -0
  125. package/flags/hm.svg +32 -0
  126. package/flags/hn.svg +10 -0
  127. package/flags/hr.svg +282 -0
  128. package/flags/ht.svg +1470 -0
  129. package/flags/hu.svg +5 -0
  130. package/flags/id.svg +4 -0
  131. package/flags/ie.svg +5 -0
  132. package/flags/il.svg +5 -0
  133. package/flags/im.svg +33 -0
  134. package/flags/in.svg +25 -0
  135. package/flags/io.svg +895 -0
  136. package/flags/iq.svg +12 -0
  137. package/flags/ir.svg +31 -0
  138. package/flags/is.svg +5 -0
  139. package/flags/it.svg +5 -0
  140. package/flags/je.svg +40 -0
  141. package/flags/jm.svg +9 -0
  142. package/flags/jo.svg +10 -0
  143. package/flags/jp.svg +4 -0
  144. package/flags/ke.svg +28 -0
  145. package/flags/kg.svg +7 -0
  146. package/flags/kh.svg +133 -0
  147. package/flags/ki.svg +54 -0
  148. package/flags/km.svg +13 -0
  149. package/flags/kn.svg +24 -0
  150. package/flags/kp.svg +16 -0
  151. package/flags/kr.svg +16 -0
  152. package/flags/kw.svg +6 -0
  153. package/flags/ky.svg +153 -0
  154. package/flags/kz.svg +49 -0
  155. package/flags/la.svg +5 -0
  156. package/flags/lb.svg +8 -0
  157. package/flags/lc.svg +6 -0
  158. package/flags/li.svg +75 -0
  159. package/flags/lk.svg +50 -0
  160. package/flags/lr.svg +15 -0
  161. package/flags/ls.svg +32 -0
  162. package/flags/lt.svg +5 -0
  163. package/flags/lu.svg +5 -0
  164. package/flags/lv.svg +4 -0
  165. package/flags/ly.svg +8 -0
  166. package/flags/ma.svg +4 -0
  167. package/flags/mc.svg +4 -0
  168. package/flags/md.svg +102 -0
  169. package/flags/me.svg +240 -0
  170. package/flags/mf.svg +5 -0
  171. package/flags/mg.svg +5 -0
  172. package/flags/mh.svg +18 -0
  173. package/flags/mk.svg +6 -0
  174. package/flags/ml.svg +5 -0
  175. package/flags/mm.svg +12 -0
  176. package/flags/mn.svg +12 -0
  177. package/flags/mo.svg +13 -0
  178. package/flags/mp.svg +2919 -0
  179. package/flags/mq.svg +5 -0
  180. package/flags/mr.svg +5 -0
  181. package/flags/ms.svg +59 -0
  182. package/flags/mt.svg +52 -0
  183. package/flags/mu.svg +6 -0
  184. package/flags/mv.svg +8 -0
  185. package/flags/mw.svg +24 -0
  186. package/flags/mx.svg +1129 -0
  187. package/flags/my.svg +12 -0
  188. package/flags/mz.svg +50 -0
  189. package/flags/na.svg +17 -0
  190. package/flags/nc.svg +5 -0
  191. package/flags/ne.svg +6 -0
  192. package/flags/nf.svg +8 -0
  193. package/flags/ng.svg +4 -0
  194. package/flags/ni.svg +281 -0
  195. package/flags/nl.svg +5 -0
  196. package/flags/no.svg +11 -0
  197. package/flags/np.svg +33 -0
  198. package/flags/nr.svg +8 -0
  199. package/flags/nu.svg +23 -0
  200. package/flags/nz.svg +37 -0
  201. package/flags/om.svg +307 -0
  202. package/flags/pa.svg +15 -0
  203. package/flags/pe.svg +767 -0
  204. package/flags/pf.svg +38 -0
  205. package/flags/pg.svg +16 -0
  206. package/flags/ph.svg +28 -0
  207. package/flags/pk.svg +7 -0
  208. package/flags/pl.svg +4 -0
  209. package/flags/pm.svg +5 -0
  210. package/flags/pn.svg +131 -0
  211. package/flags/pr.svg +6 -0
  212. package/flags/ps.svg +6 -0
  213. package/flags/pt.svg +79 -0
  214. package/flags/pw.svg +4 -0
  215. package/flags/py.svg +192 -0
  216. package/flags/qa.svg +7 -0
  217. package/flags/re.svg +5 -0
  218. package/flags/ro.svg +5 -0
  219. package/flags/rs.svg +1143 -0
  220. package/flags/ru.svg +5 -0
  221. package/flags/rw.svg +17 -0
  222. package/flags/sa.svg +23 -0
  223. package/flags/sb.svg +30 -0
  224. package/flags/sc.svg +7 -0
  225. package/flags/sd.svg +6 -0
  226. package/flags/se.svg +5 -0
  227. package/flags/sg.svg +15 -0
  228. package/flags/sh.svg +15 -0
  229. package/flags/si.svg +30 -0
  230. package/flags/sj.svg +11 -0
  231. package/flags/sk.svg +21 -0
  232. package/flags/sl.svg +5 -0
  233. package/flags/sm.svg +847 -0
  234. package/flags/sn.svg +15 -0
  235. package/flags/so.svg +13 -0
  236. package/flags/sr.svg +6 -0
  237. package/flags/ss.svg +8 -0
  238. package/flags/st.svg +16 -0
  239. package/flags/stc-icons.css +1 -0
  240. package/flags/sv.svg +3368 -0
  241. package/flags/sx.svg +172 -0
  242. package/flags/sy.svg +6 -0
  243. package/flags/sz.svg +54 -0
  244. package/flags/tc.svg +88 -0
  245. package/flags/td.svg +5 -0
  246. package/flags/tf.svg +18 -0
  247. package/flags/tg.svg +15 -0
  248. package/flags/th.svg +5 -0
  249. package/flags/tj.svg +32 -0
  250. package/flags/tk.svg +25 -0
  251. package/flags/tl.svg +6 -0
  252. package/flags/tm.svg +349 -0
  253. package/flags/tn.svg +9 -0
  254. package/flags/to.svg +8 -0
  255. package/flags/tr.svg +6 -0
  256. package/flags/tt.svg +5 -0
  257. package/flags/tv.svg +18 -0
  258. package/flags/tw.svg +12 -0
  259. package/flags/tz.svg +13 -0
  260. package/flags/ua.svg +4 -0
  261. package/flags/ug.svg +46 -0
  262. package/flags/um.svg +25 -0
  263. package/flags/us.svg +25 -0
  264. package/flags/uy.svg +138 -0
  265. package/flags/uz.svg +30 -0
  266. package/flags/va.svg +277 -0
  267. package/flags/vc.svg +9 -0
  268. package/flags/ve.svg +28 -0
  269. package/flags/vg.svg +96 -0
  270. package/flags/vi.svg +311 -0
  271. package/flags/vn.svg +12 -0
  272. package/flags/vu.svg +20 -0
  273. package/flags/wf.svg +7 -0
  274. package/flags/ws.svg +14 -0
  275. package/flags/xk.svg +11 -0
  276. package/flags/ye.svg +5 -0
  277. package/flags/yt.svg +5 -0
  278. package/flags/za.svg +17 -0
  279. package/flags/zm.svg +20 -0
  280. package/flags/zw.svg +130 -0
  281. package/package.json +1 -1
  282. package/upgrade.scss +68 -0
  283. package/fesm2022/iss-ctrl-table.field-B42zKves.mjs.map +0 -1
@@ -1,8 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { viewChild, ViewContainerRef, inject, DestroyRef, effect, Component, signal, computed, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
2
+ import { viewChild, ViewContainerRef, inject, DestroyRef, effect, Component, input, signal, computed, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
4
3
  import * as i1$1 from '@angular/forms';
5
- import { FormGroup, ReactiveFormsModule } from '@angular/forms';
4
+ import { FormGroup, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
5
+ import { a as ViewerBase, L as Loader, C as ControlBase, b as FormEngine, I as IssField, O as Outlet, F as FieldBase, V as VIEW_PROVIDER, c as ValidationMessageComponent } from './iss-ctrl-iss-ctrl-hz0ibyPg.mjs';
6
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
7
  import { MatFormFieldModule } from '@angular/material/form-field';
7
8
  import * as i1 from '@angular/material/input';
8
9
  import { MatInputModule } from '@angular/material/input';
@@ -14,7 +15,6 @@ import * as i3 from '@angular/material/sort';
14
15
  import { MatSort, MatSortModule } from '@angular/material/sort';
15
16
  import * as i2 from '@angular/material/table';
16
17
  import { MatTableDataSource, MatTableModule } from '@angular/material/table';
17
- import { a as ViewerBase, L as Loader, F as FieldBase, b as FormEngine, I as IssField, V as VIEW_PROVIDER, O as Outlet } from './iss-ctrl-iss-ctrl-BN7L4PtW.mjs';
18
18
  import { take } from 'rxjs';
19
19
 
20
20
  class FieldViewer extends ViewerBase {
@@ -58,11 +58,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
58
58
  }]
59
59
  }], propDecorators: { containerRef: [{ type: i0.ViewChild, args: ["container", { ...{ read: ViewContainerRef }, isSignal: true }] }] } });
60
60
 
61
- class TableField extends FieldBase {
61
+ class TableControl extends ControlBase {
62
+ // raw child field configs (the same json shape IssField takes), not IssField/host-field
63
+ // instances: this is what lets the control be dropped into a consumer's own wrapper
64
+ // without depending on the outlet/form-engine machinery a host IssField carries
65
+ columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
66
+ withFilter = input(false, ...(ngDevMode ? [{ debugName: "withFilter" }] : /* istanbul ignore next */ []));
67
+ withSort = input(false, ...(ngDevMode ? [{ debugName: "withSort" }] : /* istanbul ignore next */ []));
68
+ withPagination = input(false, ...(ngDevMode ? [{ debugName: "withPagination" }] : /* istanbul ignore next */ []));
69
+ // the control value stays the "*"/null sentinel (see #emitRows); the row data itself is
70
+ // carried separately here so a wrapper can push a value in on top of a plain ctrl.setValue,
71
+ // e.g. `field.ctrl.setValue("*"); field.ctrlJsonValue.set(rows);`
72
+ jsonValue = input(null, ...(ngDevMode ? [{ debugName: "jsonValue" }] : /* istanbul ignore next */ []));
62
73
  loader = inject(Loader);
63
74
  drawer = viewChild("drawer", ...(ngDevMode ? [{ debugName: "drawer" }] : /* istanbul ignore next */ []));
64
75
  tableOutletForm = new FormGroup({});
65
- fields = signal(this.constructFieldChildren(this.field.children), ...(ngDevMode ? [{ debugName: "fields" }] : /* istanbul ignore next */ []));
76
+ fields = signal([], ...(ngDevMode ? [{ debugName: "fields" }] : /* istanbul ignore next */ []));
66
77
  columnLabels = computed(() => {
67
78
  const labels = this.fields().map((f) => f.label());
68
79
  labels.push("");
@@ -80,31 +91,53 @@ class TableField extends FieldBase {
80
91
  });
81
92
  return m;
82
93
  }, ...(ngDevMode ? [{ debugName: "fieldsMap" }] : /* istanbul ignore next */ []));
83
- dataSource = new MatTableDataSource([]);
94
+ dataSource = this.#newDataSource([]);
84
95
  clickedRows = new Set();
85
96
  paginator = viewChild(MatPaginator, ...(ngDevMode ? [{ debugName: "paginator" }] : /* istanbul ignore next */ []));
86
97
  sort = viewChild(MatSort, ...(ngDevMode ? [{ debugName: "sort" }] : /* istanbul ignore next */ []));
87
98
  #formEngine = inject(FormEngine);
99
+ #destroyRef = inject(DestroyRef);
88
100
  // view-mode cells are keyed by the row object itself, not by position: sorting and
89
101
  // paging reorder dataSource.data while keeping the row references, so an array indexed
90
102
  // by the rendered row index would show another row's values
91
103
  #rowViewFields = new WeakMap();
92
104
  // the values the row editor's fields were built with; viewRow overwrites them to show a
93
105
  // stored row, so they have to be put back before the editor is used to add a new one
94
- #pristineFieldValues = new Map(this.fields().map((f) => [f.name, f.value]));
106
+ #pristineFieldValues = new Map();
95
107
  #fieldValuesOverridden = false;
108
+ // the last payload this control itself emitted; without this, feeding jsonValue() back
109
+ // into the wrapper's ctrlJsonValue would echo straight back in as a hydration and rebuild
110
+ // dataSource (and the WeakMap-cached view fields) on every single row edit
111
+ #lastEmitted = null;
112
+ #hydrateEffectRef = effect(() => {
113
+ const incoming = this.jsonValue();
114
+ if (incoming === null || incoming === undefined || incoming === this.#lastEmitted) {
115
+ return;
116
+ }
117
+ this.#hydrateRows(incoming);
118
+ }, ...(ngDevMode ? [{ debugName: "#hydrateEffectRef" }] : /* istanbul ignore next */ []));
119
+ // columns() is an input, so it is only guaranteed to be set once Angular runs ngOnInit,
120
+ // not while this class' field initializers run
121
+ ngOnInit() {
122
+ const built = this.constructFieldChildren(this.columns());
123
+ this.fields.set(built);
124
+ this.#pristineFieldValues = new Map(built.map((f) => [f.name, f.value]));
125
+ }
96
126
  // the drawer is a viewChild, so it only exists once the view is initialised
97
127
  ngAfterViewInit() {
98
128
  this.dataSource.paginator = this.paginator() ?? null;
99
129
  this.dataSource.sort = this.sort() ?? null;
100
130
  this.drawer()?.closedStart
101
- .pipe(takeUntilDestroyed(this.destroyRef))
131
+ .pipe(takeUntilDestroyed(this.#destroyRef))
102
132
  .subscribe(() => {
103
133
  this.tableOutletForm.reset();
104
134
  this.tableOutletForm.enable();
105
135
  this.#restoreFieldValues();
106
136
  });
107
137
  }
138
+ ngOnDestroy() {
139
+ this.#hydrateEffectRef.destroy();
140
+ }
108
141
  applyFilter(event) {
109
142
  const filterValue = event.target.value;
110
143
  this.dataSource.filter = filterValue.trim().toLowerCase();
@@ -115,7 +148,7 @@ class TableField extends FieldBase {
115
148
  onRowClick(row) {
116
149
  this.clickedRows.add(row);
117
150
  }
118
- // the cell of a row rendered in view mode; the row's cells are built once and cached
151
+ // the cell of a row rendered in view mode; the row's view fields are built once and cached
119
152
  // against the row itself, so they follow it through sorting, filtering and paging
120
153
  viewFieldOf(row, index) {
121
154
  let viewFields = this.#rowViewFields.get(row);
@@ -125,8 +158,8 @@ class TableField extends FieldBase {
125
158
  }
126
159
  return viewFields[index];
127
160
  }
128
- // rows are the raw values of the row editor and carry no id, so they can only be
129
- // identified by reference
161
+ // rows carry a stable id (see #buildRow) but sorting/filtering/paging only ever hand back
162
+ // the same row references, so lookup by reference is simplest
130
163
  removeRow(row) {
131
164
  if (!this.#canModify()) {
132
165
  return;
@@ -137,28 +170,25 @@ class TableField extends FieldBase {
137
170
  }
138
171
  const newData = this.dataSource.data.filter((_, i) => i !== index);
139
172
  this.renderRows(newData);
140
- if (!newData.length) {
141
- this.ctrl.setValue(null);
142
- }
143
173
  }
144
- addRow(rows) {
174
+ addRow(values, jsonValues) {
145
175
  if (!this.#canModify()) {
146
176
  return;
147
177
  }
148
- this.#rowViewFields.set(rows, this.#fieldValuesMapper(rows));
149
- this.renderRows([...this.dataSource.data, rows]);
150
- this.ctrl.setValue("*");
178
+ const row = this.#buildRow(values, jsonValues);
179
+ this.#rowViewFields.set(row, this.#fieldValuesMapper(row));
180
+ this.renderRows([...this.dataSource.data, row]);
151
181
  }
152
182
  renderRows(rows) {
153
- this.dataSource = new MatTableDataSource(rows);
183
+ this.dataSource = this.#newDataSource(rows);
154
184
  this.dataSource.paginator = this.paginator() ?? null;
155
185
  this.dataSource.sort = this.sort() ?? null;
156
- this.field.ctrlJsonValue.set(this.dataSource.data);
186
+ this.#emitRows(rows);
157
187
  }
158
188
  viewRow(row) {
159
- this.#applyFieldValues((field) => row[field.name]);
189
+ this.#applyFieldValues((field) => this.#cellValue(row, field.name), (field) => this.#cellJsonValue(row, field.name));
160
190
  this.#fieldValuesOverridden = true;
161
- this.tableOutletForm.patchValue(row);
191
+ this.tableOutletForm.patchValue(this.#toFlatValue(row));
162
192
  this.tableOutletForm.disable();
163
193
  this.drawer()?.open();
164
194
  }
@@ -167,7 +197,7 @@ class TableField extends FieldBase {
167
197
  return;
168
198
  }
169
199
  this.tableOutletForm.enable();
170
- this.tableOutletForm.patchValue(row);
200
+ this.tableOutletForm.patchValue(this.#toFlatValue(row));
171
201
  this.drawer()?.open();
172
202
  }
173
203
  openNewRow() {
@@ -180,7 +210,8 @@ class TableField extends FieldBase {
180
210
  if (!this.#canModify()) {
181
211
  return;
182
212
  }
183
- this.addRow(this.tableOutletForm.getRawValue());
213
+ const jsonValues = new Map(this.fields().map((f) => [f.name, f.ctrlJsonValue()]));
214
+ this.addRow(this.tableOutletForm.getRawValue(), jsonValues);
184
215
  this.tableOutletForm.reset();
185
216
  if (closeDrawer) {
186
217
  this.drawer()?.close();
@@ -193,104 +224,165 @@ class TableField extends FieldBase {
193
224
  if (!this.#fieldValuesOverridden) {
194
225
  return;
195
226
  }
196
- this.#applyFieldValues((field) => this.#pristineFieldValues.get(field.name));
227
+ this.#applyFieldValues((field) => this.#pristineFieldValues.get(field.name), () => null);
197
228
  this.#fieldValuesOverridden = false;
198
229
  }
199
- #applyFieldValues(valueOf) {
230
+ #applyFieldValues(valueOf, jsonValueOf) {
200
231
  this.fields.update((fields) => fields.map((field) => {
201
232
  field.value = valueOf(field);
233
+ field.ctrlJsonValue.set(jsonValueOf(field));
202
234
  return field;
203
235
  }));
204
236
  }
205
- #fieldValuesMapper(values) {
237
+ // builds the view-mode fields for a row directly from its stored cells, so the value and
238
+ // jsonValue shown always match what was captured when the row was saved
239
+ #fieldValuesMapper(row) {
206
240
  return this.fields().map((field) => {
207
- // the row editor's fields are registered by the nested outlet against tableOutletForm,
208
- // not against the host form this table lives in
209
241
  const fieldWithJsonValue = this.#formEngine.getField(this.tableOutletForm, field.name) ?? field;
210
242
  return {
211
243
  name: fieldWithJsonValue.name,
212
244
  type: fieldWithJsonValue.type,
213
- ctrlValue: signal(values[field.name]),
214
- ctrlJsonValue: signal(fieldWithJsonValue.ctrlJsonValue()),
245
+ ctrlValue: signal(this.#cellValue(row, field.name)),
246
+ ctrlJsonValue: signal(this.#cellJsonValue(row, field.name)),
215
247
  config: fieldWithJsonValue.config,
216
248
  };
217
249
  });
218
250
  }
219
251
  #canModify() {
220
- return !this.ctrl.disabled && !this.field.config.readonly();
252
+ return !this.ctrl.disabled && !this.readonly();
221
253
  }
222
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TableField, deps: null, target: i0.ɵɵFactoryTarget.Component });
223
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TableField, isStandalone: true, selector: "iss-field-table", viewQueries: [{ propertyName: "drawer", first: true, predicate: ["drawer"], descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
224
- <mat-sidenav-container [hasBackdrop]="true">
225
- <mat-sidenav #drawer [mode]="'over'" [position]="'start'" [autoFocus]="false">
226
- <form [formGroup]="tableOutletForm">
227
- <iss-form-outlet [fields]="fields()"/>
228
- </form>
229
- <ds-button (click)="saveRow(true)">save
230
- </ds-button>
231
- <ds-button (click)="saveRow(false)">save and add more</ds-button>
232
- </mat-sidenav>
233
- <mat-sidenav-content>
234
- <div>
235
- <ds-button icon="true" (click)="openNewRow()">
236
- <ds-icon icon="plus"></ds-icon>
237
- </ds-button>
238
- <!--<button mat-raised-button (click)="removeRow()" class="demo-button">Remove data</button>-->
239
- </div>
240
- @if (field.config.tableWithFilter()) {
241
- <mat-form-field>
242
- <mat-label>Filter</mat-label>
243
- <input matInput (keyup)="applyFilter($event)" placeholder="Search in table" #input>
244
- </mat-form-field>
245
- }
246
- <div class="mat-elevation-z8">
247
- <table mat-table [dataSource]="dataSource" matSort>
248
- <tr mat-header-row *matHeaderRowDef="fieldNames()"></tr>
249
- <tr mat-row *matRowDef="let row; columns: fieldNames();" (click)="onRowClick(row)"></tr>
250
-
251
- @for (col of fieldNames(); track col) {
252
- @if (col !== "actions") {
253
- <ng-container [matColumnDef]="col">
254
- <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]="!fieldsMap().get(col)?.config?.tableWithSort()">
255
- {{ columnLabels()[$index] }}
256
- </th>
257
- <td mat-cell *matCellDef="let row">
258
- @if (viewFieldOf(row, $index); as viewField) {
259
- <iss-viewer-field [field]="viewField"/>
260
- }
261
- </td>
262
- </ng-container>
263
- }
264
- }
265
-
266
- <!-- Actions -->
267
- <ng-container matColumnDef="actions">
268
- <th mat-header-cell *matHeaderCellDef mat-sort-header></th>
269
- <td mat-cell *matCellDef="let row">
270
- <ds-icon icon="eye" class="cursor-pointer" (click)="viewRow(row)"></ds-icon>
271
- <ds-icon icon="pen" class="cursor-pointer" (click)="editRow(row)"></ds-icon>
272
- <ds-icon icon="trash" class="cursor-pointer fc-red" (click)="removeRow(row)"></ds-icon>
273
- </td>
274
- </ng-container>
275
-
276
- <tr class="mat-row" *matNoDataRow>
277
- <td class="mat-cell" colspan="4">
278
- <ds-message type="emptyCard"></ds-message>
279
- </td>
280
- </tr>
281
- </table>
282
-
283
- @if (field.config.tableWithPagination()) {
284
- <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" aria-label="Select page number"></mat-paginator>
285
- }
286
- </div>
287
- </mat-sidenav-content>
288
- </mat-sidenav-container>
289
- `, isInline: true, styles: [".mat-drawer{position:fixed;left:0}\n"], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i2.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i2.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i2.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i2.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i2.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i2.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i2.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i2.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i2.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i2.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i2.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i3.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i3.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i4.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i5.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i5.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i5.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: Outlet, selector: "iss-form-outlet", inputs: ["fields"], outputs: ["ready"] }, { kind: "component", type: FieldViewer, selector: "iss-viewer-field" }], viewProviders: [VIEW_PROVIDER] });
254
+ // sets the CVA-bound control value to the "*" sentinel (or null when the table is empty)
255
+ // and emits the full {rows} payload through the onChange output for a wrapper to consume
256
+ #emitRows(rows) {
257
+ const submission = this.#toSubmission(rows);
258
+ this.#lastEmitted = submission;
259
+ this.ctrl.setValue(rows.length ? "*" : null);
260
+ this.propagateValue();
261
+ this.emitOnChangeEvent(submission);
262
+ }
263
+ // rebuilds dataSource from a jsonValue payload pushed in from outside (see the `jsonValue`
264
+ // input); accepts either our own {rows: TableRow[]} shape or a plain array of flat
265
+ // {fieldName: value} row objects
266
+ #hydrateRows(payload) {
267
+ const incomingRows = Array.isArray(payload?.rows) ? payload.rows : Array.isArray(payload) ? payload : [];
268
+ const rows = incomingRows.map((row) => this.#normalizeRow(row));
269
+ rows.forEach((row) => this.#rowViewFields.set(row, this.#fieldValuesMapper(row)));
270
+ this.dataSource = this.#newDataSource(rows);
271
+ this.dataSource.paginator = this.paginator() ?? null;
272
+ this.dataSource.sort = this.sort() ?? null;
273
+ this.ctrl.setValue(rows.length ? "*" : null, { emitEvent: false });
274
+ }
275
+ #normalizeRow(row) {
276
+ if (Array.isArray(row?.cells)) {
277
+ return { id: row.id ?? crypto.randomUUID(), index: row.index ?? 0, cells: row.cells };
278
+ }
279
+ return this.#buildRow(row);
280
+ }
281
+ // the canonical row shape (see TableRow) is used for dataSource.data itself, so the
282
+ // submission is just that shape with the current, post-sort/filter position stamped in
283
+ #toSubmission(rows) {
284
+ return { rows: rows.map((row, index) => ({ ...row, index })) };
285
+ }
286
+ #buildRow(values, jsonValues) {
287
+ return {
288
+ id: crypto.randomUUID(),
289
+ index: this.dataSource.data.length,
290
+ cells: this.fields().map((field) => ({
291
+ fieldName: field.name,
292
+ value: values[field.name],
293
+ jsonValue: jsonValues?.get(field.name) ?? null,
294
+ })),
295
+ };
296
+ }
297
+ #cellValue(row, fieldName) {
298
+ return row.cells.find((cell) => cell.fieldName === fieldName)?.value;
299
+ }
300
+ #cellJsonValue(row, fieldName) {
301
+ return row.cells.find((cell) => cell.fieldName === fieldName)?.jsonValue ?? null;
302
+ }
303
+ #toFlatValue(row) {
304
+ return Object.fromEntries(row.cells.map((cell) => [cell.fieldName, cell.value]));
305
+ }
306
+ #newDataSource(rows) {
307
+ const dataSource = new MatTableDataSource(rows);
308
+ dataSource.filterPredicate = (row, filter) => row.cells.some((cell) => `${cell.value ?? ""}`.toLowerCase().includes(filter));
309
+ dataSource.sortingDataAccessor = (row, sortHeaderId) => this.#cellValue(row, sortHeaderId) ?? "";
310
+ return dataSource;
311
+ }
312
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TableControl, deps: null, target: i0.ɵɵFactoryTarget.Component });
313
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TableControl, isStandalone: true, selector: "iss-ctrl-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, withFilter: { classPropertyName: "withFilter", publicName: "withFilter", isSignal: true, isRequired: false, transformFunction: null }, withSort: { classPropertyName: "withSort", publicName: "withSort", isSignal: true, isRequired: false, transformFunction: null }, withPagination: { classPropertyName: "withPagination", publicName: "withPagination", isSignal: true, isRequired: false, transformFunction: null }, jsonValue: { classPropertyName: "jsonValue", publicName: "jsonValue", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
314
+ { provide: NG_VALUE_ACCESSOR, useExisting: TableControl, multi: true },
315
+ ], viewQueries: [{ propertyName: "drawer", first: true, predicate: ["drawer"], descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
316
+ <mat-sidenav-container [hasBackdrop]="true">
317
+ <mat-sidenav #drawer [mode]="'over'" [position]="'start'" [autoFocus]="false">
318
+ <form [formGroup]="tableOutletForm">
319
+ <iss-form-outlet [fields]="fields()"/>
320
+ </form>
321
+ <ds-button (click)="saveRow(true)">save
322
+ </ds-button>
323
+ <ds-button (click)="saveRow(false)">save and add more</ds-button>
324
+ </mat-sidenav>
325
+ <mat-sidenav-content>
326
+ <div>
327
+ <ds-button icon="true" (click)="openNewRow()">
328
+ <ds-icon icon="plus"></ds-icon>
329
+ </ds-button>
330
+ <!--<button mat-raised-button (click)="removeRow()" class="demo-button">Remove data</button>-->
331
+ </div>
332
+ @if (withFilter()) {
333
+ <mat-form-field>
334
+ <mat-label>Filter</mat-label>
335
+ <input matInput (keyup)="applyFilter($event)" placeholder="Search in table" #input>
336
+ </mat-form-field>
337
+ }
338
+ <div class="mat-elevation-z8">
339
+ <table mat-table [dataSource]="dataSource" matSort>
340
+ <tr mat-header-row *matHeaderRowDef="fieldNames()"></tr>
341
+ <tr mat-row *matRowDef="let row; columns: fieldNames();" (click)="onRowClick(row)"></tr>
342
+
343
+ @for (col of fieldNames(); track col) {
344
+ @if (col !== "actions") {
345
+ <ng-container [matColumnDef]="col">
346
+ <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]="!fieldsMap().get(col)?.config?.tableWithSort()">
347
+ {{ columnLabels()[$index] }}
348
+ </th>
349
+ <td mat-cell *matCellDef="let row">
350
+ @if (viewFieldOf(row, $index); as viewField) {
351
+ <iss-viewer-field [field]="viewField"/>
352
+ }
353
+ </td>
354
+ </ng-container>
355
+ }
356
+ }
357
+
358
+ <!-- Actions -->
359
+ <ng-container matColumnDef="actions">
360
+ <th mat-header-cell *matHeaderCellDef mat-sort-header></th>
361
+ <td mat-cell *matCellDef="let row">
362
+ <ds-icon icon="eye" class="cursor-pointer" (click)="viewRow(row)"></ds-icon>
363
+ <ds-icon icon="pen" class="cursor-pointer" (click)="editRow(row)"></ds-icon>
364
+ <ds-icon icon="trash" class="cursor-pointer fc-red" (click)="removeRow(row)"></ds-icon>
365
+ </td>
366
+ </ng-container>
367
+
368
+ <tr class="mat-row" *matNoDataRow>
369
+ <td class="mat-cell" colspan="4">
370
+ <ds-message type="emptyCard"></ds-message>
371
+ </td>
372
+ </tr>
373
+ </table>
374
+
375
+ @if (withPagination()) {
376
+ <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" aria-label="Select page number"></mat-paginator>
377
+ }
378
+ </div>
379
+ </mat-sidenav-content>
380
+ </mat-sidenav-container>
381
+ `, isInline: true, styles: [".mat-drawer{position:fixed;left:0}\n"], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i2.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i2.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i2.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i2.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i2.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i2.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i2.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i2.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i2.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i2.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i2.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i3.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i3.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i4.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i5.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i5.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i5.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: Outlet, selector: "iss-form-outlet", inputs: ["fields"], outputs: ["ready"] }, { kind: "component", type: FieldViewer, selector: "iss-viewer-field" }] });
290
382
  }
291
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TableField, decorators: [{
383
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TableControl, decorators: [{
292
384
  type: Component,
293
- args: [{ selector: "iss-field-table", viewProviders: [VIEW_PROVIDER], imports: [
385
+ args: [{ selector: "iss-ctrl-table", imports: [
294
386
  MatFormFieldModule,
295
387
  MatInputModule,
296
388
  MatTableModule,
@@ -300,74 +392,126 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
300
392
  ReactiveFormsModule,
301
393
  Outlet,
302
394
  FieldViewer,
303
- ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
304
- <mat-sidenav-container [hasBackdrop]="true">
305
- <mat-sidenav #drawer [mode]="'over'" [position]="'start'" [autoFocus]="false">
306
- <form [formGroup]="tableOutletForm">
307
- <iss-form-outlet [fields]="fields()"/>
308
- </form>
309
- <ds-button (click)="saveRow(true)">save
310
- </ds-button>
311
- <ds-button (click)="saveRow(false)">save and add more</ds-button>
312
- </mat-sidenav>
313
- <mat-sidenav-content>
314
- <div>
315
- <ds-button icon="true" (click)="openNewRow()">
316
- <ds-icon icon="plus"></ds-icon>
317
- </ds-button>
318
- <!--<button mat-raised-button (click)="removeRow()" class="demo-button">Remove data</button>-->
319
- </div>
320
- @if (field.config.tableWithFilter()) {
321
- <mat-form-field>
322
- <mat-label>Filter</mat-label>
323
- <input matInput (keyup)="applyFilter($event)" placeholder="Search in table" #input>
324
- </mat-form-field>
325
- }
326
- <div class="mat-elevation-z8">
327
- <table mat-table [dataSource]="dataSource" matSort>
328
- <tr mat-header-row *matHeaderRowDef="fieldNames()"></tr>
329
- <tr mat-row *matRowDef="let row; columns: fieldNames();" (click)="onRowClick(row)"></tr>
330
-
331
- @for (col of fieldNames(); track col) {
332
- @if (col !== "actions") {
333
- <ng-container [matColumnDef]="col">
334
- <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]="!fieldsMap().get(col)?.config?.tableWithSort()">
335
- {{ columnLabels()[$index] }}
336
- </th>
337
- <td mat-cell *matCellDef="let row">
338
- @if (viewFieldOf(row, $index); as viewField) {
339
- <iss-viewer-field [field]="viewField"/>
340
- }
341
- </td>
342
- </ng-container>
343
- }
344
- }
345
-
346
- <!-- Actions -->
347
- <ng-container matColumnDef="actions">
348
- <th mat-header-cell *matHeaderCellDef mat-sort-header></th>
349
- <td mat-cell *matCellDef="let row">
350
- <ds-icon icon="eye" class="cursor-pointer" (click)="viewRow(row)"></ds-icon>
351
- <ds-icon icon="pen" class="cursor-pointer" (click)="editRow(row)"></ds-icon>
352
- <ds-icon icon="trash" class="cursor-pointer fc-red" (click)="removeRow(row)"></ds-icon>
353
- </td>
354
- </ng-container>
355
-
356
- <tr class="mat-row" *matNoDataRow>
357
- <td class="mat-cell" colspan="4">
358
- <ds-message type="emptyCard"></ds-message>
359
- </td>
360
- </tr>
361
- </table>
362
-
363
- @if (field.config.tableWithPagination()) {
364
- <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" aria-label="Select page number"></mat-paginator>
365
- }
366
- </div>
367
- </mat-sidenav-content>
368
- </mat-sidenav-container>
395
+ ], providers: [
396
+ { provide: NG_VALUE_ACCESSOR, useExisting: TableControl, multi: true },
397
+ ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
398
+ <mat-sidenav-container [hasBackdrop]="true">
399
+ <mat-sidenav #drawer [mode]="'over'" [position]="'start'" [autoFocus]="false">
400
+ <form [formGroup]="tableOutletForm">
401
+ <iss-form-outlet [fields]="fields()"/>
402
+ </form>
403
+ <ds-button (click)="saveRow(true)">save
404
+ </ds-button>
405
+ <ds-button (click)="saveRow(false)">save and add more</ds-button>
406
+ </mat-sidenav>
407
+ <mat-sidenav-content>
408
+ <div>
409
+ <ds-button icon="true" (click)="openNewRow()">
410
+ <ds-icon icon="plus"></ds-icon>
411
+ </ds-button>
412
+ <!--<button mat-raised-button (click)="removeRow()" class="demo-button">Remove data</button>-->
413
+ </div>
414
+ @if (withFilter()) {
415
+ <mat-form-field>
416
+ <mat-label>Filter</mat-label>
417
+ <input matInput (keyup)="applyFilter($event)" placeholder="Search in table" #input>
418
+ </mat-form-field>
419
+ }
420
+ <div class="mat-elevation-z8">
421
+ <table mat-table [dataSource]="dataSource" matSort>
422
+ <tr mat-header-row *matHeaderRowDef="fieldNames()"></tr>
423
+ <tr mat-row *matRowDef="let row; columns: fieldNames();" (click)="onRowClick(row)"></tr>
424
+
425
+ @for (col of fieldNames(); track col) {
426
+ @if (col !== "actions") {
427
+ <ng-container [matColumnDef]="col">
428
+ <th mat-header-cell *matHeaderCellDef mat-sort-header [disabled]="!fieldsMap().get(col)?.config?.tableWithSort()">
429
+ {{ columnLabels()[$index] }}
430
+ </th>
431
+ <td mat-cell *matCellDef="let row">
432
+ @if (viewFieldOf(row, $index); as viewField) {
433
+ <iss-viewer-field [field]="viewField"/>
434
+ }
435
+ </td>
436
+ </ng-container>
437
+ }
438
+ }
439
+
440
+ <!-- Actions -->
441
+ <ng-container matColumnDef="actions">
442
+ <th mat-header-cell *matHeaderCellDef mat-sort-header></th>
443
+ <td mat-cell *matCellDef="let row">
444
+ <ds-icon icon="eye" class="cursor-pointer" (click)="viewRow(row)"></ds-icon>
445
+ <ds-icon icon="pen" class="cursor-pointer" (click)="editRow(row)"></ds-icon>
446
+ <ds-icon icon="trash" class="cursor-pointer fc-red" (click)="removeRow(row)"></ds-icon>
447
+ </td>
448
+ </ng-container>
449
+
450
+ <tr class="mat-row" *matNoDataRow>
451
+ <td class="mat-cell" colspan="4">
452
+ <ds-message type="emptyCard"></ds-message>
453
+ </td>
454
+ </tr>
455
+ </table>
456
+
457
+ @if (withPagination()) {
458
+ <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" aria-label="Select page number"></mat-paginator>
459
+ }
460
+ </div>
461
+ </mat-sidenav-content>
462
+ </mat-sidenav-container>
369
463
  `, styles: [".mat-drawer{position:fixed;left:0}\n"] }]
370
- }], propDecorators: { drawer: [{ type: i0.ViewChild, args: ["drawer", { isSignal: true }] }], paginator: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatPaginator), { isSignal: true }] }], sort: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatSort), { isSignal: true }] }] } });
464
+ }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], withFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "withFilter", required: false }] }], withSort: [{ type: i0.Input, args: [{ isSignal: true, alias: "withSort", required: false }] }], withPagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "withPagination", required: false }] }], jsonValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "jsonValue", required: false }] }], drawer: [{ type: i0.ViewChild, args: ["drawer", { isSignal: true }] }], paginator: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatPaginator), { isSignal: true }] }], sort: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatSort), { isSignal: true }] }] } });
465
+
466
+ class TableField extends FieldBase {
467
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TableField, deps: null, target: i0.ɵɵFactoryTarget.Component });
468
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TableField, isStandalone: true, selector: "iss-field-table", usesInheritance: true, ngImport: i0, template: `
469
+ @if (field.visible()) {
470
+ @if (field.mode() === "edit") {
471
+ <iss-ctrl-table
472
+ [formControlName]="field.name"
473
+ [columns]="field.children"
474
+ [withFilter]="field.config.tableWithFilter() ?? false"
475
+ [withSort]="field.config.tableWithSort() ?? false"
476
+ [withPagination]="field.config.tableWithPagination() ?? false"
477
+ [readonly]="field.config.readonly() ?? false"
478
+ [jsonValue]="field.ctrlJsonValue()"
479
+ (onChange)="field.ctrlJsonValue.set($event)"
480
+ />
481
+ <iss-validation-message-viewer [errors]="ctrl.errors" [showMessage]="!ctrl.untouched"/>
482
+ }
483
+ }
484
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: TableControl, selector: "iss-ctrl-table", inputs: ["columns", "withFilter", "withSort", "withPagination", "jsonValue"] }, { kind: "component", type: ValidationMessageComponent, selector: "iss-validation-message-viewer", inputs: ["errors", "showMessage"] }], viewProviders: [VIEW_PROVIDER] });
485
+ }
486
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TableField, decorators: [{
487
+ type: Component,
488
+ args: [{
489
+ selector: "iss-field-table",
490
+ viewProviders: [VIEW_PROVIDER],
491
+ imports: [
492
+ ReactiveFormsModule,
493
+ TableControl,
494
+ ValidationMessageComponent,
495
+ ],
496
+ template: `
497
+ @if (field.visible()) {
498
+ @if (field.mode() === "edit") {
499
+ <iss-ctrl-table
500
+ [formControlName]="field.name"
501
+ [columns]="field.children"
502
+ [withFilter]="field.config.tableWithFilter() ?? false"
503
+ [withSort]="field.config.tableWithSort() ?? false"
504
+ [withPagination]="field.config.tableWithPagination() ?? false"
505
+ [readonly]="field.config.readonly() ?? false"
506
+ [jsonValue]="field.ctrlJsonValue()"
507
+ (onChange)="field.ctrlJsonValue.set($event)"
508
+ />
509
+ <iss-validation-message-viewer [errors]="ctrl.errors" [showMessage]="!ctrl.untouched"/>
510
+ }
511
+ }
512
+ `
513
+ }]
514
+ }] });
371
515
 
372
516
  export { TableField };
373
- //# sourceMappingURL=iss-ctrl-table.field-B42zKves.mjs.map
517
+ //# sourceMappingURL=iss-ctrl-table.field-kPIwve-M.mjs.map