neo.mjs 5.12.3 → 5.12.5

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.
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.12.3'
23
+ * @member {String} version='5.12.5'
24
24
  */
25
- version: '5.12.3'
25
+ version: '5.12.5'
26
26
  }
27
27
 
28
28
  /**
@@ -69,17 +69,14 @@ class ConfigurationViewport extends Viewport {
69
69
  items : [me.exampleComponent],
70
70
  flex : me.exampleComponentFlex,
71
71
  layout: 'base',
72
- style : {padding: '20px'}
72
+ style : {overflow: 'auto', padding: '20px'},
73
+ ...me.exampleContainerConfig
73
74
  }, {
74
75
  module: Panel,
75
76
  cls : ['neo-panel', 'neo-container', 'neo-configuration-panel'],
76
77
  flex : me.configPanelFlex,
77
78
  style : {margin: '20px', minWidth: me.configPanelMinWidth},
78
79
 
79
- containerConfig: {
80
- style: {overflowY: 'scroll'}
81
- },
82
-
83
80
  headers: [{
84
81
  dock : 'top',
85
82
  style: {borderLeft:0, borderRight:0, borderTop:0},
@@ -100,7 +97,7 @@ class ConfigurationViewport extends Viewport {
100
97
  items: [{
101
98
  module: Container,
102
99
  layout: {ntype: 'vbox'},
103
- style : {padding: '10px'},
100
+ style : {overflowY: 'auto', padding: '10px'},
104
101
  cls : ['neo-configuration-panel-body'],
105
102
  itemDefaults: {
106
103
  clearToOriginalValue: true,
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.12.3'
23
+ * @member {String} version='5.12.5'
24
24
  */
25
- version: '5.12.3'
25
+ version: '5.12.5'
26
26
  }
27
27
 
28
28
  /**
@@ -177,9 +177,11 @@ class MainContainer extends ConfigurationViewport {
177
177
  return Neo.create({
178
178
  module : Button,
179
179
  badgeText: 'Badge',
180
+ flex : 'none',
180
181
  handler : data => console.log('button click =>', data.component.id),
181
182
  height : 50,
182
183
  iconCls : 'fa fa-home',
184
+ style : {marginBottom: '1500px', marginTop: '500px'},
183
185
  text : 'Hello World',
184
186
  ui : 'primary',
185
187
  width : 150,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "5.12.3",
3
+ "version": "5.12.5",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -236,12 +236,12 @@ const DefaultConfig = {
236
236
  useVdomWorker: true,
237
237
  /**
238
238
  * buildScripts/injectPackageVersion.mjs will update this value
239
- * @default '5.12.3'
239
+ * @default '5.12.5'
240
240
  * @memberOf! module:Neo
241
241
  * @name config.version
242
242
  * @type String
243
243
  */
244
- version: '5.12.3'
244
+ version: '5.12.5'
245
245
  };
246
246
 
