neo.mjs 7.0.5 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/model/Content.mjs +3 -2
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/apps/portal/view/home/parts/Features.mjs +5 -5
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/todoList/version2/MainContainer.mjs +38 -48
- package/examples/todoList/version2/TodoList.mjs +6 -39
- package/examples/todoList/version2/TodoListModel.mjs +1 -1
- package/package.json +7 -7
- package/resources/data/deck/learnneo/pages/Welcome.md +0 -4
- package/resources/data/deck/learnneo/pages/guides/Forms.md +1 -0
- package/resources/data/deck/learnneo/pages/guides/InstanceLifecycle.md +1 -0
- package/resources/data/deck/learnneo/pages/guides/Layouts.md +1 -0
- package/resources/data/deck/learnneo/pages/guides/Mixins.md +1 -0
- package/resources/data/deck/learnneo/pages/guides/MultiWindow.md +1 -0
- package/resources/data/deck/learnneo/pages/guides/Tables.md +1 -0
- package/resources/data/deck/learnneo/pages/guides/events/DomEvents.md +263 -0
- package/resources/data/deck/learnneo/pages/{TodoList.md → tutorials/TodoList.md} +23 -33
- package/resources/data/deck/learnneo/tree.json +45 -48
- package/resources/scss/src/component/Splitter.scss +10 -1
- package/resources/scss/theme-dark/component/Splitter.scss +6 -3
- package/resources/scss/theme-light/component/Splitter.scss +6 -3
- package/resources/scss/theme-neo-light/component/Splitter.scss +6 -20
- package/src/DefaultConfig.mjs +2 -2
- package/src/code/LivePreview.mjs +28 -1
- package/src/collection/Base.mjs +1 -0
- package/src/component/Splitter.mjs +22 -4
- package/src/controller/Component.mjs +10 -10
- package/src/core/Observable.mjs +4 -27
- package/src/draggable/DragZone.mjs +6 -5
- package/src/grid/View.mjs +82 -0
- package/src/list/Base.mjs +16 -0
- package/src/main/addon/DragDrop.mjs +3 -2
- package/src/manager/DomEvent.mjs +30 -18
- package/src/table/View.mjs +82 -0
- package/src/util/Function.mjs +24 -0
- package/resources/data/deck/learnneo/pages/2023-10-08T20-37-30-658Z.md +0 -0
- package/resources/data/deck/learnneo/pages/2023-10-08T22-22-11-013Z.md +0 -0
- package/resources/data/deck/learnneo/pages/Earthquakes-01-goals.md +0 -32
- package/resources/data/deck/learnneo/pages/Earthquakes-Lab-01-generate-a-workspace.md +0 -47
- package/resources/data/deck/learnneo/pages/Earthquakes-Lab-02-generate-the-starter-app.md +0 -150
- package/resources/data/deck/learnneo/pages/Earthquakes-Lab-03-debugging.md +0 -136
- package/resources/data/deck/learnneo/pages/Earthquakes-Lab-04-fetch-data.md +0 -146
- package/resources/data/deck/learnneo/pages/Earthquakes-Lab-05-refactor-the-table.md +0 -146
- package/resources/data/deck/learnneo/pages/Earthquakes-Lab-06-use-a-view-model.md +0 -301
- package/resources/data/deck/learnneo/pages/Earthquakes-Lab-07-use-the-google-maps-addon.md +0 -175
- package/resources/data/deck/learnneo/pages/Earthquakes-Lab-08-events.md +0 -38
- package/resources/data/deck/learnneo/pages/TestLivePreview.md +0 -32
- package/resources/data/deck/learnneo/pages/WhatAboutHTML.md +0 -1
- package/resources/data/deck/learnneo/pages/stylesheet.md +0 -57
- /package/resources/data/deck/learnneo/pages/{WhyNeo-Effort.md → benefits/Effort.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{WhyNeo-Features.md → benefits/Features.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{WhyNeo-Intro.md → benefits/Introduction.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{WhyNeo-Multi-Window.md → benefits/Multi-Window.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{WhyNeo-Quick.md → benefits/Quick.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{WhyNeo-Speed.md → benefits/Speed.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{ComponentModels.md → gettingstarted/ComponentModels.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{Config.md → gettingstarted/Config.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{DescribingTheUI.md → gettingstarted/DescribingTheUI.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{Events.md → gettingstarted/Events.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{Extending.md → gettingstarted/Extending.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{References.md → gettingstarted/References.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{Setup.md → gettingstarted/Setup.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{2023-10-14T19-25-08-153Z.md → gettingstarted/Workspaces.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{ComponentsAndContainers.md → guides/ComponentsAndContainers.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{CustomComponents.md → guides/CustomComponents.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{MainThreadAddonExample.md → guides/MainThreadAddonExample.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{MainThreadAddonIntro.md → guides/MainThreadAddonIntro.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{GuideViewModels.md → guides/ViewModels.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{GuideEvents.md → guides/events/CustomEvents.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{2023-10-08T20-20-37-336Z.md → javascript/ClassFeatures.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{2023-10-07T19-18-28-517Z.md → javascript/Classes.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{2023-10-31T13-59-37-550Z.md → javascript/NewNode.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{2023-10-08T20-20-07-934Z.md → javascript/Overrides.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{2023-10-08T21-58-25-809Z.md → javascript/Super.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{Earthquakes.md → tutorials/Earthquakes.md} +0 -0
- /package/resources/data/deck/learnneo/pages/{RSP.md → tutorials/RSP.md} +0 -0
package/README.md
CHANGED
@@ -72,9 +72,9 @@ Join our community:</br>
|
|
72
72
|
|
73
73
|
</br><h2 id="getting-started">4. Getting Started</h2>
|
74
74
|
* Take a look at the <a href="./.github/GETTING_STARTED.md">Getting Started Guide</a>
|
75
|
-
* Make sure to dive into the <a href="https://neomjs.com/dist/production/apps/portal/#/learn/Setup">Learning Section</a>
|
75
|
+
* Make sure to dive into the <a href="https://neomjs.com/dist/production/apps/portal/#/learn/gettingstarted.Setup">Learning Section</a>
|
76
76
|
* The most advanced tutorial to help you with getting up to speed is this one:</br>
|
77
|
-
<a href="https://neomjs.com/dist/production/apps/portal/#/learn/Earthquakes">Earthquakes Tutorial</a>
|
77
|
+
<a href="https://neomjs.com/dist/production/apps/portal/#/learn/tutorials.Earthquakes">Earthquakes Tutorial</a>
|
78
78
|
|
79
79
|
</br><h2 id="cli">5. Command-Line Interface</h2>
|
80
80
|
You can find an in-depth description here: <a href="./buildScripts/README.md">Neo.mjs CLI</a>
|
package/apps/ServiceWorker.mjs
CHANGED
package/apps/portal/index.html
CHANGED
@@ -42,7 +42,7 @@ class Features extends BaseContainer {
|
|
42
42
|
]
|
43
43
|
}, {
|
44
44
|
header: 'Multi-Window Apps',
|
45
|
-
route : '#/learn/
|
45
|
+
route : '#/learn/benefits.Multi-Window',
|
46
46
|
|
47
47
|
content: [
|
48
48
|
'No need for a Native Shell (e.g. Electron)',
|
@@ -52,7 +52,7 @@ class Features extends BaseContainer {
|
|
52
52
|
]
|
53
53
|
}, {
|
54
54
|
header: 'Modern JS in your Browser',
|
55
|
-
route : '#/learn/
|
55
|
+
route : '#/learn/benefits.Quick',
|
56
56
|
|
57
57
|
content: [
|
58
58
|
'The Dev-Mode runs without the need for Transpilations or Compilations',
|
@@ -62,7 +62,7 @@ class Features extends BaseContainer {
|
|
62
62
|
]
|
63
63
|
}, {
|
64
64
|
header: 'Powerful Component-Library',
|
65
|
-
route : '#/learn/
|
65
|
+
route : '#/learn/benefits.Quick',
|
66
66
|
|
67
67
|
content: [
|
68
68
|
'Declarative Component-Trees',
|
@@ -72,7 +72,7 @@ class Features extends BaseContainer {
|
|
72
72
|
]
|
73
73
|
}, {
|
74
74
|
header: 'Elegant State Management',
|
75
|
-
route : '#/learn/
|
75
|
+
route : '#/learn/benefits.Speed',
|
76
76
|
|
77
77
|
content: [
|
78
78
|
'Multiple communicating State-Providers',
|
@@ -81,7 +81,7 @@ class Features extends BaseContainer {
|
|
81
81
|
]
|
82
82
|
}, {
|
83
83
|
header: 'Core Features',
|
84
|
-
route : '#/learn/
|
84
|
+
route : '#/learn/benefits.Speed',
|
85
85
|
|
86
86
|
content: [
|
87
87
|
'RPC Layer (cross-realm, including Backends)',
|
@@ -1,9 +1,8 @@
|
|
1
|
-
import Button
|
2
|
-
import Container
|
3
|
-
import TextField
|
4
|
-
import TodoList
|
5
|
-
import
|
6
|
-
import Toolbar from '../../../src/toolbar/Base.mjs';
|
1
|
+
import Button from '../../../src/button/Base.mjs';
|
2
|
+
import Container from '../../../src/container/Base.mjs';
|
3
|
+
import TextField from '../../../src/form/field/Text.mjs';
|
4
|
+
import TodoList from './TodoList.mjs';
|
5
|
+
import Toolbar from '../../../src/toolbar/Base.mjs';
|
7
6
|
|
8
7
|
/**
|
9
8
|
* @class Neo.examples.todoList.version2.MainContainer
|
@@ -15,72 +14,63 @@ class MainContainer extends Container {
|
|
15
14
|
autoMount: true,
|
16
15
|
height : 300,
|
17
16
|
margin : 20,
|
18
|
-
layout : {ntype: 'vbox', align: 'stretch'},
|
19
17
|
style : {margin: '20px'},
|
20
18
|
width : 300,
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
/**
|
28
|
-
* @member {Neo.data.Store|null} store=null
|
29
|
-
*/
|
30
|
-
store: null
|
31
|
-
}
|
32
|
-
|
33
|
-
construct(config) {
|
34
|
-
super.construct(config);
|
35
|
-
|
36
|
-
let me = this;
|
37
|
-
|
38
|
-
me.store = Neo.create({
|
39
|
-
module: TodoListStore
|
40
|
-
});
|
41
|
-
|
42
|
-
me.items = [{
|
43
|
-
module: TodoList,
|
44
|
-
flex : 1,
|
45
|
-
store : me.store
|
20
|
+
items: [{
|
21
|
+
module : TodoList,
|
22
|
+
flex : 1,
|
23
|
+
reference: 'todo-list'
|
46
24
|
}, {
|
47
25
|
module: Toolbar,
|
48
|
-
flex : 'none',
|
49
26
|
dock : 'bottom',
|
27
|
+
flex : 'none',
|
50
28
|
items : [{
|
51
29
|
module : TextField,
|
52
30
|
flex : 1,
|
53
31
|
labelPosition: 'inline',
|
54
32
|
labelText : 'Item Text',
|
55
|
-
reference : '
|
33
|
+
reference : 'add-item-field'
|
56
34
|
}, '->', {
|
57
|
-
module
|
58
|
-
handler
|
59
|
-
|
60
|
-
|
61
|
-
style : {height: '27px'},
|
62
|
-
text : 'Add Item'
|
35
|
+
module : Button,
|
36
|
+
handler: 'up.onAddButtonClick',
|
37
|
+
style : {height: '27px'},
|
38
|
+
text : 'Add Item'
|
63
39
|
}]
|
64
40
|
}]
|
65
41
|
}
|
66
42
|
|
67
|
-
|
43
|
+
/**
|
44
|
+
* @member {Number} idCounter=0
|
45
|
+
*/
|
46
|
+
idCounter = 0
|
47
|
+
|
48
|
+
/**
|
49
|
+
*
|
50
|
+
*/
|
51
|
+
onConstructed() {
|
52
|
+
super.onConstructed();
|
53
|
+
|
54
|
+
// Assuming the store is already loaded.
|
55
|
+
// For remote stores, add a load listener instead
|
56
|
+
this.idCounter = this.getReference('todo-list').store.getCount()
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* @param {Object} data
|
61
|
+
*/
|
62
|
+
onAddButtonClick(data) {
|
68
63
|
let me = this,
|
69
|
-
field = me.
|
70
|
-
data;
|
64
|
+
field = me.getReference('add-item-field');
|
71
65
|
|
72
66
|
if (field.value) {
|
73
67
|
me.idCounter++;
|
74
68
|
|
75
|
-
|
76
|
-
|
77
|
-
data.push({
|
69
|
+
me.getReference('todo-list').store.add({
|
78
70
|
id : me.idCounter,
|
79
71
|
done: false,
|
80
72
|
text: field.value
|
81
|
-
})
|
82
|
-
|
83
|
-
me.store.data = data
|
73
|
+
})
|
84
74
|
}
|
85
75
|
}
|
86
76
|
}
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import List
|
1
|
+
import List from '../../../src/list/Base.mjs';
|
2
|
+
import TodoListStore from './TodoListStore.mjs';
|
2
3
|
|
3
4
|
/**
|
4
5
|
* @class Neo.examples.todoList.version2.TodoList
|
@@ -6,45 +7,11 @@ import List from '../../../src/list/Base.mjs';
|
|
6
7
|
*/
|
7
8
|
class TodoList extends List {
|
8
9
|
static config = {
|
9
|
-
className
|
10
|
-
displayField: 'text'
|
10
|
+
className : 'Neo.examples.todoList.version2.TodoList',
|
11
|
+
displayField : 'text',
|
12
|
+
store : TodoListStore,
|
13
|
+
useCheckBoxes: true
|
11
14
|
}
|
12
|
-
|
13
|
-
/**
|
14
|
-
*
|
15
|
-
*/
|
16
|
-
onConstructed() {
|
17
|
-
super.onConstructed();
|
18
|
-
}
|
19
|
-
|
20
|
-
/*createItems(data) {
|
21
|
-
let me = this,
|
22
|
-
cls;
|
23
|
-
|
24
|
-
data.forEach(item => {
|
25
|
-
cls = ['todo-item'];
|
26
|
-
|
27
|
-
if (item.done) {
|
28
|
-
cls.push('fa', 'fa-check');
|
29
|
-
} else {
|
30
|
-
cls.push('far', 'fa-square');
|
31
|
-
}
|
32
|
-
|
33
|
-
me.vdom.cn.push({
|
34
|
-
tag: 'li',
|
35
|
-
cn : [{
|
36
|
-
tag : 'span',
|
37
|
-
cls,
|
38
|
-
style: {cursor: 'pointer', width: '20px'}
|
39
|
-
}, {
|
40
|
-
vtype: 'text',
|
41
|
-
html : item.text
|
42
|
-
}]
|
43
|
-
});
|
44
|
-
});
|
45
|
-
|
46
|
-
me.update();
|
47
|
-
}*/
|
48
15
|
}
|
49
16
|
|
50
17
|
export default Neo.setupClass(TodoList);
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "neo.mjs",
|
3
|
-
"version": "7.0
|
3
|
+
"version": "7.1.0",
|
4
4
|
"description": "The webworkers driven UI framework",
|
5
5
|
"type": "module",
|
6
6
|
"repository": {
|
@@ -48,22 +48,22 @@
|
|
48
48
|
"chalk": "^5.3.0",
|
49
49
|
"clean-webpack-plugin": "^4.0.0",
|
50
50
|
"commander": "^12.1.0",
|
51
|
-
"cssnano": "^7.0.
|
51
|
+
"cssnano": "^7.0.6",
|
52
52
|
"envinfo": "^7.13.0",
|
53
53
|
"fs-extra": "^11.2.0",
|
54
54
|
"highlightjs-line-numbers.js": "^2.8.0",
|
55
|
-
"inquirer": "^10.
|
56
|
-
"marked": "^14.1.
|
55
|
+
"inquirer": "^10.2.2",
|
56
|
+
"marked": "^14.1.2",
|
57
57
|
"monaco-editor": "0.50.0",
|
58
58
|
"neo-jsdoc": "1.0.1",
|
59
59
|
"neo-jsdoc-x": "1.0.5",
|
60
|
-
"postcss": "^8.4.
|
61
|
-
"sass": "^1.
|
60
|
+
"postcss": "^8.4.45",
|
61
|
+
"sass": "^1.78.0",
|
62
62
|
"siesta-lite": "5.5.2",
|
63
63
|
"url": "^0.11.4",
|
64
64
|
"webpack": "^5.94.0",
|
65
65
|
"webpack-cli": "^5.1.4",
|
66
|
-
"webpack-dev-server": "^5.0
|
66
|
+
"webpack-dev-server": "^5.1.0",
|
67
67
|
"webpack-hook-plugin": "^1.0.7",
|
68
68
|
"webpack-node-externals": "^3.0.0"
|
69
69
|
},
|
@@ -19,10 +19,6 @@ Hands-on tutorials where you'll code a few simple Neo.mjs applications.
|
|
19
19
|
|
20
20
|
These are in-depth discussions of various topics.
|
21
21
|
|
22
|
-
### Appendix
|
23
|
-
|
24
|
-
You can ignore this! It just holds a site style sheet and other miscellanea.
|
25
|
-
|
26
22
|
## Using these topics
|
27
23
|
|
28
24
|
### Layout
|
@@ -0,0 +1 @@
|
|
1
|
+
## todo
|
@@ -0,0 +1 @@
|
|
1
|
+
## todo
|
@@ -0,0 +1 @@
|
|
1
|
+
## todo
|
@@ -0,0 +1 @@
|
|
1
|
+
## todo
|
@@ -0,0 +1 @@
|
|
1
|
+
## todo
|
@@ -0,0 +1 @@
|
|
1
|
+
## todo
|
@@ -0,0 +1,263 @@
|
|
1
|
+
## Delegated global DOM Events
|
2
|
+
|
3
|
+
By default, Neo.mjs will attach DOM event listeners for all common events to the `document.body`.
|
4
|
+
You can the see the full list of event names inside:
|
5
|
+
<a href='https://github.com/neomjs/neo/blob/dev/src/manager/DomEvent.mjs' target='_blank'>manager.DomEvent</a>.
|
6
|
+
|
7
|
+
When subscribing to DOM events, the framework will automatically ensure that delegated events arrive
|
8
|
+
inside the Components where you subscribed to them.
|
9
|
+
|
10
|
+
An example: A typical Neo.mjs App will only have one global click listener.
|
11
|
+
|
12
|
+
## DOM Events are separated from the virtual DOM
|
13
|
+
|
14
|
+
Since we are frequently passing the `vdom` from the App Worker to the Data Worker,
|
15
|
+
it is crucial that our markup representation can get serialised.
|
16
|
+
|
17
|
+
So it has become a design goal to fully separate markup and logic.
|
18
|
+
The following examples will showcase how you can easily subscribe to DOM events in different ways.
|
19
|
+
|
20
|
+
## Subscribing to DOM Events
|
21
|
+
|
22
|
+
While we already have a fully polished
|
23
|
+
<a href='https://github.com/neomjs/neo/blob/dev/src/button/Base.mjs' target='_blank'>button.Base</a>
|
24
|
+
class inside the framework which you should use, the following examples will manually create
|
25
|
+
Button tags to showcase how you can subscribe to click events.
|
26
|
+
|
27
|
+
### Inline
|
28
|
+
|
29
|
+
For debugging purposes, you can specify your handler logic directly inline.
|
30
|
+
|
31
|
+
For the first Button, we are using a fat arrow function, in which case the scope will point to
|
32
|
+
the class. If you add `console.log(this);`, the output is most likely not want you want.
|
33
|
+
|
34
|
+
For the second Button we are defining a non-bound function, in which case `this` will point
|
35
|
+
to the Component instance.
|
36
|
+
|
37
|
+
<pre data-neo>
|
38
|
+
import Container from '../container/Base.mjs';
|
39
|
+
|
40
|
+
class MainView extends Container {
|
41
|
+
static config = {
|
42
|
+
className: 'Guides.domevents1.MainView',
|
43
|
+
layout : {ntype:'vbox', align:'start'},
|
44
|
+
style : {padding: '1em'},
|
45
|
+
|
46
|
+
items: [{
|
47
|
+
vdom: {tag: 'button', innerHTML: 'Button 1'},
|
48
|
+
|
49
|
+
domListeners: [{
|
50
|
+
click: data => Neo.Main.log({value: `Clicked on ${data.component.id}`})
|
51
|
+
}]
|
52
|
+
}, {
|
53
|
+
style: {marginTop: '1em'},
|
54
|
+
vdom : {tag: 'button', innerHTML: 'Button 2'},
|
55
|
+
|
56
|
+
domListeners: [{
|
57
|
+
click(data) {
|
58
|
+
Neo.Main.log({value: `Clicked on ${data.component.id}`})
|
59
|
+
}
|
60
|
+
}]
|
61
|
+
}]
|
62
|
+
}
|
63
|
+
}
|
64
|
+
MainView = Neo.setupClass(MainView);
|
65
|
+
</pre>
|
66
|
+
|
67
|
+
### Handler inside the Component Tree
|
68
|
+
|
69
|
+
When creating new Components, it can make sense to add the handler methods into the class.
|
70
|
+
A good example would be `tab.header.Toolbar`, where clicking on a Button will change the active Card.
|
71
|
+
|
72
|
+
You can use string based listeners. In case the handler method lives within the parent tree (any level),
|
73
|
+
we need to prefix these listeners with `up.`.
|
74
|
+
|
75
|
+
<pre data-neo>
|
76
|
+
import Container from '../container/Base.mjs';
|
77
|
+
|
78
|
+
class MainView extends Container {
|
79
|
+
static config = {
|
80
|
+
className: 'Guides.domevents2.MainView',
|
81
|
+
layout : {ntype:'vbox', align:'start'},
|
82
|
+
style : {padding: '1em'},
|
83
|
+
|
84
|
+
items: [{
|
85
|
+
vdom: {tag: 'button', innerHTML: 'Button 1'},
|
86
|
+
|
87
|
+
domListeners: [{
|
88
|
+
click: 'up.onButtonClick'
|
89
|
+
}]
|
90
|
+
}]
|
91
|
+
}
|
92
|
+
|
93
|
+
onButtonClick(data) {
|
94
|
+
Neo.Main.log({value: `Clicked on ${data.component.id}`})
|
95
|
+
}
|
96
|
+
}
|
97
|
+
MainView = Neo.setupClass(MainView);
|
98
|
+
</pre>
|
99
|
+
|
100
|
+
### Handler inside a ViewController
|
101
|
+
|
102
|
+
When creating Apps it often makes the most sense to move handler methods inside a ViewController.
|
103
|
+
This ensures a strict separation of your view definitions and business logic.
|
104
|
+
|
105
|
+
You can define the handlers as strings and the framework will check the ViewController hierarchy
|
106
|
+
to find the closest match.
|
107
|
+
|
108
|
+
A good use case would be a form submit Button, where a click will trigger a communication to the backend.
|
109
|
+
|
110
|
+
<pre data-neo>
|
111
|
+
import Container from '../container/Base.mjs';
|
112
|
+
import Controller from '../controller/Component.mjs';
|
113
|
+
|
114
|
+
class MainViewController extends Controller {
|
115
|
+
static config = {
|
116
|
+
className: 'Guides.domevents3.MainViewController'
|
117
|
+
}
|
118
|
+
onButtonClick(data) {
|
119
|
+
Neo.Main.log({value: `Clicked on ${data.component.id}`})
|
120
|
+
}
|
121
|
+
}
|
122
|
+
MainViewController = Neo.setupClass(MainViewController);
|
123
|
+
|
124
|
+
class MainView extends Container {
|
125
|
+
static config = {
|
126
|
+
className : 'Guides.domevents3.MainView',
|
127
|
+
controller: MainViewController,
|
128
|
+
layout : {ntype:'vbox', align:'start'},
|
129
|
+
style : {padding: '1em'},
|
130
|
+
|
131
|
+
items: [{
|
132
|
+
vdom: {tag: 'button', innerHTML: 'Button 1'},
|
133
|
+
|
134
|
+
domListeners: [{
|
135
|
+
click: 'onButtonClick'
|
136
|
+
}]
|
137
|
+
}]
|
138
|
+
}
|
139
|
+
}
|
140
|
+
MainView = Neo.setupClass(MainView);
|
141
|
+
</pre>
|
142
|
+
|
143
|
+
## Listener Options
|
144
|
+
|
145
|
+
### delegate
|
146
|
+
|
147
|
+
We can further delegate listeners to specific DOM nodes within our Component:
|
148
|
+
|
149
|
+
<pre data-neo>
|
150
|
+
import Container from '../container/Base.mjs';
|
151
|
+
|
152
|
+
class MainView extends Container {
|
153
|
+
static config = {
|
154
|
+
className: 'Guides.domevents4.MainView',
|
155
|
+
layout : {ntype:'vbox', align:'start'},
|
156
|
+
style : {padding: '1em'},
|
157
|
+
|
158
|
+
items: [{
|
159
|
+
|
160
|
+
style: {backgroundColor: '#3E63DD', padding: '3em'},
|
161
|
+
vdom : {cn: [{cls: 'inner-div', style: {backgroundColor: '#FFF', width: '5em', height: '3em'}}]},
|
162
|
+
|
163
|
+
domListeners: [{
|
164
|
+
click : 'up.onInnerDivClick',
|
165
|
+
delegate: '.inner-div'
|
166
|
+
}]
|
167
|
+
}]
|
168
|
+
}
|
169
|
+
|
170
|
+
onInnerDivClick(data) {
|
171
|
+
Neo.Main.log({value: `Clicked on ${data.component.id}`})
|
172
|
+
}
|
173
|
+
}
|
174
|
+
MainView = Neo.setupClass(MainView);
|
175
|
+
</pre>
|
176
|
+
|
177
|
+
In case you click on the blue div, no console logs will appear.
|
178
|
+
They do, when clicking on the white inner div.
|
179
|
+
|
180
|
+
Try it: In case you remove the `delegate` inside the source view,
|
181
|
+
we will get logs when clicking on the blue div too.
|
182
|
+
|
183
|
+
### bubble
|
184
|
+
|
185
|
+
We can prevent listeners from bubbling upwards:
|
186
|
+
|
187
|
+
<pre data-neo>
|
188
|
+
import Container from '../container/Base.mjs';
|
189
|
+
|
190
|
+
class MainView extends Container {
|
191
|
+
static config = {
|
192
|
+
className: 'Guides.domevents5.MainView',
|
193
|
+
layout : {ntype:'vbox', align:'start'},
|
194
|
+
style : {padding: '1em'},
|
195
|
+
|
196
|
+
items: [{
|
197
|
+
module: Container,
|
198
|
+
style : {backgroundColor: '#3E63DD', padding: '3em'},
|
199
|
+
|
200
|
+
domListeners: [
|
201
|
+
{click: 'up.onDivClick'}
|
202
|
+
],
|
203
|
+
|
204
|
+
items: [{
|
205
|
+
cls : 'inner-div',
|
206
|
+
style: {backgroundColor: '#FFF', width: '5em', height: '3em'},
|
207
|
+
|
208
|
+
domListeners: [
|
209
|
+
{click: 'up.onInnerDivClick', bubble: false}
|
210
|
+
]
|
211
|
+
}]
|
212
|
+
}]
|
213
|
+
}
|
214
|
+
|
215
|
+
onDivClick(data) {
|
216
|
+
Neo.Main.log({value: `Outer Div Click ${data.component.id}`})
|
217
|
+
}
|
218
|
+
|
219
|
+
onInnerDivClick(data) {
|
220
|
+
Neo.Main.log({value: `Inner Div Click ${data.component.id}`})
|
221
|
+
}
|
222
|
+
}
|
223
|
+
MainView = Neo.setupClass(MainView);
|
224
|
+
</pre>
|
225
|
+
|
226
|
+
Clicking on the inner (white) div will only trigger the inner listener and you will get one log.
|
227
|
+
|
228
|
+
Try it: In case you remove `bubble: false` inside the source view,
|
229
|
+
we will get 2 logs when clicking on the inner div.
|
230
|
+
|
231
|
+
### priority
|
232
|
+
|
233
|
+
The priority option defaults to 1. A higher value will get executed first.
|
234
|
+
|
235
|
+
It can be important to control the order in which handlers get executed.
|
236
|
+
While we could just manually order the array inside the following example,
|
237
|
+
there can be use cases where multiple subscribers get added at run-time and developers
|
238
|
+
can not be sure about the adding order.
|
239
|
+
|
240
|
+
<pre data-neo>
|
241
|
+
import Container from '../container/Base.mjs';
|
242
|
+
|
243
|
+
class MainView extends Container {
|
244
|
+
static config = {
|
245
|
+
className: 'Guides.domevents6.MainView',
|
246
|
+
layout : {ntype:'vbox', align:'start'},
|
247
|
+
style : {padding: '1em'},
|
248
|
+
|
249
|
+
items: [{
|
250
|
+
vdom : {tag: 'button', innerHTML: 'Button 1'},
|
251
|
+
|
252
|
+
domListeners: [
|
253
|
+
{click: data => Neo.Main.log({value: 'Listener 1'})},
|
254
|
+
{click: data => Neo.Main.log({value: 'Listener 2'}), priority: 2}
|
255
|
+
]
|
256
|
+
}]
|
257
|
+
}
|
258
|
+
}
|
259
|
+
MainView = Neo.setupClass(MainView);
|
260
|
+
</pre>
|
261
|
+
|
262
|
+
Try it: In case you remove `priority: 2` inside the source view,
|
263
|
+
the order of the logs will change.
|