x4js 2.0.13 → 2.0.15

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 (260) hide show
  1. package/.vscode/launch.json +14 -0
  2. package/README.md +5 -0
  3. package/{lib/src/demo → demo}/main.scss +3 -1
  4. package/{lib/src/demo/main.tsx → demo/main.ts} +37 -36
  5. package/demo/package.json +26 -0
  6. package/demo/scss.d.ts +4 -0
  7. package/demo/svg.d.ts +1 -0
  8. package/demo/tsconfig.json +14 -0
  9. package/lib/README.txt +5 -0
  10. package/lib/cjs/x4.css +1 -1
  11. package/lib/cjs/x4.js +2 -1
  12. package/lib/esm/x4.css +1 -1
  13. package/lib/esm/x4.mjs +2 -1
  14. package/lib/src/components/boxes/boxes.module.scss +17 -0
  15. package/lib/src/components/boxes/boxes.ts +258 -17
  16. package/lib/src/components/breadcrumb/breadcrumb.scss +56 -28
  17. package/lib/src/components/breadcrumb/breadcrumb.ts +93 -84
  18. package/lib/src/components/btngroup/btngroup.module.scss +12 -0
  19. package/lib/src/components/btngroup/btngroup.ts +41 -8
  20. package/lib/src/components/button/button.module.scss +23 -5
  21. package/lib/src/components/button/button.ts +72 -4
  22. package/lib/src/components/canvas/canvas.module.scss +25 -0
  23. package/lib/src/components/canvas/canvas.ts +189 -0
  24. package/lib/src/components/canvas/canvas_ex.ts +276 -0
  25. package/lib/src/components/checkbox/checkbox.ts +18 -4
  26. package/lib/src/components/combobox/combobox.module.scss +24 -15
  27. package/lib/src/components/combobox/combobox.ts +107 -24
  28. package/lib/src/components/components.ts +7 -0
  29. package/lib/src/components/dialog/dialog.module.scss +40 -7
  30. package/lib/src/components/dialog/dialog.ts +166 -31
  31. package/lib/src/components/filedrop/cloud-arrow-up.svg +1 -0
  32. package/lib/src/components/filedrop/filedrop.module.scss +70 -0
  33. package/lib/src/components/filedrop/filedrop.ts +131 -0
  34. package/lib/src/components/form/form.module.scss +4 -0
  35. package/lib/src/components/form/form.ts +137 -6
  36. package/lib/src/components/gridview/arrow-down-light.svg +1 -0
  37. package/lib/src/components/gridview/arrow-up-light.svg +1 -0
  38. package/lib/src/components/gridview/gridview.module.scss +324 -0
  39. package/lib/src/components/gridview/gridview.ts +1175 -0
  40. package/lib/src/components/icon/icon.module.scss +2 -1
  41. package/lib/src/components/icon/icon.ts +4 -3
  42. package/lib/src/components/image/image.module.scss +8 -1
  43. package/lib/src/components/image/image.ts +105 -6
  44. package/lib/src/components/input/input.module.scss +8 -3
  45. package/lib/src/components/input/input.ts +178 -31
  46. package/lib/src/components/keyboard/arrow-up.svg +1 -0
  47. package/lib/src/components/keyboard/delete-left.svg +1 -0
  48. package/lib/src/components/keyboard/eye-slash.svg +1 -0
  49. package/lib/src/components/keyboard/keyboard.module.scss +134 -0
  50. package/lib/src/components/keyboard/keyboard.ts +526 -0
  51. package/lib/src/components/label/label.module.scss +22 -4
  52. package/lib/src/components/label/label.ts +33 -0
  53. package/lib/src/components/link/link.ts +81 -78
  54. package/lib/src/components/listbox/listbox.module.scss +61 -3
  55. package/lib/src/components/listbox/listbox.ts +164 -56
  56. package/lib/src/components/menu/menu.module.scss +10 -1
  57. package/lib/src/components/menu/menu.ts +6 -3
  58. package/lib/src/components/messages/messages.module.scss +44 -0
  59. package/lib/src/components/messages/messages.ts +164 -18
  60. package/lib/src/components/messages/pen-field.svg +1 -0
  61. package/lib/src/components/normalize.scss +5 -0
  62. package/lib/src/components/notification/notification.module.scss +4 -2
  63. package/lib/src/components/notification/notification.ts +2 -4
  64. package/lib/src/components/panel/panel.module.scss +12 -0
  65. package/lib/src/components/popup/popup.module.scss +10 -2
  66. package/lib/src/components/popup/popup.ts +141 -95
  67. package/lib/src/components/propgrid/folder-closed.svg +1 -0
  68. package/lib/src/components/propgrid/folder-open.svg +1 -0
  69. package/lib/src/components/propgrid/progrid.module.scss +112 -0
  70. package/lib/src/components/propgrid/propgrid.ts +288 -0
  71. package/lib/src/components/propgrid/updown.svg +4 -0
  72. package/lib/src/components/radio/radio.module.scss +147 -0
  73. package/lib/src/components/radio/radio.svg +4 -0
  74. package/lib/src/components/radio/radio.ts +142 -0
  75. package/lib/src/components/select/select.module.scss +9 -0
  76. package/lib/src/components/select/select.ts +134 -0
  77. package/lib/src/components/shared.scss +47 -0
  78. package/lib/src/components/sizers/sizer.ts +10 -2
  79. package/lib/src/components/slider/slider.module.scss +77 -30
  80. package/lib/src/components/slider/slider.ts +72 -22
  81. package/lib/src/components/tabs/tabs.module.scss +1 -2
  82. package/lib/src/components/tabs/tabs.ts +49 -12
  83. package/lib/src/components/textarea/textarea.module.scss +6 -2
  84. package/lib/src/components/textarea/textarea.ts +73 -8
  85. package/lib/src/components/textedit/textedit.module.scss +3 -1
  86. package/lib/src/components/textedit/textedit.ts +47 -15
  87. package/lib/src/components/themes.scss +7 -0
  88. package/lib/src/components/tickline/tickline.module.scss +26 -0
  89. package/lib/src/components/tickline/tickline.ts +82 -0
  90. package/lib/src/components/tooltips/comments-question.svg +1 -0
  91. package/lib/src/components/tooltips/tooltips.scss +30 -9
  92. package/lib/src/components/tooltips/tooltips.ts +10 -5
  93. package/lib/src/components/treeview/treeview.module.scss +129 -60
  94. package/lib/src/components/treeview/treeview.ts +47 -12
  95. package/lib/src/components/viewport/viewport.module.scss +7 -0
  96. package/lib/src/core/component.ts +113 -40
  97. package/lib/src/core/core_application.ts +223 -2
  98. package/lib/src/core/core_colors.ts +2 -2
  99. package/lib/src/{components/grid/datastore.ts → core/core_data.ts} +264 -252
  100. package/lib/src/core/core_dragdrop.ts +3 -3
  101. package/lib/src/core/core_element.ts +18 -1
  102. package/lib/src/core/core_events.ts +28 -0
  103. package/lib/src/core/core_i18n.ts +19 -3
  104. package/lib/src/core/core_react.ts +79 -0
  105. package/lib/src/core/core_router.ts +25 -9
  106. package/lib/src/core/core_state.ts +62 -0
  107. package/lib/src/core/core_styles.ts +5 -5
  108. package/lib/src/core/core_svg.ts +174 -12
  109. package/lib/src/core/core_tools.ts +305 -87
  110. package/lib/src/x4tsx.d.ts +25 -0
  111. package/lib/styles/x4.css +1 -1
  112. package/lib/types/x4js.d.ts +828 -119
  113. package/package.json +4 -4
  114. package/scripts/build.mjs +378 -0
  115. package/scripts/prepack.mjs +346 -0
  116. package/src/components/base.scss +25 -0
  117. package/src/components/boxes/boxes.module.scss +54 -0
  118. package/src/components/boxes/boxes.ts +370 -0
  119. package/src/components/breadcrumb/breadcrumb.scss +56 -0
  120. package/src/components/breadcrumb/breadcrumb.ts +93 -0
  121. package/src/components/breadcrumb/chevron-right.svg +1 -0
  122. package/src/components/btngroup/btngroup.module.scss +41 -0
  123. package/src/components/btngroup/btngroup.ts +153 -0
  124. package/src/components/button/button.module.scss +173 -0
  125. package/src/components/button/button.ts +185 -0
  126. package/src/components/calendar/calendar-check-sharp-light.svg +1 -0
  127. package/src/components/calendar/calendar.module.scss +163 -0
  128. package/src/components/calendar/calendar.ts +327 -0
  129. package/src/components/calendar/chevron-left-sharp-light.svg +1 -0
  130. package/src/components/calendar/chevron-right-sharp-light.svg +1 -0
  131. package/src/components/canvas/canvas.module.scss +25 -0
  132. package/src/components/canvas/canvas.ts +189 -0
  133. package/src/components/canvas/canvas_ex.ts +276 -0
  134. package/src/components/checkbox/check.svg +4 -0
  135. package/src/components/checkbox/checkbox.module.scss +142 -0
  136. package/src/components/checkbox/checkbox.ts +140 -0
  137. package/src/components/colorinput/colorinput.module.scss +65 -0
  138. package/src/components/colorinput/colorinput.ts +91 -0
  139. package/src/components/colorinput/crosshairs-simple-sharp-light.svg +1 -0
  140. package/src/components/colorpicker/colorpicker.module.scss +133 -0
  141. package/src/components/colorpicker/colorpicker.ts +482 -0
  142. package/src/components/combobox/combobox.module.scss +133 -0
  143. package/src/components/combobox/combobox.ts +275 -0
  144. package/src/components/combobox/updown.svg +4 -0
  145. package/src/components/components.ts +41 -0
  146. package/src/components/dialog/dialog.module.scss +104 -0
  147. package/src/components/dialog/dialog.ts +229 -0
  148. package/src/components/dialog/xmark-sharp-light.svg +1 -0
  149. package/src/components/filedrop/cloud-arrow-up.svg +1 -0
  150. package/src/components/filedrop/filedrop.module.scss +70 -0
  151. package/src/components/filedrop/filedrop.ts +131 -0
  152. package/src/components/form/form.module.scss +38 -0
  153. package/src/components/form/form.ts +172 -0
  154. package/src/components/gridview/arrow-down-light.svg +1 -0
  155. package/src/components/gridview/arrow-up-light.svg +1 -0
  156. package/src/components/gridview/gridview.module.scss +324 -0
  157. package/src/components/gridview/gridview.ts +1175 -0
  158. package/src/components/header/header.module.scss +40 -0
  159. package/src/components/header/header.ts +130 -0
  160. package/src/components/icon/icon.module.scss +31 -0
  161. package/src/components/icon/icon.ts +137 -0
  162. package/src/components/image/image.module.scss +28 -0
  163. package/src/components/image/image.ts +168 -0
  164. package/src/components/input/input.module.scss +74 -0
  165. package/src/components/input/input.ts +422 -0
  166. package/src/components/keyboard/arrow-up.svg +1 -0
  167. package/src/components/keyboard/delete-left.svg +1 -0
  168. package/src/components/keyboard/eye-slash.svg +1 -0
  169. package/src/components/keyboard/keyboard.module.scss +134 -0
  170. package/src/components/keyboard/keyboard.ts +526 -0
  171. package/src/components/label/label.module.scss +76 -0
  172. package/src/components/label/label.ts +97 -0
  173. package/src/components/link/link.ts +81 -0
  174. package/src/components/listbox/listbox.module.scss +161 -0
  175. package/src/components/listbox/listbox.ts +539 -0
  176. package/src/components/menu/caret-right-solid.svg +1 -0
  177. package/src/components/menu/menu.module.scss +117 -0
  178. package/src/components/menu/menu.ts +174 -0
  179. package/src/components/messages/circle-exclamation.svg +1 -0
  180. package/src/components/messages/messages.module.scss +92 -0
  181. package/src/components/messages/messages.ts +215 -0
  182. package/src/components/messages/pen-field.svg +1 -0
  183. package/src/components/normalize.scss +391 -0
  184. package/src/components/notification/circle-check-solid.svg +1 -0
  185. package/src/components/notification/circle-exclamation-solid.svg +1 -0
  186. package/src/components/notification/circle-notch-light.svg +1 -0
  187. package/src/components/notification/notification.module.scss +84 -0
  188. package/src/components/notification/notification.ts +107 -0
  189. package/src/components/notification/xmark-sharp-light.svg +1 -0
  190. package/src/components/panel/panel.module.scss +60 -0
  191. package/src/components/panel/panel.ts +58 -0
  192. package/src/components/popup/popup.module.scss +51 -0
  193. package/src/components/popup/popup.ts +442 -0
  194. package/src/components/progress/progress.module.scss +57 -0
  195. package/src/components/progress/progress.ts +44 -0
  196. package/src/components/propgrid/folder-closed.svg +1 -0
  197. package/src/components/propgrid/folder-open.svg +1 -0
  198. package/src/components/propgrid/progrid.module.scss +112 -0
  199. package/src/components/propgrid/propgrid.ts +288 -0
  200. package/src/components/propgrid/updown.svg +4 -0
  201. package/src/components/radio/radio.module.scss +147 -0
  202. package/src/components/radio/radio.svg +4 -0
  203. package/src/components/radio/radio.ts +142 -0
  204. package/src/components/rating/rating.module.scss +23 -0
  205. package/src/components/rating/rating.ts +131 -0
  206. package/src/components/rating/star-sharp-light.svg +1 -0
  207. package/src/components/rating/star-sharp-solid.svg +1 -0
  208. package/src/components/select/select.module.scss +9 -0
  209. package/src/components/select/select.ts +134 -0
  210. package/src/components/shared.scss +137 -0
  211. package/src/components/sizers/sizer.module.scss +90 -0
  212. package/src/components/sizers/sizer.ts +132 -0
  213. package/src/components/slider/slider.module.scss +118 -0
  214. package/src/components/slider/slider.ts +198 -0
  215. package/src/components/switch/switch.module.scss +127 -0
  216. package/src/components/switch/switch.ts +62 -0
  217. package/src/components/tabs/tabs.module.scss +45 -0
  218. package/src/components/tabs/tabs.ts +205 -0
  219. package/src/components/textarea/textarea.module.scss +63 -0
  220. package/src/components/textarea/textarea.ts +125 -0
  221. package/src/components/textedit/textedit.module.scss +116 -0
  222. package/src/components/textedit/textedit.ts +115 -0
  223. package/src/components/themes.scss +88 -0
  224. package/src/components/tickline/tickline.module.scss +26 -0
  225. package/src/components/tickline/tickline.ts +82 -0
  226. package/src/components/tooltips/circle-info-sharp-light.svg +1 -0
  227. package/src/components/tooltips/comments-question.svg +1 -0
  228. package/src/components/tooltips/tooltips.scss +72 -0
  229. package/src/components/tooltips/tooltips.ts +109 -0
  230. package/src/components/treeview/chevron-down-light.svg +1 -0
  231. package/src/components/treeview/treeview.module.scss +185 -0
  232. package/src/components/treeview/treeview.ts +445 -0
  233. package/src/components/viewport/viewport.module.scss +32 -0
  234. package/src/components/viewport/viewport.ts +41 -0
  235. package/src/core/component.ts +1075 -0
  236. package/src/core/core_application.ts +265 -0
  237. package/src/core/core_colors.ts +250 -0
  238. package/src/core/core_data.ts +1310 -0
  239. package/src/core/core_dom.ts +471 -0
  240. package/src/core/core_dragdrop.ts +201 -0
  241. package/src/core/core_element.ts +115 -0
  242. package/src/core/core_events.ts +177 -0
  243. package/src/core/core_i18n.ts +393 -0
  244. package/src/core/core_react.ts +79 -0
  245. package/src/core/core_router.ts +237 -0
  246. package/src/core/core_state.ts +62 -0
  247. package/src/core/core_styles.ts +214 -0
  248. package/src/core/core_svg.ts +712 -0
  249. package/src/core/core_tools.ts +906 -0
  250. package/src/types/scss.d.ts +4 -0
  251. package/src/types/svg.d.ts +1 -0
  252. package/src/types/x4react.d.ts +9 -0
  253. package/src/x4.scss +19 -0
  254. package/src/x4tsx.d.ts +25 -0
  255. package/tsconfig.json +14 -0
  256. package/lib/src/components/grid/gridview.ts +0 -1108
  257. package/lib/src/components/grid/memdb.ts +0 -325
  258. /package/{lib/src/demo → demo}/assets/house-light.svg +0 -0
  259. /package/{lib/src/demo → demo}/assets/radio.svg +0 -0
  260. /package/{lib/src/demo → demo}/index.html +0 -0