247
247
  Object.assign(DefaultConfig, {
@@ -139,6 +139,20 @@ class Base extends Component {
139
139
  */
140
140
  #rippleTimeoutId = null
141
141
 
142
+ /**
143
+ * @param {Object} config
144
+ */
145
+ construct(config) {
146
+ super.construct(config);
147
+
148
+ let me = this;
149
+
150
+ me.addDomListeners({
151
+ click: me.onClick,
152
+ scope: me
153
+ })
154
+ }
155
+
142
156
  /**
143
157
  * Triggered after the badgePosition config got changed
144
158
  * @param {String} value
@@ -173,26 +187,6 @@ class Base extends Component {
173
187
  this.update();
174
188
  }
175
189
 
176
- /**
177
- * Triggered after the handler config got changed
178
- * @param {String} value
179
- * @param {String} oldValue
180
- * @protected
181
- */
182
- afterSetHandler(value, oldValue) {
183
- let me = this;
184
-
185
- value && me.addDomListeners({
186
- click: value,
187
- scope: me.handlerScope || me
188
- });
189
-
190
- me.menu && me.addDomListeners({
191
- click: me.toggleMenu,
192
- scope: me
193
- })
194
- }
195
-
196
190
  /**
197
191
  * Triggered after the iconCls config got changed
198
192
  * @param {String} value
@@ -257,45 +251,15 @@ class Base extends Component {
257
251
  let me = this;
258
252
 
259
253
  me.menuList = Neo.create({
260
- module : module.default,
261
- appName : me.appName,
262
- displayField: 'text',
263
- floating : true,
264
- hidden : true,
265
- items : value,
266
- parentId : me.id
267
- });
268
-
269
- me.vdom.cn.push(me.menuList.vdom)
270
- })
271
- }
272
- }
273
-
274
- /**
275
- * Triggered after the mounted config got changed
276
- * @param {Boolean} value
277
- * @param {Boolean} oldValue
278
- * @protected
279
- */
280
- afterSetMounted(value, oldValue) {
281
- super.afterSetMounted(value, oldValue);
282
-
283
- let me = this,
284
- style;
285
-
286
- if (value && me.menu) {
287
- setTimeout(() => {
288
- me.getDomRect().then(rect => {
289
- style = me.menuList.style || {};
290
-
291
- Object.assign(style, {
292
- right: 0,
293
- top : rect.height + 'px'
294
- });
295
-
296
- me.menuList.style = style
254
+ module : module.default,
255
+ appName : me.appName,
256
+ displayField : 'text',
257
+ floating : true,
258
+ hidden : true,
259
+ items : value,
260
+ parentComponent: me
297
261
  })
298
- }, 50)
262
+ })
299
263
  }
300
264
  }
301
265
 
@@ -312,21 +276,6 @@ class Base extends Component {
312
276
  this.cls = cls;
313
277
  }
314
278
 
315
- /**
316
- * Triggered after the route config got changed
317
- * @param {String} value
318
- * @param {String} oldValue
319
- * @protected
320
- */
321
- afterSetRoute(value, oldValue) {
322
- let me = this;
323
-
324
- value && me.addDomListeners({
325
- click: me.changeRoute,
326
- scope: me
327
- })
328
- }
329
-
330
279
  /**
331
280
  * Triggered after the text config got changed
332
281
  * @param {String|null} value
@@ -349,7 +298,7 @@ class Base extends Component {
349
298
  textNode.innerHTML = value;
350
299
  }
351
300
 
352
- me.update();
301
+ me.update()
353
302
  }
354
303
 
355
304
  /**
@@ -369,7 +318,7 @@ class Base extends Component {
369
318
  vdomRoot.tag = 'button';
370
319
  }
371
320
 
372
- this.update();
321
+ this.update()
373
322
  }
374
323
 
375
324
  /**
@@ -379,19 +328,9 @@ class Base extends Component {
379
328
  * @protected
380
329
  */
381
330
  afterSetUseRippleEffect(value, oldValue) {
382
- let me = this,
383
- listener = {click: me.showRipple, scope: me},
384
- rippleWrapper = me.getRippleWrapper();
385
-
386
- if (!value && oldValue) {
387
- me.removeDomListeners(listener);
388
- } else if (value) {
389
- me.addDomListeners(listener);
390
- }
391
-
392
- // setting the config to false should end running ripple animations
393
- rippleWrapper.removeDom = true;
394
- me.update();
331
+ // setting the config to false ends running ripple animations
332
+ this.getRippleWrapper().removeDom = true;
333
+ this.update()
395
334
  }
396
335
 
397
336
  /**
@@ -410,7 +349,7 @@ class Base extends Component {
410
349
  delete vdomRoot.target;
411
350
  }
412
351
 
413
- me.update();
352
+ me.update()
414
353
  }
415
354
 
416
355
  /**
@@ -425,7 +364,7 @@ class Base extends Component {
425
364
  return iconCls.join(' ');
426
365
  }
427
366
 
428
- return iconCls;
367
+ return iconCls
429
368
  }
430
369
 
431
370
  /**
@@ -436,7 +375,7 @@ class Base extends Component {
436
375
  * @protected
437
376
  */
438
377
  beforeSetBadgePosition(value, oldValue) {
439
- return this.beforeSetEnumValue(value, oldValue, 'badgePosition');
378
+ return this.beforeSetEnumValue(value, oldValue, 'badgePosition')
440
379
  }
441
380
 
442
381
  /**
@@ -451,7 +390,7 @@ class Base extends Component {
451
390
  value = value.split(' ').filter(Boolean);
452
391
  }
453
392
 
454
- return value;
393
+ return value
455
394
  }
456
395
 
457
396
  /**
@@ -471,9 +410,9 @@ class Base extends Component {
471
410
  let me = this;
472
411
 
473
412
  if (me.editRoute) {
474
- Neo.Main.editRoute(me.route);
413
+ Neo.Main.editRoute(me.route)
475
414
  } else {
476
- Neo.Main.setRoute({value: me.route});
415
+ Neo.Main.setRoute({value: me.route})
477
416
  }
478
417
  }
479
418
 
@@ -482,7 +421,7 @@ class Base extends Component {
482
421
  * @returns {Object}
483
422
  */
484
423
  getBadgeNode() {
485
- return this.getVdomRoot().cn[2];
424
+ return this.getVdomRoot().cn[2]
486
425
  }
487
426
 
488
427
  /**
@@ -490,7 +429,7 @@ class Base extends Component {
490
429
  * @returns {Object}
491
430
  */
492
431
  getIconNode() {
493
- return this.getVdomRoot().cn[0];
432
+ return this.getVdomRoot().cn[0]
494
433
  }
495
434
 
496
435
  /**
@@ -498,7 +437,20 @@ class Base extends Component {
498
437
  * @returns {Object}
499
438
  */
500
439
  getRippleWrapper() {
501
- return this.getVdomRoot().cn[3];
440
+ return this.getVdomRoot().cn[3]
441
+ }
442
+
443
+ /**
444
+ * @param {Object} data
445
+ */
446
+ onClick(data) {
447
+ let me = this;
448
+
449
+ me.handler?.call(me.handlerScope || me, data);
450
+
451
+ me.menu && me.toggleMenu();
452
+ me.route && me.changeRoute();
453
+ me.useRippleEffect && me.showRipple(data)
502
454
  }
503
455
 
504
456
  /**
@@ -536,7 +488,7 @@ class Base extends Component {
536
488
  me.#rippleTimeoutId = null;
537
489
 
538
490
  rippleWrapper.removeDom = true;
539
- me.update();
491
+ me.update()
540
492
  }
541
493
  }, rippleEffectDuration);
542
494
  }
package/src/core/Base.mjs CHANGED
@@ -24,7 +24,9 @@ class Base {
24
24
  static observable = false
25
25
  /**
26
26
  * Keep the overwritten methods
27
- * @type {Object}
27
+ * @member {Object} overwrittenMethods={}
28
+ * @protected
29
+ * @static
28
30
  */
29
31
  static overwrittenMethods = {}
30
32
  /**
@@ -116,7 +118,7 @@ class Base {
116
118
  value : true
117
119
  });
118
120
 
119
- me.remote && setTimeout(me.initRemote.bind(me), 1);
121
+ me.remote && setTimeout(me.initRemote.bind(me), 1)
120
122
  }
121
123
 
122
124
  /**
@@ -133,9 +135,9 @@ class Base {
133
135
 
134
136
  if (oldValue) {
135
137
  if (hasManager) {
136
- Neo.manager.Instance.unregister(oldValue);
138
+ Neo.manager.Instance.unregister(oldValue)
137
139
  } else {
138
- delete Neo.idMap[oldValue];
140
+ delete Neo.idMap[oldValue]
139
141
  }
140
142
  }
141
143
 
@@ -143,7 +145,7 @@ class Base {
143
145
  Neo.manager.Instance.register(me);
144
146
  } else {
145
147
  Neo.idMap = Neo.idMap || {};
146
- Neo.idMap[me.id] = me;
148
+ Neo.idMap[me.id] = me
147
149
  }
148
150
  }
149
151
 
@@ -169,8 +171,9 @@ class Base {
169
171
  }
170
172
  }
171
173
  }
174
+
172
175
  // Apply configs to prototype
173
- overwrites && Object.assign(cfg, overwrites);
176
+ overwrites && Object.assign(cfg, overwrites)
174
177
  }
175
178
  }
176
179
 
@@ -187,10 +190,10 @@ class Base {
187
190
 
188
191
  if (!values.includes(value)) {
189
192
  console.error(`Supported values for ${name} are: ${values.join(', ')}`, this);
190
- return oldValue;
193
+ return oldValue
191
194
  }
192
195
 
193
- return value;
196
+ return value
194
197
  }
195
198
 
196
199
  /**
@@ -217,7 +220,7 @@ class Base {
217
220
  regex = Base.methodNameRegex,
218
221
  methodName = stack.match(regex)[1];
219
222
 
220
- this.__proto__.constructor.overwrittenMethods[methodName].call(this, ...args);
223
+ this.__proto__.constructor.overwrittenMethods[methodName].call(this, ...args)
221
224
  }
222
225
 
223
226
  /**
@@ -238,14 +241,14 @@ class Base {
238
241
  let me = this;
239
242
 
240
243
  if (Base.instanceManagerAvailable === true) {
241
- Neo.manager.Instance.unregister(me);
244
+ Neo.manager.Instance.unregister(me)
242
245
  } else if (Neo.idMap) {
243
- delete Neo.idMap[me.id];
246
+ delete Neo.idMap[me.id]
244
247
  }
245
248
 
246
249
  Object.keys(me).forEach(key => {
247
250
  if (Object.getOwnPropertyDescriptor(me, key).writable) {
248
- delete me[key];
251
+ delete me[key]
249
252
  }
250
253
  })
251
254
  }
@@ -299,7 +302,7 @@ class Base {
299
302
  listenerId;
300
303
 
301
304
  if (!me.singleton) {
302
- throw new Error('Remote method access is only functional for Singleton classes ' + className);
305
+ throw new Error('Remote method access is only functional for Singleton classes ' + className)
303
306
  }
304
307
 
305
308
  if (!Neo.config.unitTestMode && Neo.isObject(remote)) {
@@ -325,11 +328,11 @@ class Base {
325
328
  ctor = me.constructor;
326
329
 
327
330
  if (!ctor.config) {
328
- throw new Error('Neo.applyClassConfig has not been run on ' + me.className);
331
+ throw new Error('Neo.applyClassConfig has not been run on ' + me.className)
329
332
  }
330
333
 
331
334
  if (!preventOriginalConfig) {
332
- me.originalConfig = Neo.clone(config, true, true);
335
+ me.originalConfig = Neo.clone(config, true, true)
333
336
  }
334
337
 
335
338
  return {...ctor.config, ...config}
@@ -364,7 +367,7 @@ class Base {
364
367
 
365
368
  if (items) {
366
369
  if (!Array.isArray(items)) {
367
- items = [items];
370
+ items = [items]
368
371
  }
369
372
 
370
373
  items.forEach(item => {
@@ -377,16 +380,16 @@ class Base {
377
380
  ns = Neo.ns(nsArray, false, me);
378
381
 
379
382
  if (ns[nsKey] === undefined) {
380
- console.error('The used @config does not exist:', nsKey, nsArray.join('.'));
383
+ console.error('The used @config does not exist:', nsKey, nsArray.join('.'))
381
384
  } else {
382
385
  symbolNs = Neo.ns(nsArray, false, me[configSymbol]);
383
386
 
384
387
  // The config might not be processed yet, especially for configs
385
388
  // not ending with an underscore, so we need to check the configSymbol first.
386
389
  if (symbolNs && Object.hasOwn(symbolNs, nsKey)) {
387
- item[key] = symbolNs[nsKey];
390
+ item[key] = symbolNs[nsKey]
388
391
  } else {
389
- item[key] = ns[nsKey];
392
+ item[key] = ns[nsKey]
390
393
  }
391
394
  }
392
395
  }
@@ -414,7 +417,7 @@ class Base {
414
417
  me[keys[0]] = me[configSymbol][keys[0]];
415
418
  }
416
419
 
417
- // there is a delete call inside the config getter as well (Neo.mjs => autoGenerateGetSet())
420
+ // there is a delete-call inside the config getter as well (Neo.mjs => autoGenerateGetSet())
418
421
  // we need to keep this one for configs, which do not use getters (no trailing underscore)
419
422
  delete me[configSymbol][keys[0]];
420
423
 
@@ -439,7 +442,7 @@ class Base {
439
442
  methods
440
443
  })
441
444
  }
442
- });
445
+ })
443
446
  }
444
447
 
445
448
  /**
@@ -455,7 +458,7 @@ class Base {
455
458
  // finish this one first before dropping new values into the configSymbol.
456
459
  // see: https://github.com/neomjs/neo/issues/2201
457
460
  if (me[forceAssignConfigs] !== true && Object.keys(me[configSymbol]).length > 0) {
458
- me.processConfigs();
461
+ me.processConfigs()
459
462
  }
460
463
 
461
464
  Object.assign(me[configSymbol], values);
@@ -476,11 +479,11 @@ class Base {
476
479
  Object.entries(config).forEach(([key, value]) => {
477
480
  if (!configNames.hasOwnProperty(key) && !Neo.hasPropertySetter(me, key)) {
478
481
  me[key] = value;
479
- delete config[key];
482
+ delete config[key]
480
483
  }
481
484
  })
482
485
 
483
- return config;
486
+ return config
484
487
  }
485
488
 
486
489
  /**
package/src/menu/List.mjs CHANGED
@@ -104,6 +104,17 @@ class List extends BaseList {
104
104
  {tag: 'ul', tabIndex: -1, cn: []}
105
105
  }
106
106
 
107
+ /**
108
+ * If the menu is floating, it will anchor itself to the parentRect
109
+ * @member {Neo.component.Base|null} parentComponent=null
110
+ */
111
+ parentComponent = null
112
+ /**
113
+ * If the menu is floating, it will anchor itself to the parentRect
114
+ * @member {Object|null} parentRect=null
115
+ */
116
+ parentRect = null
117
+
107
118
  /**
108
119
  * Triggered after the floating config got changed
109
120
  * @param {Object[]} value
@@ -157,6 +168,35 @@ class List extends BaseList {
157
168
  }
158
169
  }
159
170
 
171
+ /**
172
+ * Triggered after the mounted config got changed
173
+ * @param {Boolean} value
174
+ * @param {Boolean} oldValue
175
+ * @protected
176
+ */
177
+ afterSetMounted(value, oldValue) {
178
+ super.afterSetMounted(value, oldValue);
179
+
180
+ let me = this,
181
+ parentId = me.parentComponent?.id;
182
+
183
+ if (value && parentId) {
184
+ Neo.main.addon.ScrollSync.register({
185
+ sourceId: parentId,
186
+ targetId: me.id
187
+ });
188
+
189
+ me.getDomRect([me.id, parentId]).then(rects => {
190
+ let style = me.style || {};
191
+
192
+ style.left = `${rects[1].right - rects[0].width}px`;
193
+ style.top = `${rects[1].bottom + 1}px`;
194
+
195
+ me.style = style
196
+ })
197
+ }
198
+ }
199
+
160
200
  /**
161
201
  * Triggered after the zIndex config got changed
162
202
  * @param {Number} value
@@ -28,7 +28,7 @@ class ListModel extends BaseListModel {
28
28
  if (parentMenu) {
29
29
  view.hideSubMenu();
30
30
  view.selectionModel.deselectAll();
31
- parentMenu.selectionModel.selectAt(view.parentIndex);
31
+ parentMenu.selectionModel.selectAt(view.parentIndex)
32
32
  }
33
33
  }
34
34
 
@@ -39,7 +39,7 @@ class ListModel extends BaseListModel {
39
39
  let activeSubMenu = this.view.activeSubMenu;
40
40
 
41
41
  if (activeSubMenu) {
42
- activeSubMenu.selectionModel.selectAt(0);
42
+ activeSubMenu.selectionModel.selectAt(0)
43
43
  }
44
44
  }
45
45
  }
@@ -45,6 +45,87 @@ class View extends Component {
45
45
  {tag: 'tbody', cn: []}
46
46
  }
47
47
 
48
+ /**
49
+ * @param {String} cellId
50
+ * @param {Object} column
51
+ * @param {Object} record
52
+ * @param {Number} index
53
+ * @param {Neo.table.Container} tableContainer
54
+ * @returns {Object}
55
+ */
56
+ applyRendererOutput(cellId, column, record, index, tableContainer) {
57
+ let me = this,
58
+ cellCls = ['neo-table-cell'],
59
+ dataField = column.dataField,
60
+ fieldValue = record[dataField],
61
+ hasStore = tableContainer.store?.model, // todo: remove as soon as all tables use stores (examples table)
62
+ vdom = me.vdom,
63
+ cellConfig, rendererOutput;
64
+
65
+ if (fieldValue === undefined) {
66
+ fieldValue = ''
67
+ }
68
+
69
+ rendererOutput = column.renderer.call(column.rendererScope || tableContainer, {
70
+ dataField,
71
+ index,
72
+ record,
73
+ value: fieldValue
74
+ });
75
+
76
+ switch (Neo.typeOf(rendererOutput)) {
77
+ case 'Object': {
78
+ if (rendererOutput.cls && rendererOutput.html) {
79
+ cellCls.push(...rendererOutput.cls);
80
+ } else {
81
+ rendererOutput = [rendererOutput];
82
+ }
83
+ break;
84
+ }
85
+ case 'Number':
86
+ case 'String': {
87
+ rendererOutput = {
88
+ cls : cellCls,
89
+ html: rendererOutput?.toString()
90
+ };
91
+ break;
92
+ }
93
+ }
94
+
95
+ if (rendererOutput === null || rendererOutput === undefined) {
96
+ rendererOutput = ''
97
+ }
98
+
99
+ if (column.align !== 'left') {
100
+ cellCls.push('neo-' + column.align)
101
+ }
102
+
103
+ if (!cellId) {
104
+ // todo: remove the else part as soon as all tables use stores (examples table)
105
+ if (hasStore) {
106
+ cellId = me.getCellId(record, column.dataField)
107
+ } else {
108
+ cellId = vdom.cn[i]?.cn[j]?.id || Neo.getId('td')
109
+ }
110
+ }
111
+
112
+ cellConfig = {
113
+ tag : 'td',
114
+ id : cellId,
115
+ cls : cellCls,
116
+ style : rendererOutput.style || {},
117
+ tabIndex: '-1'
118
+ };
119
+
120
+ if (Neo.typeOf(rendererOutput) === 'Object') {
121
+ cellConfig.innerHTML = rendererOutput.html || ''
122
+ } else {
123
+ cellConfig.cn = rendererOutput
124
+ }
125
+
126
+ return cellConfig
127
+ }
128
+
48
129
  /**
49
130
  * @param {Array} inputData
50
131
  */
@@ -52,14 +133,13 @@ class View extends Component {
52
133
  let me = this,
53
134
  amountRows = inputData.length,
54
135
  container = Neo.getComponent(me.parentId),
55
- hasStore = container.store?.model, // todo: remove as soon as all tables use stores (examples table)
56
136
  columns = container.items[0].items,
57
137
  colCount = columns.length,
58
138
  data = [],
59
139
  i = 0,
60
140
  vdom = me.vdom,
61
- cellCls, cellId, config, column, dockLeftMargin, dockRightMargin, id, index, j, rendererOutput,
62
- record, rendererValue, selectedRows, trCls;
141
+ config, column, dockLeftMargin, dockRightMargin, id, index, j,
142
+ record, selectedRows, trCls;
63
143
 
64
144
  me.recordVnodeMap = {}; // remove old data
65
145
 
@@ -97,64 +177,8 @@ class View extends Component {
97
177
  j = 0;
98
178
 
99
179
  for (; j < colCount; j++) {
100
- column = columns[j];
101
- rendererValue = record[column.dataField];
102
-
103
- if (rendererValue === undefined) {
104
- rendererValue = '';
105
- }
106
-
107
- rendererOutput = column.renderer.call(column.rendererScope || container, {
108
- dataField: column.dataField,
109
- index : i,
110
- record,
111
- value : rendererValue
112
- });
113
-
114
- cellCls = ['neo-table-cell'];
115
-
116
- switch (Neo.typeOf(rendererOutput)) {
117
- case 'Object': {
118
- if (rendererOutput.cls && rendererOutput.html) {
119
- cellCls.push(...rendererOutput.cls);
120
- } else {
121
- rendererOutput = [rendererOutput];
122
- }
123
- break;
124
- }
125
- case 'String': {
126
- rendererOutput = {
127
- cls : cellCls,
128
- html: rendererOutput?.toString()
129
- };
130
- break;
131
- }
132
- }
133
-
134
- if (column.align !== 'left') {
135
- cellCls.push('neo-' + column.align)
136
- }
137
-
138
- // todo: remove the else part as soon as all tables use stores (examples table)
139
- if (hasStore) {
140
- cellId = me.getCellId(record, column.dataField);
141
- } else {
142
- cellId = vdom.cn[i]?.cn[j]?.id || Neo.getId('td');
143
- }
144
-
145
- config = {
146
- tag : 'td',
147
- id : cellId,
148
- cls : cellCls,
149
- style : rendererOutput.style || {},
150
- tabIndex: '-1'
151
- };
152
-
153
- if (Neo.typeOf(rendererOutput) === 'Object') {
154
- config.innerHTML = rendererOutput.html || ''
155
- } else {
156
- config.cn = rendererOutput
157
- }
180
+ column = columns[j];
181
+ config = me.applyRendererOutput(null, column, record, i, container);
158
182
 
159
183
  if (column.dock) {
160
184
  config.cls = ['neo-locked', ...config.cls || []];
@@ -195,7 +219,7 @@ class View extends Component {
195
219
  // this logic only works for selection.table.RowModel
196
220
  Neo.main.DomAccess.scrollToTableRow({id: selectedRows[0]});
197
221
  }
198
- });
222
+ })
199
223
  }
