neo.mjs 5.1.0 → 5.1.2

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.
@@ -419,18 +419,21 @@ fields: [{
419
419
  * (39) `if (/**/) {` if, blank char, parenthesis, blank char, curly bracket
420
420
  * (40) `for (/**/) {` for, blank char, parenthesis, blank char, curly bracket
421
421
  * (41) `switch(/**/) {` switch, parenthesis, blank char, curly bracket `// could get changed to use a blank char as well
422
- * (42) Use optional chaining => `?.` where it makes sense
422
+ * (42) `while (/**/) {` while, blank char, parenthesis, blank char, curly bracket
423
+ * (43) Use optional chaining => `?.` where it makes sense
423
424
  + Bad: `myView && myView.myFn && myView.myFn();`
424
425
  + Good: `myView?.myFn?.();`
425
426
  + https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
426
- * (43) Use method definitions (meaning avoid using the term `function`)
427
+ * (44) Use method definitions (meaning avoid using the term `function`)
427
428
  + Bad: `let obj = {a: function() {/**/}};`
428
429
  + Good: `let obj = {a() {/**/}};`
429
430
  + https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions
430
- * (44) Use shorthand property names when possible
431
+ * (45) Use shorthand property names when possible
431
432
  + Bad: `let obj = {record: record}`
432
433
  + Good: `let obj = {record};`
433
434
  + https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#property_definitions
434
- * (45) Do not use killing commas (while IE6 is luckily no longer an issue => file size)
435
- + Bad: `let obj = {a: 1,}`
435
+ * (46) Do not use killing commas (while IE6 is luckily no longer an issue => file size)
436
+ + Bad: `let obj = {a: 1,};`
437
+ + Bad: `let arr = [1,];`
436
438
  + Good: `let obj = {a: 1};`
439
+ + Good: `let arr = [1];`
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.1.0'
23
+ * @member {String} version='5.1.2'
24
24
  */
25
- version: '5.1.0'
25
+ version: '5.1.2'
26
26
  }
27
27
 
28
28
  /**
@@ -62,26 +62,26 @@ class HomeComponent extends Component {
62
62
  * @member {Object} _vdom
63
63
  */
64
64
  _vdom:
65
- {cn: [
66
- {cls: ['banner'], cn: [
67
- {cls: ['container'], cn: [
68
- {tag: 'h1', cls: ['logo-font'], html: 'conduit'},
69
- {tag: 'p', html: 'A place to share your knowledge.'}
70
- ]}
71
- ]},
72
- {cls: ['container', 'page'], cn: [
73
- {cls: ['row'], cn: [
74
- {cls: ['col-md-9'], cn: [
75
- {cls: ['feed-toggle'], cn: [
76
- {tag: 'ul', cls: ['nav', 'nav-pills', 'outline-active'], flag: 'feed-header', cn: []}
77
- ]},
78
- {tag: 'nav', cn: [
79
- {tag: 'ul', cls: ['pagination'], flag: 'pagination'}
80
- ]}
65
+ {cn: [
66
+ {cls: ['banner'], cn: [
67
+ {cls: ['container'], cn: [
68
+ {tag: 'h1', cls: ['logo-font'], html: 'conduit'},
69
+ {tag: 'p', html: 'A place to share your knowledge.'}
70
+ ]}
71
+ ]},
72
+ {cls: ['container', 'page'], cn: [
73
+ {cls: ['row'], cn: [
74
+ {cls: ['col-md-9'], cn: [
75
+ {cls: ['feed-toggle'], cn: [
76
+ {tag: 'ul', cls: ['nav', 'nav-pills', 'outline-active'], flag: 'feed-header', cn: []}
77
+ ]},
78
+ {tag: 'nav', cn: [
79
+ {tag: 'ul', cls: ['pagination'], flag: 'pagination'}
81
80
  ]}
82
81
  ]}
83
82
  ]}
84
83
  ]}
84
+ ]}
85
85
  }
86
86
 
87
87
  /**
@@ -11,6 +11,13 @@ import UserApi from '../api/User.mjs';
11
11
  * @extends Neo.controller.Component
12
12
  */
13
13
  class MainContainerController extends ComponentController {
14
+ /**
15
+ * True automatically applies the core.Observable mixin
16
+ * @member {Boolean} observable=false
17
+ * @static
18
+ */
19
+ static observable = true
20
+
14
21
  static config = {
15
22
  /**
16
23
  * @member {String} className='RealWorld.view.MainContainerController'
@@ -1,4 +1,17 @@
1
1
  [
2
+ {
3
+ "author" : "Torsten Dinkheller",
4
+ "authorImage" : "author_TorstenDinkheller.jpg",
5
+ "date" : "Feb 03, 2023",
6
+ "id" : 57,
7
+ "image" : "leveraging-overrides.jpg",
8
+ "name" : "Leveraging Overrides for Resilient Customizations and Effective Bugfixes in JavaScript Frameworks",
9
+ "provider" : "Medium",
10
+ "publisher" : "ITNEXT",
11
+ "selectedInto": [],
12
+ "type" : "Blog Post",
13
+ "url" : "https://itnext.io/leveraging-overrides-for-resilient-customizations-and-effective-bugfixes-in-javascript-frameworks-5b8ccfec0f8?source=friends_link&sk=790e868aac8b8570f0eee093adc30c00"
14
+ },
2
15
  {
3
16
  "author" : "Torsten Dinkheller",
4
17
  "authorImage" : "author_TorstenDinkheller.jpg",
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.1.0'
23
+ * @member {String} version='5.1.2'
24
24
  */
25
- version: '5.1.0'
25
+ version: '5.1.2'
26
26
  }
27
27
 
28
28
  /**
@@ -1,4 +1,5 @@
1
1
  import BreadcrumbToolbar from '../../../../src/toolbar/Breadcrumb.mjs';
2
+ import Store from '../../../../src/data/Store.mjs';
2
3
  import Viewport from '../../../../src/container/Viewport.mjs';
3
4
 
4
5
  /**
@@ -16,8 +17,36 @@ class MainContainer extends Viewport {
16
17
  * @member {Object[]} items
17
18
  */
18
19
  items: [{
19
- module: BreadcrumbToolbar,
20
- flex : 'none'
20
+ module : BreadcrumbToolbar,
21
+ activeKey: 2,
22
+ flex : 'none',
23
+
24
+ store: {
25
+ module: Store,
26
+
27
+ model: {
28
+ fields: [{
29
+ name: 'id',
30
+ type: 'Integer'
31
+ }, {
32
+ name: 'name',
33
+ type: 'String'
34
+ }, {
35
+ name: 'parentId',
36
+ type: 'Integer'
37
+ }, {
38
+ name: 'route',
39
+ type: 'String'
40
+ }]
41
+ },
42
+
43
+ data: [
44
+ {id: 1, name: 'Home', parentId: null, route: '/home/'},
45
+ {id: 2, name: 'Accessibility', parentId: 1, route: '/home/accessibility/'},
46
+ {id: 3, name: 'Imprint', parentId: 1, route: '/home/imprint/'},
47
+ {id: 4, name: 'News', parentId: 1, route: '/home/news/'},
48
+ ]
49
+ }
21
50
  }],
22
51
  /**
23
52
  * @member {Object} layout={ntype:'vbox',align:'stretch'}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "5.1.0",
3
+ "version": "5.1.2",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -18,6 +18,7 @@
18
18
  .neo-typeahead-input {
19
19
  border-color: transparent;
20
20
  color : v(selectfield-input-hint-color);
21
+ font : v(textfield-input-font);
21
22
  min-height : 25px;
22
23
  opacity : v(selectfield-input-hint-opacity);
23
24
  }
@@ -309,7 +309,6 @@
309
309
  flex-shrink : 1;
310
310
  margin : 0; // important for Safari => #1125
311
311
  min-height : v(textfield-input-height);
312
- width : 30px;
313
312
  }
314
313
  }
315
314
 
@@ -331,6 +330,7 @@
331
330
  min-width : 50px;
332
331
  padding : v(textfield-input-padding);
333
332
  transition : 250ms border-color cubic-bezier(0.4, 0, 0.2, 1);
333
+ width : 100%;
334
334
 
335
335
  &:focus {
336
336
  outline: none;
@@ -0,0 +1,17 @@
1
+ .neo-breadcrumb-toolbar {
2
+ .neo-button {
3
+ &:not(:last-child) {
4
+ margin-right: 30px;
5
+
6
+ &::after {
7
+ color : v(button-text-color);
8
+ content : "\f105";
9
+ display : block;
10
+ font-family : "Font Awesome 5 Free";
11
+ font-weight : 600;
12
+ position : absolute;
13
+ right : -20px;
14
+ }
15
+ }
16
+ }
17
+ }
@@ -237,12 +237,12 @@ const DefaultConfig = {
237
237
  useVdomWorker: true,
238
238
  /**
239
239
  * buildScripts/injectPackageVersion.mjs will update this value
240
- * @default '5.1.0'
240
+ * @default '5.1.2'
241
241
  * @memberOf! module:Neo
242
242
  * @name config.version
243
243
  * @type String
244
244
  */
245
- version: '5.1.0'
245
+ version: '5.1.2'
246
246
  };
247
247
 
248
248
  Object.assign(DefaultConfig, {
package/src/Neo.mjs CHANGED
@@ -70,13 +70,13 @@ Neo = globalThis.Neo = Object.assign({
70
70
 
71
71
  protos.forEach(element => {
72
72
  let mixins;
73
-
73
+
74
74
  ctor = element.constructor;
75
75
 
76
76
  cfg = ctor.config || {};
77
77
 
78
- if (Neo.overrides) {
79
- ctor.applyOverrides(cfg);
78
+ if (Neo.overwrites) {
79
+ ctor.applyOverwrites(cfg);
80
80
  }
81
81
 
82
82
  Object.entries(cfg).forEach(([key, value]) => {
@@ -215,6 +215,11 @@ class Base extends Component {
215
215
 
216
216
  case 'NeoInstance': {
217
217
  item.set(config);
218
+
219
+ // In case an item got created outside a VC or VM based hierarchy, there might be bindings or string
220
+ // based listeners which still need to get resolved.
221
+ item.getController()?.parseConfig(item);
222
+ item.getModel() ?.parseConfig(item);
218
223
  break;
219
224
  }
220
225
 
@@ -141,6 +141,7 @@ class Component extends Base {
141
141
  let me = this,
142
142
  listeners = component.listeners,
143
143
  reference = component.reference,
144
+ validator = component.validator,
144
145
  eventHandler, handlerScope;
145
146
 
146
147
  if (listeners) {
@@ -174,6 +175,16 @@ class Component extends Base {
174
175
  });
175
176
  }
176
177
 
178
+ if (Neo.isString(validator)) {
179
+ handlerScope = me.getHandlerScope(validator);
180
+
181
+ if (!handlerScope) {
182
+ Logger.logError('Unknown validator for', component.id, component);
183
+ } else {
184
+ component.validator = handlerScope[validator].bind(handlerScope);
185
+ }
186
+ }
187
+
177
188
  if (reference) {
178
189
  me.references[reference] = component;
179
190
  }
package/src/core/Base.mjs CHANGED
@@ -23,10 +23,10 @@ class Base {
23
23
  */
24
24
  static observable = false
25
25
  /**
26
- * Keep the overriden methods
26
+ * Keep the overwritten methods
27
27
  * @type {Object}
28
28
  */
29
- static overriddenMethods = {}
29
+ static overwrittenMethods = {}
30
30
 
31
31
  /**
32
32
  * Set this one to false in case you don't want to stick
@@ -150,29 +150,29 @@ class Base {
150
150
  }
151
151
 
152
152
  /**
153
- * Applying overrides and adding overriddenMethods to the class constructors
153
+ * Applying overwrites and adding overwrittenMethods to the class constructors
154
154
  * @param {Object} cfg
155
155
  * @protected
156
156
  */
157
- static applyOverrides(cfg) {
158
- let overrides = Neo.ns(cfg.className, false, Neo.overrides),
157
+ static applyOverwrites(cfg) {
158
+ let overwrites = Neo.ns(cfg.className, false, Neo.overwrites),
159
159
  cls, item;
160
160
 
161
- if (overrides) {
161
+ if (overwrites) {
162
162
  // Apply all methods
163
- for (item in overrides) {
164
- if (Neo.isFunction(overrides[item])) {
163
+ for (item in overwrites) {
164
+ if (Neo.isFunction(overwrites[item])) {
165
165
  // Already existing ones
166
166
  cls = this.prototype;
167
167
 
168
168
  if (cls[item]) {
169
- // add to overriddenMethods
170
- cls.constructor.overriddenMethods[item] = cls[item];
169
+ // add to overwrittenMethods
170
+ cls.constructor.overwrittenMethods[item] = cls[item];
171
171
  }
172
172
  }
173
173
  }
174
174
  // Apply configs to prototype
175
- overrides && Object.assign(cfg, overrides);
175
+ overwrites && Object.assign(cfg, overwrites);
176
176
  }
177
177
  }
178
178
 
@@ -196,12 +196,12 @@ class Base {
196
196
  }
197
197
 
198
198
  /**
199
- * From within an override, a method can call a parent method, by using callOVerridden.
199
+ * From within an overwrite, a method can call a parent method, by using callOverwritten.
200
200
  *
201
201
  * @example
202
202
  * afterSetHeight(value, oldValue) {
203
203
  * // do the standard
204
- * this.callOverridden(...arguments);
204
+ * this.callOverwritten(...arguments);
205
205
  * // do you own stuff
206
206
  * }
207
207
  *
@@ -209,17 +209,17 @@ class Base {
209
209
  * This is based on the following error structure, e.g. afterSetHeight.
210
210
  *
211
211
  * Error
212
- * at Base.callOverridden (Base.mjs:176:21)
212
+ * at Base.callOverwritten (Base.mjs:176:21)
213
213
  * at Base.afterSetHeight (Overrides.mjs:19:26)
214
214
  *
215
215
  * @param args
216
216
  */
217
- callOverridden(...args) {
217
+ callOverwritten(...args) {
218
218
  let stack = new Error().stack,
219
219
  regex = Base.methodNameRegex,
220
220
  methodName = stack.match(regex)[1];
221
221
 
222
- this.__proto__.constructor.overriddenMethods[methodName].call(this, ...args);
222
+ this.__proto__.constructor.overwrittenMethods[methodName].call(this, ...args);
223
223
  }
224
224
 
225
225
  /**
@@ -148,8 +148,10 @@ class Observable extends Base {
148
148
  }
149
149
 
150
150
  while (proto?.constructor.isClass) {
151
+ ctor = proto.constructor;
152
+
151
153
  if (ctor.observable && !ctor.listeners) {
152
- Object.assign(proto.constructor, {
154
+ Object.assign(ctor, {
153
155
  addListener : me.addListener,
154
156
  fire : me.fire,
155
157
  listeners : {},
@@ -242,7 +242,7 @@ class Number extends Text {
242
242
  value = (oldValue - stepSize) < me.minValue ? me.maxValue : (oldValue - stepSize);
243
243
 
244
244
  if (me.excludedValues) {
245
- while(me.excludedValues.includes(value)) {
245
+ while (me.excludedValues.includes(value)) {
246
246
  value = Math.max(me.minValue, value - stepSize);
247
247
  }
248
248
  }
@@ -262,7 +262,7 @@ class Number extends Text {
262
262
  value = (oldValue + stepSize) > me.maxValue ? me.minValue : (oldValue + stepSize);
263
263
 
264
264
  if (me.excludedValues) {
265
- while(me.excludedValues.includes(value)) {
265
+ while (me.excludedValues.includes(value)) {
266
266
  value = Math.min(me.maxValue, value + stepSize);
267
267
  }
268
268
  }
@@ -115,6 +115,20 @@ class Picker extends Text {
115
115
  this.cls = cls;
116
116
  }
117
117
 
118
+ /**
119
+ * Triggered after the mounted config got changed
120
+ * @param {Boolean} value
121
+ * @param {Boolean} oldValue
122
+ * @protected
123
+ */
124
+ afterSetMounted(value, oldValue) {
125
+ if (value === false && oldValue && this.pickerIsMounted) {
126
+ this.picker.hide();
127
+ }
128
+
129
+ super.afterSetMounted(value, oldValue);
130
+ }
131
+
118
132
  /**
119
133
  * @param {Boolean} silent
120
134
  */
@@ -186,6 +200,14 @@ class Picker extends Text {
186
200
  return null;
187
201
  }
188
202
 
203
+ /**
204
+ * @param args
205
+ */
206
+ destroy(...args) {
207
+ this.picker?.destroy();
208
+ super.destroy(...args);
209
+ }
210
+
189
211
  /**
190
212
  * @param {Function} [callback]
191
213
  * @param {Object} [callbackScope]
@@ -640,7 +640,7 @@ class Select extends Picker {
640
640
  }
641
641
 
642
642
  if (!hasMatch && inputHintEl) {
643
- inputHintEl.value = '';
643
+ inputHintEl.value = null;
644
644
  me.hintRecordId = null;
645
645
  }
646
646
 
@@ -158,6 +158,11 @@ class Text extends Base {
158
158
  * @member {Object|Object[]|null} triggers_=null
159
159
  */
160
160
  triggers_: null,
161
+ /**
162
+ * A string based value will get resolved into the closest controller which implements it
163
+ * @member {Function|String|null} validator=null
164
+ */
165
+ validator: null,
161
166
  /**
162
167
  * @member {Object} _vdom
163
168
  */
@@ -525,7 +530,17 @@ class Text extends Base {
525
530
  * @protected
526
531
  */
527
532
  afterSetPlaceholderText(value, oldValue) {
528
- this.changeInputElKey('placeholder', value === '' ? null : value);
533
+ let me = this,
534
+ cls = me.cls;
535
+
536
+ me.changeInputElKey('placeholder', value === '' ? null : value);
537
+
538
+ // a non-empty placeholder needs to keep the 'neo-has-content' rule
539
+ // => labelPosition: 'inline' should keep the label at the top
540
+ if (Neo.isEmpty(value) !== Neo.isEmpty(oldValue)) {
541
+ NeoArray[value !== null && value.toString().length > 0 ? 'add' : 'remove'](cls, 'neo-has-content');
542
+ me.cls = cls;
543
+ }
529
544
  }
530
545
 
531
546
  /**
@@ -681,21 +696,19 @@ class Text extends Base {
681
696
  * @protected
682
697
  */
683
698
  afterSetValue(value, oldValue) {
684
- let me = this,
685
- cls = me.cls,
686
- emptyValue = Neo.isEmpty(value),
687
- originalValue = me.originalConfig.value,
688
- isDirty = value !== originalValue && emptyValue !== Neo.isEmpty(originalValue);
699
+ let me = this,
700
+ cls = me.cls,
701
+ placeholderText = me.placeholderText,
702
+ hasContent = placeholderText?.length > 0 || value !== null && value.toString().length > 0,
703
+ originalValue = me.originalConfig.value,
704
+ isDirty = value !== originalValue && Neo.isEmpty(value) !== Neo.isEmpty(originalValue);
689
705
 
690
706
  me.silentVdomUpdate = true;
691
707
 
692
708
  me.getInputEl().value = value;
693
709
 
694
- if (emptyValue !== Neo.isEmpty(oldValue)) {
695
- NeoArray[value !== null && value.toString().length > 0 ? 'add' : 'remove'](cls, 'neo-has-content');
696
- }
697
-
698
- NeoArray[isDirty ? 'add' : 'remove'](cls, 'neo-is-dirty');
710
+ NeoArray[hasContent ? 'add' : 'remove'](cls, 'neo-has-content');
711
+ NeoArray[isDirty ? 'add' : 'remove'](cls, 'neo-is-dirty');
699
712
  me.cls = cls;
700
713
 
701
714
  me.validate(); // silent
@@ -1289,9 +1302,17 @@ class Text extends Base {
1289
1302
  value = me.value,
1290
1303
  valueLength = value?.toString().length,
1291
1304
  isEmpty = !value || valueLength < 1,
1292
- errorParam = {maxLength, minLength, valueLength};
1305
+ errorParam = {maxLength, minLength, valueLength},
1306
+ errorText;
1293
1307
 
1294
- if (required && isEmpty) {
1308
+ if (Neo.isFunction(me.validator)) {
1309
+ errorText = me.validator(me);
1310
+
1311
+ if (errorText !== true) {
1312
+ me[errorField] = errorText;
1313
+ returnValue = false;
1314
+ }
1315
+ } else if (required && isEmpty) {
1295
1316
  me[errorField] = me.errorTextRequired;
1296
1317
  returnValue = false;
1297
1318
  } else if (Neo.isNumber(maxLength) && valueLength > maxLength) {
@@ -407,11 +407,20 @@ class DomEvents extends Base {
407
407
  * @param {Object} event
408
408
  */
409
409
  onChange(event) {
410
- this.sendMessageToApp({
410
+ let target = event.target,
411
+
412
+ data = {
411
413
  ...this.getEventData(event),
412
- valid: event.target.checkValidity(),
413
- value: event.target.value
414
- });
414
+ valid: target.checkValidity(),
415
+ value: target.value
416
+ };
417
+
418
+ // input and change events can pass a FileList for input type file
419
+ if (target.files) {
420
+ data.files = target.files;
421
+ }
422
+
423
+ this.sendMessageToApp(data);
415
424
  }
416
425
 
417
426
  /**
@@ -13,6 +13,19 @@ class Breadcrumb extends Toolbar {
13
13
  * @protected
14
14
  */
15
15
  className: 'Neo.toolbar.Breadcrumb',
16
+ /**
17
+ * @member {String} ntype='breadcrumb-toolbar'
18
+ * @protected
19
+ */
20
+ ntype: 'breadcrumb-toolbar',
21
+ /**
22
+ * @member {String[]} baseCls=['neo-breadcrumb-toolbar','neo-toolbar']
23
+ */
24
+ baseCls: ['neo-breadcrumb-toolbar', 'neo-toolbar'],
25
+ /**
26
+ * @member {Number|String|null} activeKey_=null
27
+ */
28
+ activeKey_: null,
16
29
  /**
17
30
  * @member {Object[]} items
18
31
  */
@@ -23,6 +36,16 @@ class Breadcrumb extends Toolbar {
23
36
  store_: null
24
37
  }
25
38
 
39
+ /**
40
+ * Triggered after the activeKey config got changed
41
+ * @param {Number|String|null} value
42
+ * @param {Number|String|null} oldValue
43
+ * @protected
44
+ */
45
+ afterSetActiveKey(value, oldValue) {
46
+ this.store.getCount?.() > 0 && this.updateItems()
47
+ }
48
+
26
49
  /**
27
50
  * Triggered after the store config got changed
28
51
  * @param {Neo.data.Store|Object} value
@@ -30,7 +53,14 @@ class Breadcrumb extends Toolbar {
30
53
  * @protected
31
54
  */
32
55
  afterSetStore(value, oldValue) {
56
+ let me = this;
57
+
58
+ value.on({
59
+ load: this.onStoreLoad,
60
+ scope: me
61
+ });
33
62
 
63
+ value?.getCount() > 0 && me.onStoreLoad(value.items)
34
64
  }
35
65
 
36
66
  /**
@@ -44,6 +74,64 @@ class Breadcrumb extends Toolbar {
44
74
  oldValue?.destroy();
45
75
  return ClassSystemUtil.beforeSetInstance(value, Store);
46
76
  }
77
+
78
+ /**
79
+ * @returns {Object[]}
80
+ */
81
+ getPathItems() {
82
+ let items = [],
83
+ parentId = this.activeKey,
84
+ store = this.store,
85
+ item;
86
+
87
+ while (parentId !== null) {
88
+ item = store.get(parentId);
89
+
90
+ items.unshift(item);
91
+
92
+ parentId = item.parentId;
93
+ }
94
+
95
+ return items;
96
+ }
97
+
98
+ /**
99
+ * @param {Object[]} items
100
+ */
101
+ onStoreLoad(items) {
102
+ this.activeKey !== null && this.updateItems()
103
+ }
104
+
105
+ /**
106
+ *
107
+ */
108
+ updateItems() {
109
+ let me = this,
110
+ items = me.items,
111
+ pathItems = me.getPathItems(),
112
+ i = 0,
113
+ len = pathItems.length,
114
+ newItems = [],
115
+ config, item
116
+
117
+ for (; i < len; i++) {
118
+ item = pathItems[i];
119
+
120
+ config = {
121
+ editRoute: false,
122
+ route : item.route,
123
+ text : item.name
124
+ };
125
+
126
+ if (items[i]) {
127
+ items[i].set(config);
128
+ } else {
129
+ newItems.push(config);
130
+ }
131
+ }
132
+
133
+ newItems.length > 0 && me.add(newItems);
134
+ }
47
135
  }
48
136
 
49
137
  Neo.applyClassConfig(Breadcrumb);