@@ -5,7 +5,7 @@
5
5
  * / \____ _|
6
6
  * /__/\__\ |_|
7
7
  *
8
- * @file datastore.ts
8
+ * @file core_data.ts
9
9
  * @author Etienne Cochard
10
10
  *
11
11
  * @copyright (c) 2024 R-libre ingenierie
@@ -14,15 +14,16 @@
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  **/
16
16
 
17
- import { ComponentEvents, ComponentProps, EvChange } from '@core/component.js';
17
+
18
+ import { EvChange } from '@core/component.js';
18
19
  import { CoreElement } from '@core/core_element.js';
19
20
  import { CoreEvent, EventCallback, EventMap, EventSource } from '@core/core_events.js';
20
21
  import { isArray, isString } from '@core/core_tools.js';
21
- import { Component } from 'x4js';
22
-
23
22
 
23
+ export type DataRecordID = any;
24
+ export type DataFieldValue = string | Date | number | boolean;
24
25
 
25
- export type ChangeCallback = (type: string, id?: any) => void;
26
+ export type ChangeCallback = (type: string, id?: DataRecordID) => void;
26
27
  export type CalcCallback = () => string;
27
28
 
28
29
  export type FieldType = 'string' | 'int' | 'float' | 'date' | 'bool' | 'array' | 'object' | 'any' | 'calc';