200
224
 
201
225
  /**
@@ -216,6 +240,29 @@ class View extends Component {
216
240
  return this.id + '__' + record[this.store.keyProperty] + '__' + dataField;
217
241
  }
218
242
 
243
+ /**
244
+ * Get a table column by a given field name
245
+ * @param {String} field
246
+ * @returns {Object|null}
247
+ */
248
+ getColumn(field) {
249
+ let container = Neo.getComponent(this.parentId),
250
+ columns = container.columns,
251
+ i = 0,
252
+ len = columns.length,
253
+ column;
254
+
255
+ for (; i < len; i++) {
256
+ column = columns[i];
257
+
258
+ if (column.dataField === field) {
259
+ return column
260
+ }
261
+ }
262
+
263
+ return null
264
+ }
265
+
219
266
  /**
220
267
  * Get the matching record by passing a row id, a cell id or an id inside a table cell.
221
268
  * @param {String} nodeId
@@ -287,26 +334,28 @@ class View extends Component {
287
334
  * @param {Object} opts.record
288
335
  */
289
336
  onStoreRecordChange(opts) {
290
- let me = this,
291
- deltas = [],
292
- cellId, cellNode;
337
+ let me = this,
338
+ container = Neo.getComponent(me.parentId),
339
+ needsUpdate = false,
340
+ vdom = me.vdom,
341
+ cellId, cellNode, column, index, scope;
293
342
 
294
343
  opts.fields.forEach(field => {
295
344
  cellId = me.getCellId(opts.record, field.name);
296
- cellNode = me.getVdomChild(cellId);
345
+ cellNode = VDomUtil.findVdomChild(vdom, cellId);
297
346
 
298
347
  // the vdom might not exist yet => nothing to do in this case
299
- if (cellNode) {
300
- cellNode.innerHTML = field.value; // keep the vdom in sync
348
+ if (cellNode.vdom) {
349
+ column = me.getColumn(field.name);
350
+ index = cellNode.index;
351
+ needsUpdate = true;
352
+ scope = column.rendererScope || container;
301
353
 
302
- deltas.push({
303
- id : cellId,
304
- innerHTML: field.value
305
- })
354
+ cellNode.parentNode.cn[index] = me.applyRendererOutput(cellId, column, opts.record, index, container)
306
355
  }
307
356
  });
308
357
 
309
- deltas.length > 0 && Neo.applyDeltas(me.appName, deltas);
358
+ needsUpdate && me.update()
310
359
  }
311
360
  }
312
361