neo.mjs 6.13.0 → 6.15.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/apps/ServiceWorker.mjs +2 -2
- package/apps/covid/neo-config.json +1 -1
- package/apps/covid/view/HeaderContainer.mjs +2 -2
- package/apps/form/view/pages/Page10.mjs +2 -2
- package/apps/portal/view/ViewportController.mjs +5 -4
- package/apps/portal/view/home/ContentBox.mjs +80 -0
- package/apps/portal/view/home/MainContainer.mjs +51 -15
- package/apps/portal/view/learn/ContentTreeList.mjs +10 -3
- package/apps/portal/view/learn/MainContainerController.mjs +37 -5
- package/apps/portal/view/learn/MainContainerModel.mjs +51 -7
- package/apps/portal/view/learn/PageContainer.mjs +21 -9
- package/apps/sharedcovid/neo-config.json +1 -1
- package/apps/sharedcovid/view/HeaderContainer.mjs +2 -2
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/button/base/MainContainer.mjs +2 -2
- package/examples/button/split/MainContainer.mjs +2 -2
- package/examples/component/process/MainContainer.mjs +3 -3
- package/examples/component/process/realWorldExample/MainContainer.mjs +15 -15
- package/examples/component/toast/MainContainer.mjs +4 -4
- package/examples/dialog/DemoDialog.mjs +4 -4
- package/examples/fieldWithPrefix/MainContainer.mjs +4 -5
- package/examples/form/field/{select → combobox}/MainContainer.mjs +7 -10
- package/examples/form/field/{select → combobox}/MainModel.mjs +4 -4
- package/examples/form/field/{select → combobox}/MainStore.mjs +2 -2
- package/examples/form/field/{select → combobox}/app.mjs +1 -1
- package/examples/form/field/{select → combobox}/index.html +1 -1
- package/examples/form/field/{select → combobox}/neo-config.json +1 -1
- package/examples/tableFiltering/MainContainer.mjs +2 -2
- package/package.json +4 -4
- package/resources/data/deck/learnneo/pages/2023-10-14T19-25-08-153Z.md +16 -1
- package/resources/data/deck/learnneo/pages/ComponentsAndContainers.md +180 -0
- package/resources/data/deck/learnneo/pages/Config.md +11 -4
- package/resources/data/deck/learnneo/pages/DescribingTheUI.md +6 -0
- package/resources/data/deck/learnneo/pages/Earthquakes.md +36 -9
- package/resources/data/deck/learnneo/pages/Events.md +55 -43
- package/resources/data/deck/learnneo/pages/GuideEvents.md +9 -8
- package/resources/data/deck/learnneo/pages/References.md +14 -7
- package/resources/data/deck/learnneo/pages/TodoList.md +241 -0
- package/resources/data/deck/learnneo/pages/WhyNeo-Quick.md +6 -11
- package/resources/data/deck/learnneo/tree.json +2 -0
- package/resources/scss/src/apps/portal/home/ContentBox.scss +26 -0
- package/resources/scss/src/apps/portal/home/MainContainer.scss +4 -12
- package/resources/scss/src/apps/portal/learn/MainContainer.scss +0 -7
- package/resources/scss/src/apps/portal/learn/PageContainer.scss +35 -0
- package/resources/scss/src/apps/portal/learn/PageSectionsPanel.scss +8 -0
- package/resources/scss/src/form/field/{Select.scss → ComboBox.scss} +8 -8
- package/resources/scss/theme-dark/form/field/ComboBox.scss +9 -0
- package/resources/scss/theme-light/form/field/ComboBox.scss +9 -0
- package/resources/scss/theme-neo-light/form/field/ComboBox.scss +9 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/component/Base.mjs +16 -1
- package/src/container/Viewport.mjs +5 -2
- package/src/controller/Application.mjs +12 -1
- package/src/controller/Base.mjs +15 -4
- package/src/controller/Component.mjs +5 -1
- package/src/core/Observable.mjs +62 -22
- package/src/form/field/Base.mjs +21 -9
- package/src/form/field/Chip.mjs +3 -3
- package/src/form/field/Color.mjs +3 -3
- package/src/form/field/{Select.mjs → ComboBox.mjs} +179 -130
- package/src/form/field/Country.mjs +3 -3
- package/src/form/field/Text.mjs +7 -10
- package/src/form/field/_export.mjs +2 -2
- package/src/main/DomEvents.mjs +2 -1
- package/src/main/addon/MonacoEditor.mjs +2 -2
- package/src/main/addon/Navigator.mjs +27 -24
- package/src/selection/ListModel.mjs +13 -14
- package/src/selection/Model.mjs +10 -10
- package/src/toolbar/Paging.mjs +2 -2
- package/src/util/HashHistory.mjs +1 -0
- package/src/worker/App.mjs +5 -1
- package/src/worker/Manager.mjs +14 -7
- package/test/components/app.mjs +1 -1
- package/test/components/files/form/field/{Select.mjs → ComboBox.mjs} +9 -7
- package/test/components/siesta.js +1 -1
- package/resources/scss/theme-dark/form/field/Select.scss +0 -9
- package/resources/scss/theme-light/form/field/Select.scss +0 -9
- package/resources/scss/theme-neo-light/form/field/Select.scss +0 -9
@@ -1,10 +1,10 @@
|
|
1
1
|
import Button from '../../../src/button/Base.mjs';
|
2
2
|
import CheckBox from '../../../src/form/field/CheckBox.mjs';
|
3
|
+
import ComboBox from '../../../src/form/field/ComboBox.mjs';
|
3
4
|
import Component from '../../../src/component/Base.mjs';
|
4
5
|
import FormContainer from '../../../src/form/Container.mjs';
|
5
6
|
import MainContainerController from './MainContainerController.mjs';
|
6
7
|
import NumberField from '../../../src/form/field/Number.mjs';
|
7
|
-
import SelectField from '../../../src/form/field/Select.mjs';
|
8
8
|
import TextField from '../../../src/form/field/Text.mjs';
|
9
9
|
import Viewport from '../../../src/container/Viewport.mjs';
|
10
10
|
|
@@ -51,19 +51,19 @@ class MainContainer extends Viewport {
|
|
51
51
|
labelText: 'iconCls',
|
52
52
|
name : 'iconCls'
|
53
53
|
}, {
|
54
|
-
module :
|
54
|
+
module : ComboBox,
|
55
55
|
labelText : 'position = tr',
|
56
56
|
name : 'position',
|
57
57
|
store : {data: [{name: 'tl'}, {name: 'tc'}, {name: 'tr'}, {name: 'bl'}, {name: 'bc'}, {name: 'br'}]},
|
58
58
|
valueField: 'name'
|
59
59
|
}, {
|
60
|
-
module :
|
60
|
+
module : ComboBox,
|
61
61
|
labelText: 'slideDirection = right',
|
62
62
|
name : 'slideDirection',
|
63
63
|
store : {data: [{name: 'down'}, {name: 'up'}, {name: 'left'}, {name: 'right'}]},
|
64
64
|
valueField: 'name'
|
65
65
|
}, {
|
66
|
-
module :
|
66
|
+
module : ComboBox,
|
67
67
|
labelText: 'ui = info',
|
68
68
|
name : 'ui',
|
69
69
|
store : {data: [{name: 'info'}, {name: 'danger'}, {name: 'success'}]},
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import Button
|
2
|
-
import
|
3
|
-
import
|
1
|
+
import Button from '../../src/button/Base.mjs';
|
2
|
+
import ComboBox from '../../src/form/field/ComboBox.mjs';
|
3
|
+
import Dialog from '../../src/dialog/Base.mjs';
|
4
4
|
|
5
5
|
/**
|
6
6
|
* @class Neo.examples.dialog.DemoDialog
|
@@ -57,7 +57,7 @@ class DemoDialog extends Dialog {
|
|
57
57
|
const me = this;
|
58
58
|
|
59
59
|
me.items = [{
|
60
|
-
module :
|
60
|
+
module : ComboBox,
|
61
61
|
labelText : 'Select',
|
62
62
|
labelWidth: 80,
|
63
63
|
|
@@ -1,8 +1,7 @@
|
|
1
|
+
import ComboBox from '../../src/form/field/ComboBox.mjs';
|
1
2
|
import ConfigurationViewport from '../ConfigurationViewport.mjs';
|
2
|
-
|
3
|
-
import
|
4
|
-
import SelectField from '../../src/form/field/Select.mjs';
|
5
|
-
import TextField from '../../src/form/field/Text.mjs';
|
3
|
+
import PrefixPlugin from '../../src/plugin/PrefixField.mjs';
|
4
|
+
import TextField from '../../src/form/field/Text.mjs';
|
6
5
|
|
7
6
|
/**
|
8
7
|
* @class Neo.examples.fieldWithPrefix.MainContainer
|
@@ -50,7 +49,7 @@ class MainContainer extends ConfigurationViewport {
|
|
50
49
|
value : '_',
|
51
50
|
style : {marginTop: '10px'}
|
52
51
|
}, {
|
53
|
-
module:
|
52
|
+
module: ComboBox,
|
54
53
|
store : {
|
55
54
|
model: {fields: [{name: 'id'}, {name: 'name'}, {name: 'value'}]},
|
56
55
|
data : [
|
@@ -1,19 +1,18 @@
|
|
1
1
|
import CheckBox from '../../../../src/form/field/CheckBox.mjs';
|
2
|
+
import ComboBox from '../../../../src/form/field/ComboBox.mjs';
|
2
3
|
import ConfigurationViewport from '../../../ConfigurationViewport.mjs';
|
3
4
|
import MainStore from './MainStore.mjs';
|
4
5
|
import NumberField from '../../../../src/form/field/Number.mjs';
|
5
|
-
import SelectField from '../../../../src/form/field/Select.mjs';
|
6
6
|
import Radio from '../../../../src/form/field/Radio.mjs';
|
7
7
|
import TextField from '../../../../src/form/field/Text.mjs';
|
8
8
|
|
9
9
|
/**
|
10
|
-
* @class Neo.examples.form.field.
|
10
|
+
* @class Neo.examples.form.field.combobox.MainContainer
|
11
11
|
* @extends Neo.examples.ConfigurationViewport
|
12
12
|
*/
|
13
13
|
class MainContainer extends ConfigurationViewport {
|
14
14
|
static config = {
|
15
|
-
className : 'Neo.examples.form.field.
|
16
|
-
autoMount : true,
|
15
|
+
className : 'Neo.examples.form.field.combobox.MainContainer',
|
17
16
|
configItemLabelWidth : 160,
|
18
17
|
exampleContainerConfig: {style: {position: 'relative'}}
|
19
18
|
}
|
@@ -160,17 +159,15 @@ class MainContainer extends ConfigurationViewport {
|
|
160
159
|
|
161
160
|
createExampleComponent() {
|
162
161
|
return Neo.create({
|
163
|
-
module :
|
162
|
+
module : ComboBox,
|
164
163
|
labelPosition: 'inline',
|
165
164
|
labelText : 'US States',
|
166
165
|
labelWidth : 80,
|
166
|
+
pickerConfig : {minHeight : '6em'},
|
167
167
|
store : MainStore,
|
168
|
-
value : '
|
168
|
+
value : 'AZ',
|
169
169
|
valueField : 'abbreviation',
|
170
|
-
width : '50%'
|
171
|
-
pickerConfig : {
|
172
|
-
minHeight : '6em'
|
173
|
-
}
|
170
|
+
width : '50%'
|
174
171
|
})
|
175
172
|
}
|
176
173
|
}
|
@@ -1,20 +1,20 @@
|
|
1
1
|
import Model from '../../../../src/data/Model.mjs';
|
2
2
|
|
3
3
|
/**
|
4
|
-
* @class Neo.examples.form.field.
|
4
|
+
* @class Neo.examples.form.field.combobox.MainModel
|
5
5
|
* @extends Neo.data.Model
|
6
6
|
*/
|
7
7
|
class MainModel extends Model {
|
8
8
|
static config = {
|
9
|
-
className : 'Neo.examples.form.field.
|
9
|
+
className : 'Neo.examples.form.field.combobox.MainModel',
|
10
10
|
keyProperty: 'abbreviation',
|
11
11
|
|
12
12
|
fields: [{
|
13
13
|
name: 'abbreviation',
|
14
|
-
type: '
|
14
|
+
type: 'String'
|
15
15
|
}, {
|
16
16
|
name: 'name',
|
17
|
-
type: '
|
17
|
+
type: 'String'
|
18
18
|
}]
|
19
19
|
}
|
20
20
|
}
|
@@ -2,12 +2,12 @@ import Store from '../../../../src/data/Store.mjs';
|
|
2
2
|
import Model from './MainModel.mjs';
|
3
3
|
|
4
4
|
/**
|
5
|
-
* @class Neo.examples.form.field.
|
5
|
+
* @class Neo.examples.form.field.combobox.MainStore
|
6
6
|
* @extends Neo.data.Store
|
7
7
|
*/
|
8
8
|
class MainStore extends Store {
|
9
9
|
static config = {
|
10
|
-
className : 'Neo.examples.form.field.
|
10
|
+
className : 'Neo.examples.form.field.combobox.MainStore',
|
11
11
|
autoLoad : true,
|
12
12
|
keyProperty: 'abbreviation',
|
13
13
|
model : Model,
|
@@ -1,11 +1,11 @@
|
|
1
1
|
import BooleanContainer from '../../src/filter/BooleanContainer.mjs';
|
2
2
|
import CellModel from '../../src/selection/table/CellModel.mjs';
|
3
3
|
import CheckBox from '../../src/form/field/CheckBox.mjs';
|
4
|
+
import ComboBox from '../../src/form/field/ComboBox.mjs';
|
4
5
|
import DateContainer from '../../src/filter/DateContainer.mjs';
|
5
6
|
import DateUtil from '../../src/util/Date.mjs';
|
6
7
|
import MainStore from './MainStore.mjs';
|
7
8
|
import NumberContainer from '../../src/filter/NumberContainer.mjs';
|
8
|
-
import SelectField from '../../src/form/field/Select.mjs';
|
9
9
|
import TableContainer from '../../src/table/Container.mjs';
|
10
10
|
import Viewport from '../../src/container/Viewport.mjs';
|
11
11
|
|
@@ -64,7 +64,7 @@ class MainContainer extends Viewport {
|
|
64
64
|
text : 'Country',
|
65
65
|
|
66
66
|
editorConfig: {
|
67
|
-
module:
|
67
|
+
module: ComboBox,
|
68
68
|
|
69
69
|
store: {
|
70
70
|
autoLoad : true,
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
{
|
3
3
|
"name": "neo.mjs",
|
4
|
-
"version": "6.
|
4
|
+
"version": "6.15.0",
|
5
5
|
"description": "The webworkers driven UI framework",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
@@ -53,13 +53,13 @@
|
|
53
53
|
"envinfo": "^7.11.1",
|
54
54
|
"fs-extra": "^11.2.0",
|
55
55
|
"highlightjs-line-numbers.js": "^2.8.0",
|
56
|
-
"inquirer": "^9.2.
|
56
|
+
"inquirer": "^9.2.16",
|
57
57
|
"marked": "^12.0.1",
|
58
58
|
"monaco-editor": "^0.47.0",
|
59
59
|
"neo-jsdoc": "1.0.1",
|
60
60
|
"neo-jsdoc-x": "1.0.5",
|
61
|
-
"postcss": "^8.4.
|
62
|
-
"sass": "^1.
|
61
|
+
"postcss": "^8.4.37",
|
62
|
+
"sass": "^1.72.0",
|
63
63
|
"siesta-lite": "5.5.2",
|
64
64
|
"url": "^0.11.3",
|
65
65
|
"webpack": "^5.90.3",
|
@@ -1,3 +1,5 @@
|
|
1
|
+
## Introduction
|
2
|
+
|
1
3
|
The purpose of this tutorial is to let you see the structure of a Neo.mjs workspace,
|
2
4
|
and the structure of an application.
|
3
5
|
|
@@ -5,7 +7,12 @@ If you wish, you can create a workspace by following the directions in the previ
|
|
5
7
|
|
6
8
|
<img src="https://raw.githubusercontent.com/neomjs/pages/main/resources/images/apps/learnneo/NeoWorkspace.png" style="height: 400px;">
|
7
9
|
|
8
|
-
As you can see, a Neo.mjs workspace is a conventional npm package.
|
10
|
+
As you can see, a Neo.mjs workspace is a conventional npm package.
|
11
|
+
|
12
|
+
|
13
|
+
## Browsing the workspace
|
14
|
+
|
15
|
+
If you run
|
9
16
|
the script `npm run server-start` from the workspace, Neo.mjs launches a web
|
10
17
|
server whose doc root is the workspace.
|
11
18
|
|
@@ -14,6 +21,8 @@ server whose doc root is the workspace.
|
|
14
21
|
If you drill down into the `src` directory you'll see your applications.
|
15
22
|
The `docs` directory holds the Neo.mjs API docs.
|
16
23
|
|
24
|
+
## The structure of a simple app
|
25
|
+
|
17
26
|
In order to discuss the structure of an app, we'll create a simple starter
|
18
27
|
app vis this script, run from the workspace. The script prompts for various
|
19
28
|
application settings.
|
@@ -29,6 +38,8 @@ These files are part of the typical structure of a Neo.mjs application. The file
|
|
29
38
|
You will, however, edit the main container, and its associated "controller" and "model",
|
30
39
|
as well as create new views classes, their controllers, and other application logic.
|
31
40
|
|
41
|
+
## Some source code
|
42
|
+
|
32
43
|
Now let's look at a source file. This is the contents of `MainView.mjs`.
|
33
44
|
|
34
45
|
<pre data-javascript>
|
@@ -61,6 +72,8 @@ This view also has a "controller" and "model". We'll talk about those later, but
|
|
61
72
|
a controller is where event handling and app logic goes, and a model is where you set up shared
|
62
73
|
bindable data.
|
63
74
|
|
75
|
+
## Adding a button to the view
|
76
|
+
|
64
77
|
We'll go into a lot more depth about view, controllers, and models in other topics, but to let
|
65
78
|
you see how a component is configured let's put a button in the container.
|
66
79
|
|
@@ -103,6 +116,8 @@ some value."
|
|
103
116
|
In another topic you'll learn about the Neo.mjs config system and declaratively describing views,
|
104
117
|
controllers, and other things.
|
105
118
|
|
119
|
+
## A running example
|
120
|
+
|
106
121
|
Here's a simplified running example. The `model` and `controller` are omitted, because they aren't
|
107
122
|
actually used in the example, and the import root path is different to reflect the location of the
|
108
123
|
Neo.mjs library relative to the examples.
|
@@ -0,0 +1,180 @@
|
|
1
|
+
## Introduction
|
2
|
+
|
3
|
+
Neo.mjs views are made up of components and containers.
|
4
|
+
|
5
|
+
A component is a visual widget, such as a button, label, or text field. A container is a visual
|
6
|
+
collection of components.
|
7
|
+
|
8
|
+
`Neo.component.Base` is the base class for all components. It introduces some common features, such as
|
9
|
+
event handling, binding, and some life-cycle methods.
|
10
|
+
|
11
|
+
`Neo.container.Base` is the base class for all containers. Containers are also components.
|
12
|
+
|
13
|
+
## Neo.container.Base
|
14
|
+
|
15
|
+
Containers are commonly used, although there are many specialized sub-classes, such as panels and toolbars.
|
16
|
+
|
17
|
+
|
18
|
+
Containers have two key properties:
|
19
|
+
|
20
|
+
- `items`, which are the components within the container, and
|
21
|
+
- `layout`, which describes how the items are arranged
|
22
|
+
|
23
|
+
## Neo.component.Base
|
24
|
+
|
25
|
+
The component base class introduces common component features, but is rarely used itself because it's so
|
26
|
+
primitive. Components introduce various properties, such as `width`, `height`, `cls` (to specify CSS classes for the component).
|
27
|
+
|
28
|
+
Here's a container, with one child item.
|
29
|
+
|
30
|
+
<pre data-neo>
|
31
|
+
import Container from '../../../../src/container/Base.mjs';
|
32
|
+
|
33
|
+
class MainView extends Container {
|
34
|
+
static config = {
|
35
|
+
className: 'Example.view.MainView',
|
36
|
+
layout : {ntype:'vbox', align:'start'},
|
37
|
+
items : [{
|
38
|
+
ntype : 'component', // Or module:Component
|
39
|
+
style : {border: 'thin solid red;'}, // Styling is usually done via "cls"
|
40
|
+
height: 100,
|
41
|
+
width : 200
|
42
|
+
}]
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
Neo.setupClass(MainView);
|
47
|
+
</pre>
|
48
|
+
|
49
|
+
Components also have an `html`. The `html` property is rarely used, and goes against the abstract philosophy of Neo.mjs, but
|
50
|
+
sometimes it's handy as a placeholder as you stub out views.
|
51
|
+
|
52
|
+
<pre data-neo>
|
53
|
+
import Container from '../../../../src/container/Base.mjs';
|
54
|
+
|
55
|
+
class MainView extends Container {
|
56
|
+
static config = {
|
57
|
+
className: 'Example.view.MainView',
|
58
|
+
layout : {ntype:'vbox', align:'start'},
|
59
|
+
items : [{
|
60
|
+
ntype : 'component', // Or module:Component
|
61
|
+
style : {border: 'thin solid red;'}, // Styling is usually done via "cls"
|
62
|
+
html : 'This is a placeholder for a more sophisticated component we\'ll add later.',
|
63
|
+
height: 100,
|
64
|
+
width : 200
|
65
|
+
}]
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
Neo.setupClass(MainView);
|
70
|
+
</pre>
|
71
|
+
|
72
|
+
|
73
|
+
## Layout
|
74
|
+
|
75
|
+
The `layout` config specifies how components are arranged within a container. Here are examples of
|
76
|
+
some commonly-used layouts.
|
77
|
+
|
78
|
+
### Fit layout
|
79
|
+
|
80
|
+
Fix is used when there's a single child. The component is sized to fit the container.
|
81
|
+
|
82
|
+
<pre data-neo>
|
83
|
+
import Container from '../../../../src/container/Base.mjs';
|
84
|
+
|
85
|
+
class MainView extends Container {
|
86
|
+
static config = {
|
87
|
+
className: 'Example.view.MainView',
|
88
|
+
layout : 'fit', // If no configs are needed, simply use the ntype of the layout
|
89
|
+
items : [{
|
90
|
+
ntype: 'component',
|
91
|
+
style: {backgroundColor: 'lightgreen'}, // The camel-cased property converts to the hyphenated css style
|
92
|
+
}]
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
Neo.setupClass(MainView);
|
97
|
+
</pre>
|
98
|
+
|
99
|
+
### Vbox and hbox
|
100
|
+
|
101
|
+
Items are arranged vertically or horizontally. On-axis and off-axis alignment can be specified.
|
102
|
+
|
103
|
+
<pre data-neo>
|
104
|
+
import Button from '../../../../src/button/Base.mjs';
|
105
|
+
import Container from '../../../../src/container/Base.mjs';
|
106
|
+
|
107
|
+
class MainView extends Container {
|
108
|
+
static config = {
|
109
|
+
className: 'Example.view.MainView',
|
110
|
+
layout : {ntype:'vbox', align:'start'}, // Change the ntype to 'hbox'
|
111
|
+
items : [{
|
112
|
+
module : Button,
|
113
|
+
iconCls: 'fa fa-home',
|
114
|
+
text : 'Home'
|
115
|
+
}, {
|
116
|
+
module : Button,
|
117
|
+
iconCls: 'fa fa-star',
|
118
|
+
text : 'Star'
|
119
|
+
}]
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
Neo.setupClass(MainView);
|
124
|
+
</pre>
|
125
|
+
|
126
|
+
### Card
|
127
|
+
|
128
|
+
Having multiple child items, one of which is visible.
|
129
|
+
|
130
|
+
<pre data-neo>
|
131
|
+
import Button from '../../../../src/button/Base.mjs';
|
132
|
+
import Base from '../../../../src/container/Base.mjs';
|
133
|
+
|
134
|
+
class MainView extends Base {
|
135
|
+
static config = {
|
136
|
+
className: 'Example.view.MainView',
|
137
|
+
layout : 'vbox',
|
138
|
+
items : [{
|
139
|
+
ntype: 'toolbar',
|
140
|
+
dock : 'top',
|
141
|
+
items: [{
|
142
|
+
ntype: 'button',
|
143
|
+
text: 'Click me to cycle through the cards',
|
144
|
+
ui: 'ghost',
|
145
|
+
iconCls: 'fa fa-chevron-right',
|
146
|
+
iconPosition: 'right',
|
147
|
+
handler: data => {
|
148
|
+
const container = data.component.up('container').getReference('cardContainer');
|
149
|
+
container.layout.activeIndex = (container.layout.activeIndex +1) % container.items.length;
|
150
|
+
}
|
151
|
+
}]
|
152
|
+
}, {
|
153
|
+
ntype: 'container',
|
154
|
+
reference: 'cardContainer',
|
155
|
+
layout: 'card',
|
156
|
+
flex: 1,
|
157
|
+
items: [{
|
158
|
+
ntype : 'component',
|
159
|
+
style: {backgroundColor: 'lightsalmon'}, // The camel-cased property converts to the hyphated css style
|
160
|
+
}, {
|
161
|
+
ntype : 'component',
|
162
|
+
style: {backgroundColor: 'darkseagreen'} // https://drafts.csswg.org/css-color/#named-colors
|
163
|
+
}, {
|
164
|
+
ntype : 'component',
|
165
|
+
style: {backgroundColor: 'cornflowerblue'} // Who came up with these names?
|
166
|
+
}]
|
167
|
+
}]
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
Neo.setupClass(MainView);
|
172
|
+
</pre>
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
## Reusing containers
|
178
|
+
|
179
|
+
|
180
|
+
## Lifecycle methods
|
@@ -1,9 +1,13 @@
|
|
1
|
+
## Introduction
|
2
|
+
|
1
3
|
As you've probably noticed, Neo.mjs classes have a `static config` property.
|
2
4
|
|
3
5
|
The config describes properties you can specify as you create an instance of the class.
|
4
6
|
Any config in the class, or its ancestors, can be specified.
|
5
7
|
|
6
|
-
|
8
|
+
## Simple properties and lifecycle properties
|
9
|
+
|
10
|
+
In addition, Neo.mjs uses that information to set up property lifecycle
|
7
11
|
methods.
|
8
12
|
|
9
13
|
Here's an example of a new component class `Simple` with three config properties:
|
@@ -12,6 +16,9 @@ Here's an example of a new component class `Simple` with three config properties
|
|
12
16
|
2. `foo` — an instance property
|
13
17
|
2. `bar_` — another instance property
|
14
18
|
|
19
|
+
The `Simple` class introduces syntax. It doesn't have any content, so if you run the code you won't
|
20
|
+
see anything. We'll change that in the next example.
|
21
|
+
|
15
22
|
<pre data-neo>
|
16
23
|
import Component from '../../../../src/component/Base.mjs';
|
17
24
|
import Container from '../../../../src/container/Base.mjs';
|
@@ -46,8 +53,7 @@ class MainView extends Container {
|
|
46
53
|
Neo.setupClass(MainView);
|
47
54
|
</pre>
|
48
55
|
|
49
|
-
|
50
|
-
change that in the next example.
|
56
|
+
## Detecting when a value changes
|
51
57
|
|
52
58
|
Note that the `bar` property is defined with an underscore at the end. That tags the property as
|
53
59
|
a _lifecyle property_. A lifecycle property provides methods that are run as the property is
|
@@ -75,7 +81,6 @@ class Simple extends Component {
|
|
75
81
|
}
|
76
82
|
afterSetBar(value, oldValue){
|
77
83
|
this.html = value;
|
78
|
-
this.fire('barChange', {component: this, value, oldValue});
|
79
84
|
}
|
80
85
|
|
81
86
|
}
|
@@ -103,6 +108,8 @@ This time if you run the code you'll see "hi there" in the view. That's because
|
|
103
108
|
configured with `bar: 'hi there'`, and since that's a lifecycle property the `afterSetBar()` method
|
104
109
|
is run. That method updates the view with the passed value.
|
105
110
|
|
111
|
+
## Firing an event when a value changes
|
112
|
+
|
106
113
|
Typically, the _afterSet_ method is used to update a view or to fire an event.
|
107
114
|
|
108
115
|
Look at this code: `afterSetBar()` fires an event, and the config in the `items[]` is listening to it.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
## Introduction
|
2
|
+
|
1
3
|
A Neo.mjs view is comprised of components and containers. A component is a visual widget, like a button,
|
2
4
|
and a container is a visual collection of components.
|
3
5
|
|
@@ -8,6 +10,8 @@ have a few key configs, including `text` and `iconCls`. The configs are properti
|
|
8
10
|
use to describe the component you're creating> You can also access or set the properties dynamically.
|
9
11
|
|
10
12
|
|
13
|
+
## A view with one component
|
14
|
+
|
11
15
|
<pre data-neo>
|
12
16
|
import Button from '../../../../src/button/Base.mjs';
|
13
17
|
import Container from '../../../../src/container/Base.mjs';
|
@@ -42,6 +46,8 @@ Containers also have a `layout` property, which describes how the items are arra
|
|
42
46
|
|
43
47
|
Let's put a second button in the container.
|
44
48
|
|
49
|
+
## A view with two components
|
50
|
+
|
45
51
|
<pre data-neo>
|
46
52
|
import Button from '../../../../src/button/Base.mjs';
|
47
53
|
import Container from '../../../../src/container/Base.mjs';
|
@@ -120,7 +120,7 @@ As you can see, `MicroLoader.mjs` runs `Main.mjs`, which in turn spawns the thre
|
|
120
120
|
- `neomjs-app-worker` is where app logic is run
|
121
121
|
|
122
122
|
Neo.mjs apps run in multiple webworkers, and each webworker is run in a separate parallel thread.
|
123
|
-
Parallel processing — along wih the efficient way the
|
123
|
+
Parallel processing — along wih the efficient way the vdom worker applies delta updates — is why Neo.mjs applications run so fast.
|
124
124
|
|
125
125
|
##Commonly-used Scripts
|
126
126
|
|
@@ -294,7 +294,7 @@ layout: {
|
|
294
294
|
|
295
295
|
## Debugging
|
296
296
|
|
297
|
-
At startup a Neo.mjs application launches three Web Workers:
|
297
|
+
At startup, a Neo.mjs application launches three Web Workers:
|
298
298
|
|
299
299
|
- neomjs-app-worker
|
300
300
|
- neomjs-data-worker
|
@@ -1153,7 +1153,7 @@ and each class is simpler than using complex source files that try to configure
|
|
1153
1153
|
|
1154
1154
|
<!-- /lab -->
|
1155
1155
|
|
1156
|
-
|
1156
|
+
## Google Maps Add-on
|
1157
1157
|
|
1158
1158
|
Neo.mjs has a Google Map component. This component is a little different than a button or table,
|
1159
1159
|
becauase it's implemented as a _main thread add-on_.
|
@@ -1169,14 +1169,10 @@ to also provide a wrapper class so it can be used like any other component withi
|
|
1169
1169
|
Maps is implemented: there's a main-thread add-on and a corresponding Neo.mjs component. The add-on is
|
1170
1170
|
specified in _neo-config.json_, and the component is imported and used like any other component.
|
1171
1171
|
|
1172
|
-
Ultimately, normal components are responsible for specifying how
|
1173
|
-
they're rendered (which is usually handled by Neo.mjs).
|
1174
|
-
|
1175
1172
|
How do you specify which main-thread add-ons you want? If you recall the script you used to create the starter
|
1176
1173
|
app, it has a step that asks what add-ons you want. That results in populating the `mainThreadAddons` property
|
1177
|
-
in `neo-config.json`. We didn't choose Google Maps when we ran the script, but we need it
|
1178
|
-
need to edit `neo-config.json
|
1179
|
-
`neo-config.json`.
|
1174
|
+
in `neo-config.json`. We didn't choose Google Maps when we ran the script, but we need it, which means we'll
|
1175
|
+
need to edit `neo-config.json`. Google Maps also requires an API key, which is also configured there.
|
1180
1176
|
|
1181
1177
|
The Google Maps component has a few key configs:
|
1182
1178
|
|
@@ -1193,6 +1189,20 @@ Marker store records are required to have these properties:
|
|
1193
1189
|
|
1194
1190
|
<!-- lab -->
|
1195
1191
|
|
1192
|
+
<details>
|
1193
|
+
<summary>Get the code for the custom add-on</summary>
|
1194
|
+
At the time this tutorial was written, the Neo.mjs Google Maps addon was about to be updated to
|
1195
|
+
accomodate Google's "AdvancedMarker" class. Until that's ready, we're going to use a modified version of the add-on.
|
1196
|
+
|
1197
|
+
Download and unzip this file, and copy the two source files to the corresponding subdirectories in
|
1198
|
+
your workspace's `src` directory. Note that `src` already contains some files, so don't replace the whole
|
1199
|
+
directory, but instead, move the files to their individual locations.
|
1200
|
+
|
1201
|
+
<a href="https://s3.amazonaws.com/mjs.neo.learning.images/zip/src.zip">src.zip</a>
|
1202
|
+
|
1203
|
+
<img src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/CopyGoogleMapsFiles.png" width="30%%"></img>
|
1204
|
+
</details>
|
1205
|
+
|
1196
1206
|
<details>
|
1197
1207
|
<summary>Specify the main-thread add-on</summary>
|
1198
1208
|
|
@@ -1215,6 +1225,10 @@ Edit `apps/earthquakes/neo-config.json` and add entries for the Google Maps add-
|
|
1215
1225
|
}
|
1216
1226
|
</pre>
|
1217
1227
|
|
1228
|
+
It's unusual to need to edit `neo-config.json`. The app theme is specified there, and so are main thread add-ons.
|
1229
|
+
In our case, we're adding `WS/GoogleMaps` which in turn requires that we specify the map key. The `WS/`
|
1230
|
+
prefix tells Neo.mjs that the add-on is in our workspace, rather than an add-on provided by Neo.mjs.
|
1231
|
+
|
1218
1232
|
Save and refresh, and you'll see a console log emanating from the plugin.
|
1219
1233
|
|
1220
1234
|
<img style="width:80%" src="https://s3.amazonaws.com/mjs.neo.learning.images/earthquakes/GoogleMapsLoaded.png"></img>
|
@@ -1406,3 +1420,16 @@ Save, refresh, and confirm that you see the value logged when you click on a map
|
|
1406
1420
|
|
1407
1421
|
|
1408
1422
|
<!-- /lab -->
|
1423
|
+
|
1424
|
+
## Summary
|
1425
|
+
|
1426
|
+
Congratulations on completing the tutorial!
|
1427
|
+
|
1428
|
+
The goals was to give you hands-on coding a simple app to let you get a feel for syntax
|
1429
|
+
and to introduce some basic Neo.mjs concepts
|
1430
|
+
|
1431
|
+
- Declarative, abstract code
|
1432
|
+
- Class-based coding, and the ability to extend any class, such as `view/earthquakes/Table.mjs`
|
1433
|
+
- View models, to share properties and objects, such as the store shared by the table and map
|
1434
|
+
- Events, specified via `listeners:{}`
|
1435
|
+
- Controllers, to hold event listeners and other procedural logic
|