@@ -30,7 +31,7 @@ export type DataIndex = Uint32Array;
30
31
 
31
32
  export interface EvDataChange extends CoreEvent {
32
33
  change_type: 'create' | 'update' | 'delete' | 'data' | 'change';
33
- id?: any;
34
+ id?: DataRecordID;
34
35
  }
35
36
 
36
37
 
@@ -47,8 +48,8 @@ export interface MetaData {
47
48
  type?: FieldType;
48
49
  prec?: number;
49
50
  required?: boolean;
50
- calc?: (rec: Record) => any;
51
- model?: Record; // in case of array of subtypes, the model
51
+ calc?: (rec: DataRecord) => any;
52
+ model?: DataModel; // in case of array of subtypes, the model
52
53
  }
53
54
 
54
55
  export interface FieldInfo extends MetaData {
@@ -76,7 +77,7 @@ const metaFields = Symbol( 'metaField' );
76
77
  function _getMetas( obj: object, create = true ) : MetaInfos {
77
78
 
78
79
  let ctor = obj.constructor as any;
79
- let mfld = ctor.hasOwnProperty(metaFields) ? ctor[metaFields] : undefined;
80
+ let mfld = Object.prototype.hasOwnProperty.call(ctor,metaFields) ? ctor[metaFields] : undefined;
80
81
 
81
82
  if( mfld===undefined ) {
82
83
  if( !create ) {
@@ -88,7 +89,7 @@ function _getMetas( obj: object, create = true ) : MetaInfos {
88
89
 
89
90
  // merge with parent class metas
90
91
  let pctor = Object.getPrototypeOf(ctor);
91
- if( pctor!=Record ) {
92
+ if( pctor!=DataModel ) {
92
93
  let pmetas = pctor[metaFields];
93
94
  mfld.fields = [...pmetas.fields, ...mfld.fields ]
94
95
 
@@ -104,14 +105,15 @@ function _getMetas( obj: object, create = true ) : MetaInfos {
104
105
  return mfld;
105
106
  }
106
107
 
108
+ // eslint-disable-next-line @typescript-eslint/no-namespace
107
109
  export namespace data {
108
110
 
109
- /**
110
- * define a record id
111
- * @example
112
- * \@data_id()
113
- * id: string; // this field is the record id
114
- **/
111
+ /**
112
+ * define a model id
113
+ * @example
114
+ * \@data_id()
115
+ * id: string; // this field is the record id
116
+ **/
115
117
 
116
118
  export function id( ) {
117
119
  return ( ownerCls: any, fldName: string ) => {
@@ -126,110 +128,118 @@ export namespace data {
126
128
  }
127
129
  }
128
130
 
129
- /**
130
- * @ignore
131
- */
131
+ /**
132
+ * @ignore
133
+ */
132
134
 
133
135
  export function field( data: MetaData ) {
134
136
 
135
- return ( ownerCls: any, fldName: string ) => {
136
- let metas = _getMetas( ownerCls );
137
- metas.fields.push( {
138
- name: fldName,
139
- ...data
140
- } );
137
+ return ( ownerCls: any, fldName: string ) => {
138
+ let metas = _getMetas( ownerCls );
139
+ metas.fields.push( {
140
+ name: fldName,
141
+ ...data
142
+ } );
143
+ }
141
144
  }
142
- }
143
145
 
144
- /**
145
- * following member is a string field
146
- * @example
147
- * \@data_string()
148
- * my_field: string; // this field will be seen as a string
149
- */
146
+ /**
147
+ * following member is a string field
148
+ * @example
149
+ * \@data_string()
150
+ * my_field: string; // this field will be seen as a string
151
+ */
150
152
 
151
153
  export function string( props?: MetaData ) {
152
154
  return field( { ...props, type: 'string' } );
153
- }
155
+ }
154
156
 
155
- /**
156
- * following member is an integer field
157
- * @example
158
- * \@data_string()
159
- * my_field: number; // this field will be seen as an integer
160
- */
157
+ /**
158
+ * following member is an integer field
159
+ * @example
160
+ * \@data_string()
161
+ * my_field: number; // this field will be seen as an integer
162
+ */
161
163
 
162
164
  export function int( props?: MetaData ) {
163
165
  return field( { ...props, type: 'int' } );
164
- }
166
+ }
165
167
 
166
- /**
167
- * following member is a float field
168
- * @example
169
- * \@data_float()
170
- * my_field: number; // this field will be seen as a float
171
- */
168
+ /**
169
+ * following member is a float field
170
+ * @example
171
+ * \@data_float()
172
+ * my_field: number; // this field will be seen as a float
173
+ */
172
174
 
173
175
  export function float( props?: MetaData ) {
174
176
  return field( { ...props, type: 'float' } );
175
- }
177
+ }
176
178
 
177
- /**
178
- * following member is a boolean field
179
- * @example
180
- * \@data_bool()
181
- * my_field: boolean; // this field will be seen as a boolean
182
- */
179
+ /**
180
+ * following member is a boolean field
181
+ * @example
182
+ * \@data_bool()
183
+ * my_field: boolean; // this field will be seen as a boolean
184
+ */
183
185
 
184
186
  export function bool( props?: MetaData ) {
185
187
  return field( { ...props, type: 'bool' } );
186
- }
188
+ }
187
189
 
188
- /**
189
- * following member is a date field
190
- * @example
191
- * \@data_date()
192
- * my_field: date; // this field will be seen as a date
193
- */
190
+ /**
191
+ * following member is a date field
192
+ * @example
193
+ * \@data_date()
194
+ * my_field: date; // this field will be seen as a date
195
+ */
194
196
 
195
197
  export function date( props?: MetaData ) {
196
198
  return field( { ...props, type: 'date' } );
197
- }
199
+ }
198
200
 
199
- /**
200
- * following member is a calculated field
201
- * @example
202
- * \@data_calc( )
203
- * get my_field(): string => {
204
- * return 'hello';
205
- * };
206
- */
201
+ /**
202
+ * following member is a calculated field
203
+ * @example
204
+ * \@data_calc( )
205
+ * get my_field(): string => {
206
+ * return 'hello';
207
+ * };
208
+ */
207
209
 
208
210
  export function calc( props?: MetaData ) {
209
211
  return field( { ...props, type: 'calc'} )
210
- }
211
-
212
-
212
+ }
213
213
 
214
- /**
215
- *
216
- */
214
+ /**
215
+ *
216
+ */
217
217
 
218
- interface RecordConstructor {
219
- new ( data?: any, id?: any ): Record;
220
- }
218
+ interface ModelConstructor {
219
+ new ( data?: any, id?: any ): DataModel;
220
+ }
221
221
 
222
- /**
223
- * following member is a record array
224
- * @example
225
- * \@data_array( )
226
- * my_field(): TypedRecord[];
227
- */
222
+ /**
223
+ * following member is a record array
224
+ * @example
225
+ * \@data_array( )
226
+ * my_field(): TypedRecord[];
227
+ */
228
228
 
229
- export function array( ctor: RecordConstructor, props?: MetaData ) {
229
+ export function array( ctor: ModelConstructor, props?: MetaData ) {
230
230
  return data.field( { ...props, type: 'array', model: ctor ? new ctor() : null } )
231
231
  }
232
232
 
233
+ /**
234
+ * following member is unknown
235
+ * @example
236
+ * \@data.any( )
237
+ * my_field: TypedRecord[];
238
+ */
239
+
240
+ export function any( props?: MetaData ) {
241
+ return field( { ...props, type: 'any' } );
242
+ }
233
243
  }
234
244
 
235
245
 
@@ -239,34 +249,7 @@ interface RecordConstructor {
239
249
  * record model
240
250
  */
241
251
 
242
- export class Record {
243
- [ key: string ]: any;
244
-
245
- constructor( data?: any, id?: any ) {
246
-
247
- if( data!==undefined ) {
248
- this.unSerialize( data, id );
249
- }
250
- }
251
-
252
- clone( source?: any ) {
253
- let rec = new (this.constructor as any)( );
254
- if( source ) {
255
- rec.unSerialize( source );
256
- }
257
- return rec;
258
- }
259
-
260
- /**
261
- * get the record unique identifier
262
- * by default the return value is the first field
263
- * @return unique identifier
264
- */
265
-
266
- getID(): any {
267
- let metas = _getMetas( this, false );
268
- return this[metas.id];
269
- }
252
+ export class DataModel {
270
253
 
271
254
  /**
272
255
  * MUST IMPLEMENT
@@ -277,18 +260,19 @@ export class Record {
277
260
  let metas = _getMetas( this, false );
278
261
  return metas.fields;
279
262
  }
280
-
263
+
281
264
  /**
282
265
  *
283
266
  */
284
267
 
285
- validate( ) : Error[] {
268
+ validate( record: DataRecord ) : Error[] {
286
269
 
287
270
  let errs: Error[] = null;
288
271
 
289
272
  let fields = this.getFields( );
273
+
290
274
  fields.forEach( (fi) => {
291
- if( fi.required && !this.getField(fi.name) ) {
275
+ if( fi.required && !this.getField(fi.name,record) ) {
292
276
  if( errs ) {
293
277
  errs = [];
294
278
  }
@@ -298,15 +282,11 @@ export class Record {
298
282
  })
299
283
 
300
284
  return errs;
301
- }
285
+ }
302
286
 
303
- //mapAnyFields() {
304
- // this.getFields = ( ) => {
305
- // return Object.keys( this ).map( (name) => {
306
- // return <FieldInfo>{ name };
307
- // });
308
- // }
309
- //}
287
+ /**
288
+ * return the field index by name
289
+ */
310
290
 
311
291
  getFieldIndex( name: string ) : number {
312
292
  let fields = this.getFields( );
@@ -318,17 +298,19 @@ export class Record {
318
298
  * @returns an object with known record values
319
299
  */
320
300
 
321
- serialize(): any {
301
+ serialize<T = any>( input: DataRecord ): T {
322
302
  let rec: any = {};
323
303
 
324
304
  this.getFields().forEach((f) => {
325
305
  if( f.calc === undefined ) {
326
- rec[f.name] = rec[f.name];
306
+ rec[f.name] = input[f.name];
327
307
  }
328
308
  });
329
309
 
330
- return rec;
310
+ return rec as T;
331
311
  }
312
+
313
+
332
314
 
333
315
  /**
334
316
  * default unserializer
@@ -336,25 +318,26 @@ export class Record {
336
318
  * @returns a new Record
337
319
  */
338
320
 
339
- unSerialize(data: any, id?: any) : Record {
321
+ unSerialize(data: any, id?: DataRecordID ) : DataRecord {
340
322
 
341
- let fields = this.getFields();
323
+ const fields = this.getFields();
324
+ const rec = new DataRecord( );
342
325
 
343
326
  fields.forEach( (sf) => {
344
327
  let value = data[sf.name];
345
328
  if (value !== undefined) {
346
- this[sf.name] = this._convertField( sf, value );
329
+ rec[sf.name] = this._convertField( sf, value );
347
330
  }
348
331
  });
349
332
 
350
333
  if( id!==undefined ) {
351
- this[fields[0].name] = id;
334
+ rec[fields[0].name] = id;
352
335
  }
353
336
  else {
354
- console.assert( this.getID()!==undefined ); // store do not have ID field
337
+ console.assert( this.getID(rec)!==undefined ); // store do not have ID field
355
338
  }
356
339
 
357
- return this;
340
+ return rec;
358
341
  }
359
342
 
360
343
  /**
@@ -389,6 +372,8 @@ export class Record {
389
372
  }
390
373
 
391
374
  case 'array': {
375
+ debugger;
376
+ /*
392
377
  let result: any[] = [];
393
378
 
394
379
  if( field.model ) {
@@ -398,6 +383,7 @@ export class Record {
398
383
 
399
384
  return result;
400
385
  }
386
+ */
401
387
  break;
402
388
  }
403
389
  }
@@ -405,18 +391,30 @@ export class Record {
405
391
  return input;
406
392
  }
407
393
 
394
+ /**
395
+ * get the record unique identifier
396
+ * by default the return value is the first field
397
+ * @return unique identifier
398
+ */
399
+
400
+ getID( rec: DataRecord ): any {
401
+ if( !rec ) return null;
402
+ let metas = _getMetas( this, false );
403
+ return rec[metas.id];
404
+ }
405
+
408
406
  /**
409
407
  * get raw value of a field
410
408
  * @param name - field name or field index
411
409
  */
412
410
 
413
- getRaw( name: string | number ) : any {
411
+ getRaw( name: string | number, rec: DataRecord ) : any {
414
412
 
415
413
  let idx;
416
414
  let fields = this.getFields( );
417
415
 
418
416
  if( typeof(name) === 'string' ) {
419
- idx = fields.findIndex( fi => fi.name == name );
417
+ idx = fields.findIndex( ( fi: FieldInfo) => fi.name == name );
420
418
  if( idx < 0 ) {
421
419
  console.assert( false, 'unknown field: '+name);
422
420
  return undefined;
@@ -436,20 +434,10 @@ export class Record {
436
434
 
437
435
  let fld = fields[idx];
438
436
  if( fld.calc!==undefined ) {
439
- return fld.calc( this );
437
+ return fld.calc( rec );
440
438
  }
441
439
 
442
- return this[fld.name];
443
- }
444
-
445
- /**
446
- *
447
- * @param name
448
- * @param data
449
- */
450
-
451
- setRaw( name: string, data: string ) {
452
- this[name] = data;
440
+ return rec[fld.name];
453
441
  }
454
442
 
455
443
  /**
@@ -459,18 +447,50 @@ export class Record {
459
447
  * let value = record.get('field1');
460
448
  */
461
449
 
462
- getField( name: string ): string {
463
- let v = this.getRaw( name );
450
+ getField( name: string, rec: DataRecord ): string {
451
+ let v = this.getRaw( name, rec );
464
452
  return (v===undefined || v===null) ? '' : ''+v;
465
453
  }
454
+ }
466
455
 
467
- /**
456
+ /**
457
+ *
458
+ */
459
+
460
+ export class DataRecord {
461
+ [ key: string ]: DataFieldValue;
462
+
463
+ /*
464
+ / **
465
+ * @returns fields descriptors
466
+ * /
467
+
468
+ getFields(): FieldInfo[] {
469
+ let metas = _getMetas( this, false );
470
+ return metas.fields;
471
+ }
472
+
473
+
474
+
475
+ / **
476
+ *
477
+ * @param name
478
+ * @param data
479
+ * /
480
+
481
+ setRaw( name: string, data: string ) {
482
+ this[name] = data;
483
+ }
484
+
485
+
486
+
487
+ / **
468
488
  * set field value
469
489
  * @param name - field name
470
490
  * @param value - value to set
471
491
  * @example
472
492
  * record.set( 'field1', 7 );
473
- */
493
+ * /
474
494
 
475
495
  setField(name: string, value: any) {
476
496
  let fields = this.getFields( );
@@ -489,65 +509,21 @@ export class Record {
489
509
 
490
510
  this.setRaw( fld.name, value );
491
511
  }
492
- }
493
-
494
- /**
495
- * by default, the field id is rhe first member or the record
496
- */
497
-
498
- export class AutoRecord extends Record {
499
-
500
- private m_data;
501
- private m_fid: string;
502
-
503
- constructor( data: any ) {
504
- super( );
505
-
506
- this.m_data = data;
507
- }
508
-
509
- getID( ) {
510
- if( !this.m_fid ) {
511
- let fnames = Object.keys( this.m_data );
512
- this.m_fid = fnames[0];
513
- }
514
-
515
- return this.m_data[this.m_fid];
516
- }
512
+ */
517
513
 
518
- getFields( ) : FieldInfo[] {
519
- let fnames = Object.keys( this.m_data );
520
- let fields: FieldInfo[] = fnames.map( (n) => {
521
- return {
522
- name: n
523
- };
524
- })
525
-
526
- return fields;
527
- }
528
-
529
- getRaw( name: string ) : string {
530
- return this.m_data[name];
531
- }
532
-
533
- setRaw( name: string, data: string ) {
534
- this.m_data[name] = data;
535
- }
536
-
537
- clone( data: any ) {
538
- return new AutoRecord( {...data} );
539
- }
514
+
540
515
  }
541
516
 
517
+
542
518
  /**
543
519
  *
544
520
  */
545
521
 
546
- interface DataEventMap extends ComponentEvents {
522
+ interface DataEventMap extends EventMap {
547
523
  change?: EvChange;
548
524
  }
549
525
 
550
- type DataSolver = ( data: any ) => Record[];
526
+ type DataSolver = ( data: any ) => DataRecord[];
551
527
 
552
528
  export interface DataProxyProps {
553
529
  url: string;
@@ -596,9 +572,9 @@ export class DataProxy extends CoreElement<DataEventMap> {
596
572
  *
597
573
  */
598
574
 
599
- interface DataStoreProps<T extends Record> {
600
- model: T;
601
- data?: T[];
575
+ interface DataStoreProps {
576
+ model: DataModel;
577
+ data?: any[];
602
578
  url?: string;
603
579
  autoload?: false;
604
580
  solver?: DataSolver;
@@ -615,16 +591,16 @@ interface DataStoreEventMap extends EventMap {
615
591
  *
616
592
  */
617
593
 
618
- export class DataStore<T extends Record = Record> extends EventSource<DataStoreEventMap> {
594
+ export class DataStore extends EventSource<DataStoreEventMap> {
619
595
 
620
- protected m_model: T;
596
+ protected m_model: DataModel;
621
597
  protected m_fields: FieldInfo[];
622
- protected m_records: T[];
598
+ protected m_records: DataRecord[];
623
599
 
624
600
  protected m_proxy: DataProxy;
625
601
  protected m_rec_index: DataIndex;
626
602
 
627
- constructor(props: DataStoreProps<T> ) {
603
+ constructor(props: DataStoreProps ) {
628
604
  super( );
629
605
 
630
606
  this.m_fields = undefined;
@@ -672,10 +648,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
672
648
 
673
649
  public setData( records: any[] ) {
674
650
 
675
- let realRecords: T[] = [];
651
+ const realRecords: DataRecord[] = new Array( records.length );
676
652
 
677
- records.forEach( (rec) => {
678
- realRecords.push( this.m_model.clone(rec) );
653
+ records.forEach( (rec,idx) => {
654
+ realRecords[idx] = this.m_model.unSerialize(rec);
679
655
  });
680
656
 
681
657
  this.setRawData( realRecords );
@@ -686,14 +662,13 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
686
662
  * @param records - must be of the same type as model
687
663
  */
688
664
 
689
- public setRawData(records: T[]) {
665
+ public setRawData(records: DataRecord[]) {
690
666
 
691
667
  this.m_records = records;
692
668
  this._rebuildIndex( );
693
669
  this.fire( 'data_change', { change_type: 'change'} );
694
670
  }
695
671
 
696
-
697
672
  private _rebuildIndex( ) {
698
673
  this.m_rec_index = null; // null to signal that we have to run on records instead of index
699
674
  this.m_rec_index = this.createIndex( null ); // prepare index (remove deleted)
@@ -704,8 +679,9 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
704
679
  *
705
680
  */
706
681
 
707
- public update( rec: T ) {
708
- let id = rec.getID();
682
+ public update( rec: DataRecord ) {
683
+
684
+ let id = this.m_model.getID( rec );
709
685
  let index = this.indexOfId(id);
710
686
  if (index < 0) {
711
687
  return false;
@@ -721,18 +697,18 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
721
697
  * @param data
722
698
  */
723
699
 
724
- public append( rec: T | any ) {
700
+ public append( rec: DataRecord | any ) {
725
701
 
726
- if( !(rec instanceof Record) ) {
727
- let nrec = this.m_model.clone( );
728
- rec = nrec.unSerialize( rec );
702
+ if( !(rec instanceof DataRecord) ) {
703
+ rec = this.m_model.unSerialize( rec );
729
704
  }
730
705
 
731
- console.assert( rec.getID() );
706
+ const id = this.m_model.getID(rec);
707
+ console.assert( id!==undefined );
732
708
 
733
709
  this.m_records.push( rec );
734
710
  this._rebuildIndex( );
735
- this.fire( 'data_change', {change_type: 'create', id: rec.getID() } );
711
+ this.fire( 'data_change', {change_type: 'create', id } );
736
712
  }
737
713
 
738
714
  /**
@@ -741,8 +717,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
741
717
 
742
718
  getMaxId( ) {
743
719
  let maxID: number = undefined;
720
+ const m = this.m_model;
721
+
744
722
  this.m_records.forEach( (r) => {
745
- let rid = r.getID( );
723
+ let rid = m.getID( r );
746
724
  if( maxID===undefined || maxID<rid ) {
747
725
  maxID = rid;
748
726
  }
@@ -756,7 +734,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
756
734
  * @param id
757
735
  */
758
736
 
759
- public delete(id: any): boolean {
737
+ public delete(id: DataRecordID ): boolean {
760
738
 
761
739
  let idx = this.indexOfId( id );
762
740
  if( idx<0 ) {
@@ -792,17 +770,19 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
792
770
  * find the index of the element with the given id
793
771
  */
794
772
 
795
- public indexOfId(id: any ): number {
773
+ public indexOfId(id: DataRecordID ): number {
796
774
 
797
775
  //if( this.count<10 ) {
798
776
  // this.forEach( (rec) => rec.getID() == id );
799
777
  //}
800
778
 
779
+ const m = this.m_model;
780
+
801
781
  for( let lim = this.count, base = 0; lim != 0; lim >>= 1 ) {
802
782
 
803
- let p = base + (lim >> 1); // int conversion
804
- let idx = this.m_rec_index[p];
805
- let rid = this.m_records[idx].getID( );
783
+ const p = base + (lim >> 1); // int conversion
784
+ const idx = this.m_rec_index[p];
785
+ const rid = m.getID( this.m_records[idx] );
806
786
 
807
787
  if( rid==id ) {
808
788
  return p;
@@ -822,7 +802,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
822
802
  * @returns record or null
823
803
  */
824
804
 
825
- public getById(id: any): T {
805
+ public getById(id: DataRecordID): DataRecord {
826
806
  let idx = this.indexOfId( id );
827
807
  if( idx<0 ) {
828
808
  return null;
@@ -837,16 +817,16 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
837
817
  * @returns record or null
838
818
  */
839
819
 
840
- public getByIndex( index: number ): T {
820
+ public getByIndex( index: number ): DataRecord {
841
821
  let idx = this.m_rec_index[index];
842
822
  return this._getRecord( idx );
843
823
  }
844
824
 
845
- private _getRecord( index: number ) : T {
825
+ private _getRecord( index: number ) : DataRecord {
846
826
  return this.m_records[index] ?? null;
847
827
  }
848
828
 
849
- public moveTo( other: DataStore<T> ) {
829
+ public moveTo( other: DataStore ) {
850
830
  other.setRawData( this.m_records );
851
831
  }
852
832
 
@@ -855,7 +835,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
855
835
  * @param opts
856
836
  */
857
837
 
858
- createView( opts?: DataViewProps<T> ) : DataView<T> {
838
+ createView( opts?: DataViewProps ) : DataView {
859
839
  let eopts = { ...opts, store: this };
860
840
  return new DataView( eopts );
861
841
  }
@@ -882,11 +862,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
882
862
  else {
883
863
  if( typeof(filter.op)==='function' ) {
884
864
 
885
- let fn = <FilterFunc>filter.op;
865
+ let fn = filter.op as FilterFunc;
886
866
 
887
867
  // scan all records and append only interesting ones
888
868
  this.forEach( (rec, idx) => {
889
-
890
869
  // skip deleted
891
870
  if( !rec ) {
892
871
  return;
@@ -957,6 +936,8 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
957
936
  }
958
937
 
959
938
  // scan all records and append only interesting ones
939
+ const m = this.m_model;
940
+
960
941
  this.forEach( (rec, idx) => {
961
942
 
962
943
  // skip deleted
@@ -964,7 +945,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
964
945
  return;
965
946
  }
966
947
 
967
- let field = rec.getRaw( filterFld );
948
+ let field = m.getRaw( filterFld, rec );
968
949
  if( field===null || field===undefined ) {
969
950
  field = '';
970
951
  }
@@ -1019,13 +1000,16 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
1019
1000
  }
1020
1001
 
1021
1002
  // sort only by one field : optimize it
1003
+ const m = this.m_model;
1004
+
1022
1005
  if( fidxs.length==1 ) {
1023
1006
 
1024
- let field = fidxs[0].fidx;
1007
+ const field = fidxs[0].fidx;
1008
+
1025
1009
  index.sort( ( ia, ib ) => {
1026
1010
 
1027
- let va = this.getByIndex(ia).getRaw( field ) ?? '';
1028
- let vb = this.getByIndex(ib).getRaw( field ) ?? '';
1011
+ let va = m.getRaw( field, this.getByIndex(ia) ) ?? '';
1012
+ let vb = m.getRaw( field, this.getByIndex(ib) ) ?? '';
1029
1013
  if (va > vb) { return 1; }
1030
1014
  if (va < vb) { return -1; }
1031
1015
  return 0;
@@ -1044,8 +1028,8 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
1044
1028
  let fidx = fidxs[fi].fidx;
1045
1029
  let mul = fidxs[fi].asc ? 1 : -1;
1046
1030
 
1047
- let va = this.getByIndex(ia).getRaw( fidx ) ?? '';
1048
- let vb = this.getByIndex(ib).getRaw( fidx ) ?? '';
1031
+ let va = m.getRaw( fidx, this.getByIndex(ia) ) ?? '';
1032
+ let vb = m.getRaw( fidx, this.getByIndex(ib) ) ?? '';
1049
1033
  if (va > vb) { return mul; }
1050
1034
  if (va < vb) { return -mul; }
1051
1035
  }
@@ -1056,12 +1040,12 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
1056
1040
 
1057
1041
  return index
1058
1042
  }
1059
-
1043
+
1060
1044
  /**
1061
1045
  *
1062
1046
  */
1063
1047
 
1064
- forEach( cb: ( rec:T, index: number ) => any ) {
1048
+ forEach( cb: ( rec: DataRecord, index: number ) => any ) {
1065
1049
 
1066
1050
  if( this.m_rec_index ) {
1067
1051
  this.m_rec_index.some( (ri,index) => {
@@ -1088,6 +1072,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
1088
1072
  changed( ) {
1089
1073
  this.fire( 'data_change', { change_type: 'change'} );
1090
1074
  }
1075
+
1076
+ getModel( ) {
1077
+ return this.m_model;
1078
+ }
1091
1079
  }
1092
1080
 
1093
1081
 
@@ -1101,13 +1089,13 @@ interface DataViewEventMap extends EventMap {
1101
1089
  view_change: EvViewChange;
1102
1090
  }
1103
1091
 
1104
- interface DataViewProps<T extends Record> {
1105
- store?: DataStore<T>;
1092
+ interface DataViewProps {
1093
+ store?: DataStore;
1106
1094
  filter?: FilterInfo;
1107
1095
  order?: string | SortProp[] | SortProp;
1108
1096
  }
1109
1097
 
1110
- export type FilterFunc = ( rec: Record ) => boolean;
1098
+ export type FilterFunc = ( rec: DataRecord ) => boolean;
1111
1099
 
1112
1100
  export interface FilterInfo {
1113
1101
  op: '<' | '<=' | '=' | '>=' | '>' | '<>' | 'empty-result' | FilterFunc, // emptydb mean return an empty result always
@@ -1120,6 +1108,7 @@ export interface FilterInfo {
1120
1108
  export interface SortProp {
1121
1109
  field: string; //
1122
1110
  ascending: boolean; //
1111
+ numeric?: boolean; // numeric sort
1123
1112
  }
1124
1113
 
1125
1114
 
@@ -1130,17 +1119,18 @@ export interface SortProp {
1130
1119
  * You can have multiple views for a single DataStore
1131
1120
  */
1132
1121
 
1133
- export class DataView<T extends Record = Record> extends CoreElement<DataViewEventMap>
1122
+ export class DataView extends CoreElement<DataViewEventMap>
1134
1123
  {
1135
1124
  protected m_index: DataIndex;
1136
- protected m_store: DataStore<T>;
1125
+ protected m_store: DataStore;
1126
+ protected m_model: DataModel;
1137
1127
 
1138
1128
  protected m_sort: SortProp[];
1139
1129
  protected m_filter: FilterInfo;
1140
1130
 
1141
- protected m_props: DataViewProps<T>;
1131
+ protected m_props: DataViewProps;
1142
1132
 
1143
- constructor( props: DataViewProps<T> ) {
1133
+ constructor( props: DataViewProps ) {
1144
1134
  super( );
1145
1135
 
1146
1136
  this.m_props = props;
@@ -1148,6 +1138,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
1148
1138
  this.m_index = null;
1149
1139
  this.m_filter = null;
1150
1140
  this.m_sort = null;
1141
+ this.m_model = this.m_store.getModel();
1151
1142
 
1152
1143
  this.filter( props.filter );
1153
1144
 
@@ -1245,7 +1236,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
1245
1236
  * @param id
1246
1237
  */
1247
1238
 
1248
- public indexOfId(id: any): number {
1239
+ public indexOfId(id: DataRecordID): number {
1249
1240
  let ridx = this.m_store.indexOfId( id );
1250
1241
  return this.m_index.findIndex( (rid) => rid === ridx );
1251
1242
  }
@@ -1255,7 +1246,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
1255
1246
  * @param index
1256
1247
  */
1257
1248
 
1258
- public getByIndex(index: number): T {
1249
+ public getByIndex(index: number): DataRecord {
1259
1250
 
1260
1251
  if (index >= 0 && index < this.m_index.length) {
1261
1252
  let rid = this.m_index[index];
@@ -1265,15 +1256,36 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
1265
1256
  return null;
1266
1257
  }
1267
1258
 
1259
+ public getIdByIndex( index: number ) : DataRecordID {
1260
+ const rec = this.getByIndex( index );
1261
+ return this.m_model.getID( rec );
1262
+ }
1263
+
1264
+ public getRecId( rec: DataRecord ): DataRecordID {
1265
+ return this.m_model.getID( rec );
1266
+ }
1267
+
1268
1268
  /**
1269
1269
  *
1270
1270
  * @param id
1271
1271
  */
1272
1272
 
1273
- public getById( id: any): T {
1273
+ public getById( id: DataRecordID): DataRecord {
1274
1274
  return this.m_store.getById( id );
1275
1275
  }
1276
1276
 
1277
+ /**
1278
+ *
1279
+ */
1280
+
1281
+ getModel( ) {
1282
+ return this.m_model;
1283
+ }
1284
+
1285
+ /**
1286
+ *
1287
+ */
1288
+
1277
1289
  changed( ) {
1278
1290
  this.fire( 'view_change', {change_type:'change'} );
1279
1291
  }
@@ -1282,7 +1294,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
1282
1294
  *
1283
1295
  */
1284
1296
 
1285
- forEach( cb: ( rec:T, index: number ) => any ) {
1297
+ forEach( cb: ( rec: DataRecord, index: number ) => any ) {
1286
1298
  this.m_index.some( ( index ) => {
1287
1299
  let rec = this.m_store.getByIndex( index );
1288
1300
  if( rec ) {