neo.mjs 10.0.0-alpha.4 → 10.0.0-beta.1
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/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/resources/data/examples_devmode.json +26 -27
- package/apps/portal/resources/data/examples_dist_dev.json +26 -27
- package/apps/portal/resources/data/examples_dist_esm.json +26 -27
- package/apps/portal/resources/data/examples_dist_prod.json +27 -28
- package/apps/portal/view/blog/List.mjs +1 -1
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/apps/portal/view/learn/ContentComponent.mjs +102 -111
- package/buildScripts/buildThemes.mjs +1 -1
- package/examples/grid/animatedRowSorting/Viewport.mjs +4 -4
- package/examples/grid/bigData/ControlsContainer.mjs +3 -3
- package/examples/grid/bigData/GridContainer.mjs +8 -8
- package/examples/grid/cellEditing/MainContainer.mjs +5 -5
- package/examples/grid/container/MainContainer.mjs +4 -4
- package/examples/grid/nestedRecordFields/Viewport.mjs +5 -5
- package/examples/table/cellEditing/MainContainer.mjs +1 -1
- package/examples/table/container/MainContainer.mjs +3 -3
- package/examples/table/nestedRecordFields/Viewport.mjs +6 -6
- package/examples/tableFiltering/MainContainer.mjs +1 -1
- package/examples/tablePerformance/MainContainer.mjs +1 -1
- package/examples/tablePerformance/MainContainer2.mjs +1 -1
- package/examples/tablePerformance/MainContainer3.mjs +2 -2
- package/examples/tableStore/MainContainer.mjs +2 -2
- package/learn/UsingTheseTopics.md +2 -2
- package/learn/benefits/ConfigSystem.md +2 -2
- package/learn/benefits/FormsEngine.md +14 -14
- package/learn/benefits/MultiWindow.md +2 -2
- package/learn/benefits/OffTheMainThread.md +2 -2
- package/learn/benefits/Speed.md +2 -2
- package/learn/gettingstarted/ComponentModels.md +4 -4
- package/learn/gettingstarted/Config.md +6 -6
- package/learn/gettingstarted/DescribingTheUI.md +4 -4
- package/learn/gettingstarted/Events.md +6 -6
- package/learn/gettingstarted/Extending.md +4 -4
- package/learn/gettingstarted/References.md +6 -6
- package/learn/gettingstarted/Workspaces.md +6 -6
- package/learn/guides/ApplicationBootstrap.md +40 -42
- package/learn/guides/ComponentsAndContainers.md +12 -12
- package/learn/guides/CustomComponents.md +2 -2
- package/learn/guides/MainThreadAddonIntro.md +2 -2
- package/learn/guides/PortalApp.md +2 -2
- package/learn/guides/StateProviders.md +12 -12
- package/learn/guides/events/CustomEvents.md +16 -16
- package/learn/guides/events/DomEvents.md +12 -12
- package/learn/javascript/ClassFeatures.md +3 -2
- package/learn/javascript/Classes.md +8 -8
- package/learn/javascript/NewNode.md +4 -4
- package/learn/javascript/Overrides.md +8 -8
- package/learn/javascript/Super.md +10 -8
- package/learn/tutorials/Earthquakes.md +54 -57
- package/learn/tutorials/TodoList.md +4 -4
- package/package.json +1 -1
- package/resources/scss/src/apps/portal/learn/ContentComponent.scss +12 -0
- package/resources/scss/src/grid/{View.scss → Body.scss} +2 -2
- package/resources/scss/src/grid/VerticalScrollbar.scss +1 -1
- package/resources/scss/src/grid/plugin/AnimateRows.scss +1 -1
- package/resources/scss/src/grid/plugin/CellEditing.scss +1 -1
- package/resources/scss/src/table/{View.scss → Body.scss} +1 -1
- package/resources/scss/src/table/plugin/CellEditing.scss +1 -1
- package/resources/scss/theme-dark/grid/{View.scss → Body.scss} +1 -1
- package/resources/scss/theme-dark/table/{View.scss → Body.scss} +1 -1
- package/resources/scss/theme-light/grid/{View.scss → Body.scss} +1 -1
- package/resources/scss/theme-light/table/{View.scss → Body.scss} +1 -1
- package/resources/scss/theme-neo-light/Global.scss +1 -2
- package/resources/scss/theme-neo-light/grid/{View.scss → Body.scss} +1 -1
- package/resources/scss/theme-neo-light/table/{View.scss → Body.scss} +1 -1
- package/src/DefaultConfig.mjs +2 -2
- package/src/core/Base.mjs +59 -12
- package/src/core/Util.mjs +14 -2
- package/src/draggable/grid/header/toolbar/SortZone.mjs +21 -21
- package/src/draggable/table/header/toolbar/SortZone.mjs +1 -1
- package/src/grid/{View.mjs → Body.mjs} +19 -20
- package/src/grid/Container.mjs +58 -58
- package/src/grid/ScrollManager.mjs +56 -56
- package/src/grid/VerticalScrollbar.mjs +2 -2
- package/src/grid/_export.mjs +2 -2
- package/src/grid/column/AnimatedChange.mjs +5 -5
- package/src/grid/column/Base.mjs +1 -1
- package/src/grid/column/Component.mjs +6 -6
- package/src/grid/header/Toolbar.mjs +9 -9
- package/src/grid/plugin/AnimateRows.mjs +1 -2
- package/src/main/addon/AmCharts.mjs +8 -11
- package/src/main/addon/Base.mjs +150 -42
- package/src/main/addon/GoogleMaps.mjs +9 -16
- package/src/main/addon/HighlightJS.mjs +2 -13
- package/src/main/addon/IntersectionObserver.mjs +21 -21
- package/src/main/addon/MonacoEditor.mjs +1 -6
- package/src/table/{View.mjs → Body.mjs} +19 -20
- package/src/table/Container.mjs +43 -43
- package/src/table/_export.mjs +2 -2
- package/src/table/plugin/CellEditing.mjs +19 -19
- package/src/util/Style.mjs +2 -6
- package/src/vdom/Helper.mjs +10 -13
- package/src/worker/App.mjs +6 -18
- package/src/worker/Base.mjs +1 -1
- package/src/worker/Manager.mjs +4 -8
- package/src/worker/mixin/RemoteMethodAccess.mjs +1 -1
@@ -14,11 +14,20 @@ using Web Workers.
|
|
14
14
|
|
15
15
|
## Bootstrap Sequence
|
16
16
|
|
17
|
+
```text
|
18
|
+
myapp/
|
19
|
+
├── view/
|
20
|
+
│ └── Viewport.mjs // The app main view
|
21
|
+
├── app.mjs // The entry-point for your code inside the app worker
|
22
|
+
├── index.html // The entry-point for a main-thread
|
23
|
+
└── neo-config.json // Framework global configs for your app
|
24
|
+
```
|
25
|
+
|
17
26
|
### 1. Entry Point: index.html
|
18
27
|
|
19
28
|
The bootstrap process begins with a minimal HTML file:
|
20
29
|
|
21
|
-
```html
|
30
|
+
```html readonly
|
22
31
|
<!DOCTYPE HTML>
|
23
32
|
<html>
|
24
33
|
<head>
|
@@ -42,7 +51,7 @@ The only JavaScript file imported is the `MicroLoader.mjs`, which is loaded as a
|
|
42
51
|
|
43
52
|
The `MicroLoader.mjs` is a small script that fetches the application configuration and bootstraps the main thread:
|
44
53
|
|
45
|
-
```javascript
|
54
|
+
```javascript readonly
|
46
55
|
fetch('./neo-config.json').then(r => r.json()).then(d => {
|
47
56
|
globalThis.Neo = {config: {...d}};
|
48
57
|
import(d.mainPath)
|
@@ -60,13 +69,13 @@ It performs these steps:
|
|
60
69
|
The `neo-config.json` file contains essential configuration for the application bootstrap. For a complete overview
|
61
70
|
of all available configuration options, you can refer to the `src/DefaultConfig.mjs` file in the Neo.mjs framework:
|
62
71
|
|
63
|
-
```json
|
72
|
+
```json readonly
|
64
73
|
{
|
65
74
|
"appPath" : "apps/myapp/app.mjs",
|
66
75
|
"basePath" : "../../",
|
67
76
|
"environment" : "development",
|
68
77
|
"mainPath" : "./Main.mjs",
|
69
|
-
"mainThreadAddons": ["Stylesheet"],
|
78
|
+
"mainThreadAddons": ["DragDrop", "Navigator", "Stylesheet"],
|
70
79
|
"themes" : ["neo-theme-light"],
|
71
80
|
"useCanvasWorker" : false,
|
72
81
|
"useDataWorker" : false,
|
@@ -79,23 +88,23 @@ of all available configuration options, you can refer to the `src/DefaultConfig.
|
|
79
88
|
```
|
80
89
|
|
81
90
|
**Key Configuration Properties:**
|
82
|
-
-
|
83
|
-
-
|
84
|
-
-
|
85
|
-
-
|
86
|
-
-
|
87
|
-
-
|
88
|
-
-
|
89
|
-
-
|
90
|
-
-
|
91
|
-
-
|
91
|
+
- `appPath` - Points to your application's entry point (app.mjs)
|
92
|
+
- `basePath` - Root path for resolving other paths
|
93
|
+
- `environment` - Controls optimization and debugging features
|
94
|
+
- `mainPath` - Framework's main thread bootstrap file
|
95
|
+
- `mainThreadAddons` - Additional features to load in the main thread
|
96
|
+
- `themes` - CSS themes to load
|
97
|
+
- `useCanvasWorker` - Controls whether to use a separate worker for canvas operations
|
98
|
+
- `useDataWorker` - Controls whether to use a separate worker for data operations
|
99
|
+
- `useServiceWorker` - Controls whether to use a service worker for caching
|
100
|
+
- `useSharedWorkers` - When set to true, ALL workers (App, VDom, Data, etc.) will be created as SharedWorkers,
|
92
101
|
enabling multi-window applications. When false, all workers will be dedicated workers (better for single-page applications).
|
93
|
-
The
|
102
|
+
The worker.Base class provides an abstraction layer that supports both types with a consistent API, allowing developers
|
94
103
|
to create an app with dedicated workers first (which are easier to debug) and then switch to shared workers with just
|
95
104
|
a one-line configuration change.
|
96
|
-
-
|
97
|
-
-
|
98
|
-
-
|
105
|
+
- `useTaskWorker` - Controls whether to use a separate worker for background tasks
|
106
|
+
- `useVdomWorker` - Controls whether to use a separate worker for virtual DOM operations
|
107
|
+
- `workerBasePath` - Location of worker initialization files
|
99
108
|
|
100
109
|
**Configuration Categories:**
|
101
110
|
- **Path Resolution** - Where to find files and modules (auto-generated by default)
|
@@ -107,7 +116,7 @@ of all available configuration options, you can refer to the `src/DefaultConfig.
|
|
107
116
|
|
108
117
|
The MicroLoader imports `Main.mjs`, which initializes the main thread:
|
109
118
|
|
110
|
-
```javascript
|
119
|
+
```javascript readonly
|
111
120
|
import Neo from './Neo.mjs';
|
112
121
|
import * as core from './core/_export.mjs';
|
113
122
|
import DomAccess from './main/DomAccess.mjs';
|
@@ -149,12 +158,10 @@ The Main class:
|
|
149
158
|
3. Listens for the 'domContentLoaded' event
|
150
159
|
4. When the DOM is loaded, it loads any main thread addons and notifies the WorkerManager
|
151
160
|
|
152
|
-
### 5.
|
161
|
+
### 5. Neo.worker.Manager: Creating Workers
|
153
162
|
|
154
|
-
|
155
|
-
|
156
|
-
```javascript
|
157
|
-
class Manager extends Base {
|
163
|
+
```javascript readonly
|
164
|
+
class Manager extends core.Base {
|
158
165
|
// ...
|
159
166
|
|
160
167
|
createWorkers() {
|
@@ -198,24 +205,20 @@ class Manager extends Base {
|
|
198
205
|
if (me.constructedThreads === me.activeWorkers) {
|
199
206
|
// All workers are constructed, load the application
|
200
207
|
NeoConfig.appPath && me.timeout(NeoConfig.loadApplicationDelay).then(() => {
|
201
|
-
me.loadApplication(
|
208
|
+
me.loadApplication()
|
202
209
|
})
|
203
210
|
}
|
204
211
|
}
|
205
212
|
|
206
|
-
loadApplication(
|
207
|
-
this.sendMessage('app', {
|
208
|
-
action : 'loadApplication',
|
209
|
-
path,
|
210
|
-
resourcesPath: NeoConfig.resourcesPath
|
211
|
-
})
|
213
|
+
loadApplication() {
|
214
|
+
this.sendMessage('app', {action: 'loadApplication' })
|
212
215
|
}
|
213
216
|
|
214
217
|
// ...
|
215
218
|
}
|
216
219
|
```
|
217
220
|
|
218
|
-
|
221
|
+
`Neo.worker.Manager`:
|
219
222
|
1. Detects browser features (Web Workers, SharedWorkers)
|
220
223
|
2. Creates workers for App, VDom, Data, etc. based on configuration
|
221
224
|
3. Sends the Neo.config to each worker
|
@@ -227,7 +230,7 @@ The App worker receives the 'loadApplication' message and loads the application.
|
|
227
230
|
in Neo.mjs is an instance of Neo.controller.Application, which is not common in other frameworks like React, Angular,
|
228
231
|
or Vue (which typically just use a tag):
|
229
232
|
|
230
|
-
```javascript
|
233
|
+
```javascript readonly
|
231
234
|
class App extends Base {
|
232
235
|
// ...
|
233
236
|
|
@@ -262,12 +265,7 @@ class App extends Base {
|
|
262
265
|
path = path.slice(0, -4)
|
263
266
|
}
|
264
267
|
|
265
|
-
return import(
|
266
|
-
/* webpackInclude: /(?:\/|\\)app.mjs$/ */
|
267
|
-
/* webpackExclude: /(?:\/|\\)(dist|node_modules)/ */
|
268
|
-
/* webpackMode: "lazy" */
|
269
|
-
`../../${path}.mjs`
|
270
|
-
)
|
268
|
+
return import(`../../${path}.mjs`)
|
271
269
|
}
|
272
270
|
|
273
271
|
// ...
|
@@ -284,8 +282,8 @@ The App worker:
|
|
284
282
|
|
285
283
|
Finally, the application's `app.mjs` file is loaded and executed:
|
286
284
|
|
287
|
-
```javascript
|
288
|
-
import Overwrites from './Overwrites.mjs';
|
285
|
+
```javascript readonly
|
286
|
+
import Overwrites from './Overwrites.mjs'; // Optional class config default value changes for framework classes
|
289
287
|
import Viewport from './view/Viewport.mjs'; // Your main UI component
|
290
288
|
|
291
289
|
export const onStart = () => Neo.app({
|
@@ -303,7 +301,7 @@ The app.mjs file:
|
|
303
301
|
|
304
302
|
When Neo.app() is called, it creates an Application controller and instantiates your mainView component:
|
305
303
|
|
306
|
-
```javascript
|
304
|
+
```javascript readonly
|
307
305
|
// Your Viewport component
|
308
306
|
class Viewport extends Container {
|
309
307
|
static config = {
|
@@ -25,7 +25,7 @@ primitive. Components introduce various properties, such as `width`, `height`, `
|
|
25
25
|
|
26
26
|
Here's a container, with one child item.
|
27
27
|
|
28
|
-
|
28
|
+
```javascript live-preview
|
29
29
|
import Container from '../container/Base.mjs';
|
30
30
|
|
31
31
|
class MainView extends Container {
|
@@ -42,12 +42,12 @@ class MainView extends Container {
|
|
42
42
|
}
|
43
43
|
|
44
44
|
MainView = Neo.setupClass(MainView);
|
45
|
-
|
45
|
+
```
|
46
46
|
|
47
47
|
Components also have an `html`. The `html` property is rarely used, and goes against the abstract philosophy of Neo.mjs, but
|
48
48
|
sometimes it's handy as a placeholder as you stub out views.
|
49
49
|
|
50
|
-
|
50
|
+
```javascript live-preview
|
51
51
|
import Container from '../container/Base.mjs';
|
52
52
|
|
53
53
|
class MainView extends Container {
|
@@ -65,7 +65,7 @@ class MainView extends Container {
|
|
65
65
|
}
|
66
66
|
|
67
67
|
MainView = Neo.setupClass(MainView);
|
68
|
-
|
68
|
+
```
|
69
69
|
|
70
70
|
|
71
71
|
## Layout
|
@@ -77,7 +77,7 @@ some commonly-used layouts.
|
|
77
77
|
|
78
78
|
Fix is used when there's a single child. The component is sized to fit the container.
|
79
79
|
|
80
|
-
|
80
|
+
```javascript live-preview
|
81
81
|
import Container from '../container/Base.mjs';
|
82
82
|
|
83
83
|
class MainView extends Container {
|
@@ -92,13 +92,13 @@ class MainView extends Container {
|
|
92
92
|
}
|
93
93
|
|
94
94
|
MainView = Neo.setupClass(MainView);
|
95
|
-
|
95
|
+
```
|
96
96
|
|
97
97
|
### Vbox and hbox
|
98
98
|
|
99
99
|
With `vbox` and `hbox`, items are arranged vertically or horizontally.
|
100
100
|
|
101
|
-
|
101
|
+
```javascript live-preview
|
102
102
|
import Button from '../button/Base.mjs';
|
103
103
|
import Container from '../container/Base.mjs';
|
104
104
|
|
@@ -119,13 +119,13 @@ class MainView extends Container {
|
|
119
119
|
}
|
120
120
|
|
121
121
|
MainView = Neo.setupClass(MainView);
|
122
|
-
|
122
|
+
```
|
123
123
|
|
124
124
|
### Card
|
125
125
|
|
126
126
|
A card container has multiple child items, one of which is visible.
|
127
127
|
|
128
|
-
|
128
|
+
```javascript live-preview
|
129
129
|
import Button from '../button/Base.mjs';
|
130
130
|
import Container from '../container/Base.mjs';
|
131
131
|
|
@@ -167,7 +167,7 @@ class MainView extends Container {
|
|
167
167
|
}
|
168
168
|
|
169
169
|
MainView = Neo.setupClass(MainView);
|
170
|
-
|
170
|
+
```
|
171
171
|
|
172
172
|
|
173
173
|
|
@@ -177,7 +177,7 @@ MainView = Neo.setupClass(MainView);
|
|
177
177
|
Neo.mjs is class-based, and thus, any component or container can be defined as its own class, and reused like any
|
178
178
|
other component in the framework.
|
179
179
|
|
180
|
-
|
180
|
+
```javascript live-preview
|
181
181
|
import Button from '../button/Base.mjs';
|
182
182
|
// In practice this would be some handy reusable component
|
183
183
|
class MySpecialButton extends Button {
|
@@ -209,5 +209,5 @@ class MainView extends Container {
|
|
209
209
|
}
|
210
210
|
|
211
211
|
MainView = Neo.setupClass(MainView);
|
212
|
-
|
212
|
+
```
|
213
213
|
|
@@ -9,7 +9,7 @@ Neo.mjs is class-based, which means you're free to extend any component (or any
|
|
9
9
|
|
10
10
|
## Lifecycle config properties
|
11
11
|
|
12
|
-
|
12
|
+
```javascript live-preview
|
13
13
|
import Button from '../button/Base.mjs';
|
14
14
|
// In practice this would be some handy reusable component
|
15
15
|
class MySpecialButton extends Button {
|
@@ -41,5 +41,5 @@ class MainView extends Container {
|
|
41
41
|
}
|
42
42
|
|
43
43
|
Neo.setupClass(MainView);
|
44
|
-
|
44
|
+
```
|
45
45
|
|
@@ -18,10 +18,10 @@ please return a specified `window` property." Neo.mjs
|
|
18
18
|
lets you do that via `Neo.Main.getByPath()`. For
|
19
19
|
example, the following statement logs the URL query string.
|
20
20
|
|
21
|
-
|
21
|
+
```javascript readonly
|
22
22
|
const search = await Neo.Main.getByPath({path: 'window.location.search'});
|
23
23
|
console.log(search); // Logs the search string
|
24
|
-
|
24
|
+
```
|
25
25
|
|
26
26
|
`Neo.Main` & `Neo.main.DomAccess` provide some basic methods for accessing the
|
27
27
|
main thread, but in case you want to use a third party library which relies on directly
|
@@ -27,9 +27,9 @@ The setting will get stored inside the LocalStorage,
|
|
27
27
|
so you will need to click the following Button a 2nd time to deactivate it again.
|
28
28
|
Or you can clear the LocalStorage manually.</br></br>
|
29
29
|
|
30
|
-
|
30
|
+
```json neo-component
|
31
31
|
{
|
32
32
|
"className": "Portal.view.learn.CubeLayoutButton",
|
33
33
|
"style" : {"margin": 0}
|
34
34
|
}
|
35
|
-
|
35
|
+
```
|
@@ -10,7 +10,7 @@ Other libraries or frameworks often call state providers "Stores".
|
|
10
10
|
|
11
11
|
## Inline State Providers
|
12
12
|
### Direct Bindings
|
13
|
-
|
13
|
+
```javascript live-preview
|
14
14
|
import Button from '../button/Base.mjs';
|
15
15
|
import Container from '../container/Base.mjs';
|
16
16
|
import Label from '../component/Label.mjs';
|
@@ -49,7 +49,7 @@ class MainView extends Container {
|
|
49
49
|
}
|
50
50
|
}
|
51
51
|
MainView = Neo.setupClass(MainView);
|
52
|
-
|
52
|
+
```
|
53
53
|
|
54
54
|
We use a Container with a stateProvider containing the data props `hello` and `world`.
|
55
55
|
Inside the Container are 2 Labels which bind their `text` config to a data prop directly.
|
@@ -58,7 +58,7 @@ We can easily bind 1:1 to specific data props using the following syntax:</br>
|
|
58
58
|
`bind: {text: data => data.hello}`
|
59
59
|
|
60
60
|
### Bindings with multiple data props
|
61
|
-
|
61
|
+
```javascript live-preview
|
62
62
|
import Button from '../button/Base.mjs';
|
63
63
|
import Container from '../container/Base.mjs';
|
64
64
|
import Label from '../component/Label.mjs';
|
@@ -104,7 +104,7 @@ class MainView extends Container {
|
|
104
104
|
}
|
105
105
|
}
|
106
106
|
MainView = Neo.setupClass(MainView);
|
107
|
-
|
107
|
+
```
|
108
108
|
|
109
109
|
We use a Container with a stateProvider containing the data props `hello` and `world`.
|
110
110
|
Inside the Container are 3 Labels which bind their `text` config to a combination of both data props.
|
@@ -128,7 +128,7 @@ data.component equals to the Button instance itself. Since the Button instance d
|
|
128
128
|
`getStateProvider()` will return the closest stateProvider inside the parent chain.
|
129
129
|
|
130
130
|
### Nested Inline State Providers
|
131
|
-
|
131
|
+
```javascript live-preview
|
132
132
|
import Button from '../button/Base.mjs';
|
133
133
|
import Container from '../container/Base.mjs';
|
134
134
|
import Label from '../component/Label.mjs';
|
@@ -182,7 +182,7 @@ class MainView extends Container {
|
|
182
182
|
}
|
183
183
|
}
|
184
184
|
MainView = Neo.setupClass(MainView);
|
185
|
-
|
185
|
+
```
|
186
186
|
|
187
187
|
The output of this demo is supposed to exactly look the same like the previous demo.
|
188
188
|
|
@@ -203,7 +203,7 @@ We can even change data props which live inside different stateProviders at once
|
|
203
203
|
Hint: Modify the example code (Button handler) to try it out right away!
|
204
204
|
|
205
205
|
### Nested Data Properties
|
206
|
-
|
206
|
+
```javascript live-preview
|
207
207
|
import Button from '../button/Base.mjs';
|
208
208
|
import Container from '../container/Base.mjs';
|
209
209
|
import Label from '../component/Label.mjs';
|
@@ -244,7 +244,7 @@ class MainView extends Container {
|
|
244
244
|
}
|
245
245
|
}
|
246
246
|
MainView = Neo.setupClass(MainView);
|
247
|
-
|
247
|
+
```
|
248
248
|
Data props inside VMs can be nested. Our stateProvider contains a `user` data prop as an object,
|
249
249
|
which contains the nested props `firstname` and `lastname`.
|
250
250
|
|
@@ -262,7 +262,7 @@ Or we can directly pass the object containing the change(s):</br>
|
|
262
262
|
Hint: This will not override left out nested data props (lastname in this case).
|
263
263
|
|
264
264
|
### Dialog connecting to a Container
|
265
|
-
|
265
|
+
```javascript live-preview
|
266
266
|
import Controller from '../controller/Component.mjs';
|
267
267
|
import Dialog from '../dialog/Base.mjs';
|
268
268
|
import Panel from '../container/Panel.mjs';
|
@@ -378,13 +378,13 @@ class MainView extends Viewport {
|
|
378
378
|
}
|
379
379
|
|
380
380
|
MainView = Neo.setupClass(MainView);
|
381
|
-
|
381
|
+
```
|
382
382
|
|
383
383
|
## Class based State Providers
|
384
384
|
When your stateProviders contain many data props or need custom logic, you can easily move them into their own classes.
|
385
385
|
|
386
386
|
### Direct Bindings
|
387
|
-
|
387
|
+
```javascript live-preview
|
388
388
|
import Button from '../button/Base.mjs';
|
389
389
|
import Container from '../container/Base.mjs';
|
390
390
|
import Label from '../component/Label.mjs';
|
@@ -436,4 +436,4 @@ class MainView extends Container {
|
|
436
436
|
}
|
437
437
|
}
|
438
438
|
MainView = Neo.setupClass(MainView);
|
439
|
-
|
439
|
+
```
|
@@ -1,7 +1,7 @@
|
|
1
1
|
As you read in the <a href="#/learn/Events">Getting Started > Events</a> topic, components, stores, and many other objects fire events.
|
2
2
|
|
3
3
|
|
4
|
-
|
4
|
+
```javascript live-preview
|
5
5
|
import Container from '../container/Base.mjs';
|
6
6
|
import TextField from '../form/field/Text.mjs';
|
7
7
|
|
@@ -26,7 +26,7 @@ class MainView extends Container {
|
|
26
26
|
}
|
27
27
|
}
|
28
28
|
MainView = Neo.setupClass(MainView);
|
29
|
-
|
29
|
+
```
|
30
30
|
|
31
31
|
## Event listeners
|
32
32
|
|
@@ -35,7 +35,7 @@ MainView = Neo.setupClass(MainView);
|
|
35
35
|
The event listener function can be coded in-line. Normally you want event handlers to be in a view's
|
36
36
|
controller, but for very simple situation it can be convenient to use this syntax.
|
37
37
|
|
38
|
-
|
38
|
+
```javascript live-preview
|
39
39
|
import Container from '../container/Base.mjs';
|
40
40
|
import TextField from '../form/field/Text.mjs';
|
41
41
|
|
@@ -54,7 +54,7 @@ class MainView extends Container {
|
|
54
54
|
}
|
55
55
|
}
|
56
56
|
MainView = Neo.setupClass(MainView);
|
57
|
-
|
57
|
+
```
|
58
58
|
|
59
59
|
### As a view method
|
60
60
|
|
@@ -62,7 +62,7 @@ You can also use the `up.` qualifier to specify a method in the component's pare
|
|
62
62
|
in-line syntax you saw above, using the `up.` syntax might be convenient for simple classees,
|
63
63
|
or when you simply haven't gotten around to defining a view's controller.
|
64
64
|
|
65
|
-
|
65
|
+
```javascript live-preview
|
66
66
|
import Container from '../container/Base.mjs';
|
67
67
|
import TextField from '../form/field/Text.mjs';
|
68
68
|
|
@@ -84,7 +84,7 @@ class MainView extends Container {
|
|
84
84
|
}
|
85
85
|
}
|
86
86
|
MainView = Neo.setupClass(MainView);
|
87
|
-
|
87
|
+
```
|
88
88
|
|
89
89
|
### As a controller method
|
90
90
|
|
@@ -92,7 +92,7 @@ Despite the examples above, the most correct way of setting up event handlers is
|
|
92
92
|
Any view class can specify a controller — wWhen the view is created a controller instance is
|
93
93
|
also created.
|
94
94
|
|
95
|
-
|
95
|
+
```javascript live-preview
|
96
96
|
import Controller from '../controller/Component.mjs';
|
97
97
|
|
98
98
|
class MainViewController extends Controller {
|
@@ -125,7 +125,7 @@ class MainView extends Container {
|
|
125
125
|
}
|
126
126
|
}
|
127
127
|
MainView = Neo.setupClass(MainView);
|
128
|
-
|
128
|
+
```
|
129
129
|
|
130
130
|
## Adding listeners procedurally
|
131
131
|
|
@@ -134,7 +134,7 @@ a listener procedurally.
|
|
134
134
|
|
135
135
|
Any observable class has an `addListener` method, along with an easier-to-type version called `on`.
|
136
136
|
|
137
|
-
|
137
|
+
```javascript live-preview
|
138
138
|
import Controller from '../controller/Component.mjs';
|
139
139
|
|
140
140
|
class MainViewController extends Controller {
|
@@ -167,11 +167,11 @@ class MainView extends Container {
|
|
167
167
|
}
|
168
168
|
}
|
169
169
|
MainView = Neo.setupClass(MainView);
|
170
|
-
|
170
|
+
```
|
171
171
|
|
172
172
|
The method specified in `on()` doesn't have to be an arrow function; you can use a controller function.
|
173
173
|
|
174
|
-
|
174
|
+
```javascript live-preview
|
175
175
|
import Controller from '../controller/Component.mjs';
|
176
176
|
|
177
177
|
class MainViewController extends Controller {
|
@@ -208,7 +208,7 @@ class MainView extends Container {
|
|
208
208
|
}
|
209
209
|
}
|
210
210
|
MainView = Neo.setupClass(MainView);
|
211
|
-
|
211
|
+
```
|
212
212
|
|
213
213
|
## Events versus binding
|
214
214
|
|
@@ -241,7 +241,7 @@ will automatically be reflected in the view model.
|
|
241
241
|
To contrast syntax, and to illustrate the simplicity of a binding, let's look at two exmaples of updating a component
|
242
242
|
to reflect the value of a text field. THe first example uses events; the second uses bindings.
|
243
243
|
|
244
|
-
|
244
|
+
```javascript live-preview
|
245
245
|
import Component from '../component/Base.mjs';
|
246
246
|
import Container from '../container/Base.mjs';
|
247
247
|
import TextField from '../form/field/Text.mjs';
|
@@ -277,9 +277,9 @@ class MainView extends Container {
|
|
277
277
|
}
|
278
278
|
}
|
279
279
|
MainView = Neo.setupClass(MainView);
|
280
|
-
|
280
|
+
```
|
281
281
|
|
282
|
-
|
282
|
+
```javascript live-preview
|
283
283
|
import Component from '../component/Base.mjs';
|
284
284
|
import Container from '../container/Base.mjs';
|
285
285
|
import TextField from '../form/field/Text.mjs';
|
@@ -313,7 +313,7 @@ class MainView extends Container {
|
|
313
313
|
}
|
314
314
|
}
|
315
315
|
MainView = Neo.setupClass(MainView);
|
316
|
-
|
316
|
+
```
|
317
317
|
|
318
318
|
##How are events set up?
|
319
319
|
|
@@ -34,7 +34,7 @@ the class. If you add `console.log(this);`, the output is most likely not want y
|
|
34
34
|
For the second Button we are defining a non-bound function, in which case `this` will point
|
35
35
|
to the Component instance.
|
36
36
|
|
37
|
-
|
37
|
+
```javascript live-preview
|
38
38
|
import Container from '../container/Base.mjs';
|
39
39
|
|
40
40
|
class MainView extends Container {
|
@@ -62,7 +62,7 @@ class MainView extends Container {
|
|
62
62
|
}
|
63
63
|
}
|
64
64
|
MainView = Neo.setupClass(MainView);
|
65
|
-
|
65
|
+
```
|
66
66
|
|
67
67
|
### Handler inside the Component Tree
|
68
68
|
|
@@ -72,7 +72,7 @@ A good example would be `tab.header.Toolbar`, where clicking on a Button will ch
|
|
72
72
|
You can use string based listeners. In case the handler method lives within the parent tree (any level),
|
73
73
|
we need to prefix these listeners with `up.`.
|
74
74
|
|
75
|
-
|
75
|
+
```javascript live-preview
|
76
76
|
import Container from '../container/Base.mjs';
|
77
77
|
|
78
78
|
class MainView extends Container {
|
@@ -95,7 +95,7 @@ class MainView extends Container {
|
|
95
95
|
}
|
96
96
|
}
|
97
97
|
MainView = Neo.setupClass(MainView);
|
98
|
-
|
98
|
+
```
|
99
99
|
|
100
100
|
### Handler inside a ViewController
|
101
101
|
|
@@ -107,7 +107,7 @@ to find the closest match.
|
|
107
107
|
|
108
108
|
A good use case would be a form submit Button, where a click will trigger a communication to the backend.
|
109
109
|
|
110
|
-
|
110
|
+
```javascript live-preview
|
111
111
|
import Container from '../container/Base.mjs';
|
112
112
|
import Controller from '../controller/Component.mjs';
|
113
113
|
|
@@ -138,7 +138,7 @@ class MainView extends Container {
|
|
138
138
|
}
|
139
139
|
}
|
140
140
|
MainView = Neo.setupClass(MainView);
|
141
|
-
|
141
|
+
```
|
142
142
|
|
143
143
|
## Listener Options
|
144
144
|
|
@@ -146,7 +146,7 @@ MainView = Neo.setupClass(MainView);
|
|
146
146
|
|
147
147
|
We can further delegate listeners to specific DOM nodes within our Component:
|
148
148
|
|
149
|
-
|
149
|
+
```javascript live-preview
|
150
150
|
import Container from '../container/Base.mjs';
|
151
151
|
|
152
152
|
class MainView extends Container {
|
@@ -172,7 +172,7 @@ class MainView extends Container {
|
|
172
172
|
}
|
173
173
|
}
|
174
174
|
MainView = Neo.setupClass(MainView);
|
175
|
-
|
175
|
+
```
|
176
176
|
|
177
177
|
In case you click on the blue div, no console logs will appear.
|
178
178
|
They do, when clicking on the white inner div.
|
@@ -184,7 +184,7 @@ we will get logs when clicking on the blue div too.
|
|
184
184
|
|
185
185
|
We can prevent listeners from bubbling upwards:
|
186
186
|
|
187
|
-
|
187
|
+
```javascript live-preview
|
188
188
|
import Container from '../container/Base.mjs';
|
189
189
|
|
190
190
|
class MainView extends Container {
|
@@ -221,7 +221,7 @@ class MainView extends Container {
|
|
221
221
|
}
|
222
222
|
}
|
223
223
|
MainView = Neo.setupClass(MainView);
|
224
|
-
|
224
|
+
```
|
225
225
|
|
226
226
|
Clicking on the inner (white) div will only trigger the inner listener and you will get one log.
|
227
227
|
|
@@ -237,7 +237,7 @@ While we could just manually order the array inside the following example,
|
|
237
237
|
there can be use cases where multiple subscribers get added at run-time and developers
|
238
238
|
can not be sure about the adding order.
|
239
239
|
|
240
|
-
|
240
|
+
```javascript live-preview
|
241
241
|
import Container from '../container/Base.mjs';
|
242
242
|
|
243
243
|
class MainView extends Container {
|
@@ -257,7 +257,7 @@ class MainView extends Container {
|
|
257
257
|
}
|
258
258
|
}
|
259
259
|
MainView = Neo.setupClass(MainView);
|
260
|
-
|
260
|
+
```
|
261
261
|
|
262
262
|
Try it: In case you remove `priority: 2` inside the source view,
|
263
263
|
the order of the logs will change.
|
@@ -1,6 +1,7 @@
|
|
1
1
|
Neo.mjs uses standard modular JavaScript, so you're free to use other class
|
2
2
|
features, like private members.
|
3
|
-
|
3
|
+
|
4
|
+
```javascript readonly
|
4
5
|
class Human extends Mammal {
|
5
6
|
static config = {
|
6
7
|
className: 'Simple.example.Human',
|
@@ -33,4 +34,4 @@ const myPerson = Neo.create(Human, {
|
|
33
34
|
});
|
34
35
|
|
35
36
|
myPerson.speak(true);
|
36
|
-
|
37
|
+
```
|