neo.mjs 6.9.10 → 6.9.12
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/learnneo/index.html +4 -3
- package/apps/learnneo/neo-config.json +2 -1
- package/apps/learnneo/store/Content.mjs +1 -1
- package/apps/learnneo/view/Viewport.mjs +18 -0
- package/apps/learnneo/view/ViewportController.mjs +2 -2
- package/apps/learnneo/view/home/ContentTreeList.mjs +22 -14
- package/apps/learnneo/view/home/ContentView.mjs +60 -0
- package/apps/learnneo/view/home/MainContainer.mjs +14 -6
- package/apps/learnneo/view/home/MainContainerController.mjs +57 -18
- package/apps/learnneo/view/home/MainContainerModel.mjs +3 -5
- package/apps/newwebsite/app.mjs +6 -0
- package/apps/newwebsite/index.html +13 -0
- package/apps/newwebsite/neo-config.json +7 -0
- package/apps/newwebsite/view/MainContainer.mjs +59 -0
- package/buildScripts/convertDesignTokens.mjs +173 -0
- package/buildScripts/webpack/json/myApps.template.json +1 -0
- package/examples/ConfigurationViewport.mjs +12 -9
- package/examples/ServiceWorker.mjs +2 -2
- package/package.json +3 -2
- package/resources/data/{learnneo → deck/learnneo}/p/2023-10-01T18-29-19-158Z.md +3 -6
- package/resources/data/deck/learnneo/p/2023-10-08T20-20-37-336Z.md +36 -0
- package/resources/data/deck/learnneo/p/stylesheet.md +58 -0
- package/resources/data/{learnneo → deck/learnneo}/t.json +19 -2
- package/resources/data/deck/training/p/2022-12-27T21-54-52-300Z.md +11 -0
- package/resources/data/deck/training/p/2022-12-27T21-55-23-144Z.md +43 -0
- package/resources/data/deck/training/p/2022-12-27T21-55-30-948Z.md +1 -0
- package/resources/data/deck/training/p/2022-12-27T21-55-43-542Z.md +84 -0
- package/resources/data/deck/training/p/2022-12-27T22-23-55-083Z.md +1 -0
- package/resources/data/deck/training/p/2022-12-27T22-24-07-886Z.md +8 -0
- package/resources/data/deck/training/p/2022-12-27T22-24-52-295Z.md +8 -0
- package/resources/data/deck/training/p/2022-12-27T22-25-03-853Z.md +5 -0
- package/resources/data/deck/training/p/2022-12-27T22-43-58-924Z.md +10 -0
- package/resources/data/deck/training/p/2022-12-27T22-44-28-881Z.md +3 -0
- package/resources/data/deck/training/p/2022-12-27T22-44-41-791Z.md +4 -0
- package/resources/data/deck/training/p/2022-12-27T22-45-21-032Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-27T22-49-22-078Z.md +4 -0
- package/resources/data/deck/training/p/2022-12-27T22-50-20-626Z.md +4 -0
- package/resources/data/deck/training/p/2022-12-28T16-58-47-786Z.md +0 -0
- package/resources/data/deck/training/p/2022-12-28T16-58-55-192Z.md +9 -0
- package/resources/data/deck/training/p/2022-12-28T17-10-18-058Z.md +15 -0
- package/resources/data/deck/training/p/2022-12-28T17-10-42-296Z.md +40 -0
- package/resources/data/deck/training/p/2022-12-28T17-11-34-653Z.md +41 -0
- package/resources/data/deck/training/p/2022-12-28T17-13-09-994Z.md +0 -0
- package/resources/data/deck/training/p/2022-12-28T21-32-14-420Z.md +0 -0
- package/resources/data/deck/training/p/2022-12-29T01-43-32-431Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-29T15-56-54-485Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-29T15-57-11-499Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-29T16-00-13-223Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-29T18-34-25-826Z.md +4 -0
- package/resources/data/deck/training/p/2022-12-29T18-36-08-226Z.md +106 -0
- package/resources/data/deck/training/p/2022-12-29T18-36-56-893Z.md +112 -0
- package/resources/data/deck/training/p/2022-12-29T19-31-30-507Z.md +31 -0
- package/resources/data/deck/training/p/2022-12-29T19-31-55-091Z.md +14 -0
- package/resources/data/deck/training/p/2022-12-29T20-03-42-628Z.md +9 -0
- package/resources/data/deck/training/p/2022-12-29T20-21-20-669Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-29T20-37-08-919Z.md +46 -0
- package/resources/data/deck/training/p/2022-12-29T20-37-20-344Z.md +43 -0
- package/resources/data/deck/training/p/2022-12-30T19-04-30-990Z.md +8 -0
- package/resources/data/deck/training/p/2022-12-31T18-43-56-338Z.md +7 -0
- package/resources/data/deck/training/p/2022-12-31T18-51-50-682Z.md +1 -0
- package/resources/data/deck/training/p/2022-12-31T18-54-04-176Z.md +4 -0
- package/resources/data/deck/training/p/2022-12-31T22-11-55-555Z.md +112 -0
- package/resources/data/deck/training/p/2022-12-31T23-00-41-222Z.md +6 -0
- package/resources/data/deck/training/p/2022-12-31T23-18-55-655Z.md +69 -0
- package/resources/data/deck/training/p/2022-12-31T23-25-40-735Z.md +21 -0
- package/resources/data/deck/training/p/2022-12-31T23-25-51-014Z.md +7 -0
- package/resources/data/deck/training/p/2023-01-01T17-49-18-429Z.md +3 -0
- package/resources/data/deck/training/p/2023-01-01T18-44-07-034Z.md +34 -0
- package/resources/data/deck/training/p/2023-01-01T18-47-39-766Z.md +15 -0
- package/resources/data/deck/training/p/2023-01-01T19-04-22-830Z.md +4 -0
- package/resources/data/deck/training/p/2023-01-01T21-11-58-025Z.md +25 -0
- package/resources/data/deck/training/p/2023-01-01T21-12-37-340Z.md +23 -0
- package/resources/data/deck/training/p/2023-01-01T21-13-13-880Z.md +8 -0
- package/resources/data/deck/training/p/2023-01-01T21-14-45-740Z.md +98 -0
- package/resources/data/deck/training/p/2023-01-01T21-18-23-886Z.md +26 -0
- package/resources/data/deck/training/p/2023-01-01T21-18-31-316Z.md +19 -0
- package/resources/data/deck/training/p/2023-01-01T21-18-42-290Z.md +23 -0
- package/resources/data/deck/training/p/2023-01-01T21-19-57-020Z.md +24 -0
- package/resources/data/deck/training/p/2023-01-01T21-22-31-184Z.md +13 -0
- package/resources/data/deck/training/p/2023-01-01T21-22-38-317Z.md +17 -0
- package/resources/data/deck/training/p/2023-01-01T21-22-47-693Z.md +20 -0
- package/resources/data/deck/training/p/2023-01-01T21-23-17-716Z.md +39 -0
- package/resources/data/deck/training/p/2023-01-01T21-23-28-532Z.md +22 -0
- package/resources/data/deck/training/p/2023-01-01T21-25-23-899Z.md +3 -0
- package/resources/data/deck/training/p/2023-01-01T21-25-59-742Z.md +1 -0
- package/resources/data/deck/training/p/2023-01-01T21-26-53-748Z.md +12 -0
- package/resources/data/deck/training/p/2023-01-01T23-38-42-863Z.md +2 -0
- package/resources/data/deck/training/p/2023-01-03T02-07-19-014Z.md +143 -0
- package/resources/data/deck/training/p/2023-01-04T01-52-23-454Z.md +76 -0
- package/resources/data/deck/training/p/2023-01-06T23-21-12-009Z.md +127 -0
- package/resources/data/deck/training/p/2023-01-06T23-21-31-685Z.md +81 -0
- package/resources/data/deck/training/p/2023-01-06T23-21-59-596Z.md +36 -0
- package/resources/data/deck/training/p/2023-01-06T23-34-13-897Z.md +87 -0
- package/resources/data/deck/training/p/2023-01-06T23-44-02-340Z.md +0 -0
- package/resources/data/deck/training/p/2023-01-06T23-46-36-687Z.md +1 -0
- package/resources/data/deck/training/p/2023-01-06T23-46-45-783Z.md +33 -0
- package/resources/data/deck/training/p/2023-01-08T00-45-11-144Z.md +50 -0
- package/resources/data/deck/training/p/2023-01-08T01-06-31-267Z.md +41 -0
- package/resources/data/deck/training/p/2023-01-08T01-24-21-088Z.md +95 -0
- package/resources/data/deck/training/p/2023-01-08T01-25-12-557Z.md +11 -0
- package/resources/data/deck/training/p/2023-01-08T01-46-50-723Z.md +25 -0
- package/resources/data/deck/training/p/2023-01-08T02-09-07-802Z.md +18 -0
- package/resources/data/deck/training/p/2023-01-08T02-09-19-678Z.md +66 -0
- package/resources/data/deck/training/p/2023-01-08T02-11-26-333Z.md +29 -0
- package/resources/data/deck/training/p/2023-01-08T17-22-48-841Z.md +14 -0
- package/resources/data/deck/training/p/2023-01-08T20-46-11-806Z.md +5 -0
- package/resources/data/deck/training/p/2023-01-08T20-47-23-682Z.md +5 -0
- package/resources/data/deck/training/p/2023-01-08T20-47-32-064Z.md +13 -0
- package/resources/data/deck/training/p/2023-01-08T20-47-57-045Z.md +0 -0
- package/resources/data/deck/training/p/2023-01-08T20-48-03-791Z.md +18 -0
- package/resources/data/deck/training/p/2023-01-08T20-48-32-466Z.md +9 -0
- package/resources/data/deck/training/p/2023-01-08T20-48-51-322Z.md +20 -0
- package/resources/data/deck/training/p/2023-01-08T20-49-52-741Z.md +0 -0
- package/resources/data/deck/training/p/2023-01-08T20-52-03-556Z.md +0 -0
- package/resources/data/deck/training/p/2023-01-08T20-57-36-333Z.md +2 -0
- package/resources/data/deck/training/p/2023-01-08T20-57-51-136Z.md +5 -0
- package/resources/data/deck/training/p/2023-01-09T00-07-37-951Z.md +0 -0
- package/resources/data/deck/training/p/2023-01-09T00-35-40-671Z.md +3 -0
- package/resources/data/deck/training/p/2023-01-10T01-29-38-148Z.md +10 -0
- package/resources/data/deck/training/p/2023-01-10T01-43-12-166Z.md +31 -0
- package/resources/data/deck/training/p/2023-01-10T02-21-54-303Z.md +10 -0
- package/resources/data/deck/training/p/2023-01-12T01-50-54-617Z.md +74 -0
- package/resources/data/deck/training/p/2023-01-13T19-55-24-735Z.md +14 -0
- package/resources/data/deck/training/p/2023-01-13T20-08-27-068Z.md +28 -0
- package/resources/data/deck/training/p/2023-01-13T20-23-38-411Z.md +25 -0
- package/resources/data/deck/training/p/2023-01-13T20-37-06-267Z.md +13 -0
- package/resources/data/deck/training/p/2023-01-13T21-05-57-708Z.md +8 -0
- package/resources/data/deck/training/p/2023-01-13T21-48-17-258Z.md +20 -0
- package/resources/data/deck/training/p/2023-01-13T22-05-05-799Z.md +14 -0
- package/resources/data/deck/training/p/2023-01-13T22-08-30-863Z.md +17 -0
- package/resources/data/deck/training/p/2023-01-13T23-01-50-449Z.md +4 -0
- package/resources/data/deck/training/p/2023-01-14T00-33-05-958Z.md +62 -0
- package/resources/data/deck/training/p/2023-01-14T00-40-27-784Z.md +229 -0
- package/resources/data/deck/training/p/2023-01-14T00-41-59-081Z.md +153 -0
- package/resources/data/deck/training/p/2023-01-14T13-50-28-199Z.md +19 -0
- package/resources/data/deck/training/p/2023-01-14T13-59-20-275Z.md +6 -0
- package/resources/data/deck/training/p/2023-01-14T14-03-29-456Z.md +3 -0
- package/resources/data/deck/training/p/2023-01-14T14-27-57-678Z.md +7 -0
- package/resources/data/deck/training/p/2023-01-14T17-30-18-228Z.md +33 -0
- package/resources/data/deck/training/p/2023-01-14T18-28-39-316Z.md +1 -0
- package/resources/data/deck/training/p/2023-01-14T18-28-44-115Z.md +4 -0
- package/resources/data/deck/training/p/2023-01-14T18-28-49-548Z.md +18 -0
- package/resources/data/deck/training/p/2023-01-14T18-40-13-758Z.md +10 -0
- package/resources/data/deck/training/p/2023-01-14T19-29-15-291Z.md +12 -0
- package/resources/data/deck/training/p/2023-01-15T18-51-52-134Z.md +83 -0
- package/resources/data/deck/training/p/2023-01-15T20-03-30-073Z.md +11 -0
- package/resources/data/deck/training/p/2023-01-15T22-07-52-073Z.md +16 -0
- package/resources/data/deck/training/p/2023-01-15T22-22-13-517Z.md +12 -0
- package/resources/data/deck/training/p/2023-01-15T22-28-57-508Z.md +131 -0
- package/resources/data/deck/training/p/2023-01-15T22-36-30-913Z.md +115 -0
- package/resources/data/deck/training/p/2023-01-16T16-03-40-770Z.md +12 -0
- package/resources/data/deck/training/p/2023-01-16T20-21-56-859Z.md +5 -0
- package/resources/data/deck/training/p/2023-01-16T20-24-09-690Z.md +24 -0
- package/resources/data/deck/training/p/2023-01-20T12-51-22-646Z.md +21 -0
- package/resources/data/deck/training/p/2023-01-20T13-06-46-614Z.md +9 -0
- package/resources/data/deck/training/p/2023-01-20T13-08-51-600Z.md +7 -0
- package/resources/data/deck/training/p/2023-01-20T15-20-13-363Z.md +26 -0
- package/resources/data/deck/training/p/2023-01-20T15-34-58-813Z.md +75 -0
- package/resources/data/deck/training/p/2023-01-21T16-33-20-458Z.md +33 -0
- package/resources/data/deck/training/p/2023-01-21T16-45-28-263Z.md +28 -0
- package/resources/data/deck/training/p/2023-01-21T16-56-25-452Z.md +3 -0
- package/resources/data/deck/training/p/2023-01-21T17-28-31-493Z.md +6 -0
- package/resources/data/deck/training/p/2023-01-21T19-49-51-918Z.md +13 -0
- package/resources/data/deck/training/p/2023-01-21T20-08-24-452Z.md +15 -0
- package/resources/data/deck/training/p/2023-01-21T20-35-54-947Z.md +20 -0
- package/resources/data/deck/training/p/2023-01-21T20-54-47-603Z.md +39 -0
- package/resources/data/deck/training/p/2023-01-21T20-56-28-184Z.md +25 -0
- package/resources/data/deck/training/p/2023-01-21T20-57-32-927Z.md +4 -0
- package/resources/data/deck/training/p/2023-01-21T23-13-33-394Z.md +6 -0
- package/resources/data/deck/training/p/2023-01-28T19-11-37-464Z.md +24 -0
- package/resources/data/deck/training/p/2023-01-28T20-43-41-188Z.md +9 -0
- package/resources/data/deck/training/p/2023-01-28T20-53-56-476Z.md +8 -0
- package/resources/data/deck/training/p/2023-01-28T20-58-43-776Z.md +10 -0
- package/resources/data/deck/training/p/2023-01-28T22-18-41-259Z.md +33 -0
- package/resources/data/deck/training/p/2023-01-28T22-24-34-808Z.md +24 -0
- package/resources/data/deck/training/p/2023-01-29T16-25-24-528Z.md +44 -0
- package/resources/data/deck/training/p/2023-01-29T21-14-32-588Z.md +12 -0
- package/resources/data/deck/training/p/2023-01-31T19-24-53-504Z.md +8 -0
- package/resources/data/deck/training/p/2023-01-31T20-33-55-855Z.md +11 -0
- package/resources/data/deck/training/p/2023-01-31T20-34-30-261Z.md +7 -0
- package/resources/data/deck/training/p/2023-01-31T20-52-53-367Z.md +43 -0
- package/resources/data/deck/training/p/2023-02-04T15-18-35-682Z.md +20 -0
- package/resources/data/deck/training/p/2023-02-04T15-49-47-597Z.md +14 -0
- package/resources/data/deck/training/p/2023-02-04T18-58-57-808Z.md +1 -0
- package/resources/data/deck/training/p/2023-02-04T20-07-11-288Z.md +1 -0
- package/resources/data/deck/training/p/2023-02-04T20-09-50-169Z.md +1 -0
- package/resources/data/deck/training/p/2023-02-04T20-19-42-740Z.md +8 -0
- package/resources/data/deck/training/p/2023-02-04T20-23-56-013Z.md +12 -0
- package/resources/data/deck/training/p/2023-02-04T20-28-12-391Z.md +20 -0
- package/resources/data/deck/training/p/2023-02-05T00-20-32-554Z.md +16 -0
- package/resources/data/deck/training/p/2023-02-05T00-35-56-282Z.md +13 -0
- package/resources/data/deck/training/p/2023-02-05T15-36-57-182Z.md +24 -0
- package/resources/data/deck/training/p/2023-02-05T17-39-51-712Z.md +70 -0
- package/resources/data/deck/training/p/2023-02-05T17-44-53-815Z.md +195 -0
- package/resources/data/deck/training/p/2023-02-05T17-45-40-114Z.md +92 -0
- package/resources/data/deck/training/p/2023-02-05T18-12-14-489Z.md +60 -0
- package/resources/data/deck/training/p/2023-02-06T00-14-54-457Z.md +9 -0
- package/resources/data/deck/training/p/2023-06-28T18-03-14-313Z.md +8 -0
- package/resources/data/deck/training/p/2023-06-28T18-26-17-290Z.md +7 -0
- package/resources/data/deck/training/p/2023-06-28T21-16-24-034Z.md +40 -0
- package/resources/data/deck/training/p/2023-06-28T21-16-34-972Z.md +16 -0
- package/resources/data/deck/training/p/2023-06-28T21-28-28-379Z.md +4 -0
- package/resources/data/deck/training/p/2023-06-29T23-15-10-411Z.md +5 -0
- package/resources/data/deck/training/p/2023-07-01T15-42-45-193Z.md +433 -0
- package/resources/data/deck/training/p/2023-07-01T21-54-31-329Z.md +6 -0
- package/resources/data/deck/training/p/2023-07-02T16-14-06-970Z.md +14 -0
- package/resources/data/deck/training/p/2023-07-31T00-26-03-842Z.md +4 -0
- package/resources/data/deck/training/p/2023-07-31T00-31-51-933Z.md +10 -0
- package/resources/data/deck/training/p/2023-07-31T00-37-21-927Z.md +205 -0
- package/resources/data/deck/training/p/2023-10-01T18-29-19-158Z.md +76 -0
- package/resources/data/deck/training/p/2023-10-07T19-18-28-517Z.md +102 -0
- package/resources/data/deck/training/p/2023-10-08T20-20-07-934Z.md +75 -0
- package/resources/data/deck/training/p/2023-10-08T20-37-30-658Z.md +0 -0
- package/resources/data/deck/training/p/2023-10-08T21-58-25-809Z.md +68 -0
- package/resources/data/deck/training/p/2023-10-08T22-22-11-013Z.md +0 -0
- package/resources/data/deck/training/p/2023-10-14T19-25-08-153Z.md +119 -0
- package/resources/data/deck/training/t.json +1276 -0
- package/resources/design-tokens/json/component.json +288 -0
- package/resources/design-tokens/json/core.json +352 -0
- package/resources/design-tokens/json/semantic.json +231 -0
- package/resources/scss/src/apps/learnneo/Viewport.scss +3 -0
- package/resources/scss/src/apps/learnneo/home/ContentTreeList.scss +60 -13
- package/resources/scss/src/apps/learnneo/home/ContentView.scss +58 -0
- package/resources/scss/src/apps/newwebsite/MainContainer.scss +32 -0
- package/resources/scss/src/list/Base.scss +1 -1
- package/resources/scss/theme-neo-light/Global.scss +65 -1
- package/resources/scss/theme-neo-light/design-tokens/Component.scss +64 -0
- package/resources/scss/theme-neo-light/design-tokens/Core.scss +67 -0
- package/resources/scss/theme-neo-light/design-tokens/Semantic.scss +61 -0
- package/resources/scss/theme-neo-light/design-tokens/_all.scss +4 -0
- package/resources/scss/theme-neo-light/list/Base.scss +29 -6
- package/src/DefaultConfig.mjs +4 -4
- package/src/controller/Base.mjs +31 -23
- package/src/data/connection/Xhr.mjs +1 -1
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-07T19-18-28-517Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-08T20-20-07-934Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-08T20-37-30-658Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-08T21-58-25-809Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-08T22-22-11-013Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/p/2023-10-14T19-25-08-153Z.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/pages/whyneo.md +0 -0
- /package/resources/data/{learnneo → deck/learnneo}/tree.json +0 -0
- /package/resources/data/{learnneo → deck/training}/p/2023-10-08T20-20-37-336Z.md +0 -0
- /package/resources/{deck → data/deck}/whyneo.md +0 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
#Introduction
|
2
|
+
|
3
|
+
In this lab you'll add `city` and `category` properties.
|
4
|
+
|
5
|
+
#Steps
|
6
|
+
|
7
|
+
??Define a city_ property
|
8
|
+
|
9
|
+
Add a `city_:''` config.
|
10
|
+
|
11
|
+
As you know, this creates a get/set property.
|
12
|
+
|
13
|
+
Save your changes, then in the Chrome debugger's app-worker context
|
14
|
+
get a reference to the filter component and confirm that the property
|
15
|
+
exists.
|
16
|
+
|
17
|
+
Is the property there? This statement should evaluate to '' (and not undefined).
|
18
|
+
|
19
|
+
Neo.findFirst({ntype:'yelp-filter'}).city
|
20
|
+
|
21
|
+
Assign a value.
|
22
|
+
|
23
|
+
Neo.findFirst({ntype:'yelp-filter'}).city = 'Madison'
|
24
|
+
|
25
|
+
Read the value. This should evaluate the city you assigned above.
|
26
|
+
|
27
|
+
Neo.findFirst({ntype:'yelp-filter'}).city
|
28
|
+
|
29
|
+
None of this is very surprising yet. The `city` property would behave
|
30
|
+
the same whether it was a simple property or a get/set property.
|
31
|
+
|
32
|
+
|
33
|
+
??Detect when `city` changes
|
34
|
+
|
35
|
+
We need a function to be run when the city property changes. Later,
|
36
|
+
we'll use that function to update the text field.
|
37
|
+
|
38
|
+
How do you detect a change to a get/set property? Via its `afterSet...`
|
39
|
+
method!
|
40
|
+
|
41
|
+
Add that method, with a single statement that logs the passed value.
|
42
|
+
|
43
|
+
<pre class="runnable readonly text 320">
|
44
|
+
import Base from '../../../../node_modules/neo.mjs/src/container/Base.mjs';
|
45
|
+
import TextField from '../../../../node_modules/neo.mjs/src/form/field/Text.mjs';
|
46
|
+
class Filter extends Base {
|
47
|
+
static config = {
|
48
|
+
...
|
49
|
+
}
|
50
|
+
|
51
|
+
afterSetCity(city) {
|
52
|
+
console.log(city);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
Neo.applyClassConfig(Filter);
|
57
|
+
|
58
|
+
export default Filter;
|
59
|
+
</pre>
|
60
|
+
|
61
|
+
??Test the filter on the command line
|
62
|
+
|
63
|
+
Use the debugger's console (in the app worker context) and verify that
|
64
|
+
you see the value logged. In other words, runing the following should result
|
65
|
+
in `afterSetCity()` being run.
|
66
|
+
|
67
|
+
Neo.findFirst({ntype:'yelp-filter'}).city = 'Madison'
|
68
|
+
|
69
|
+
|
70
|
+
??Add a `category` get/set
|
71
|
+
|
72
|
+
Now add a `category_:'',` config, and a corresponding `afterSetCategory()`
|
73
|
+
method. The code will be almost identical to what you did for city.
|
74
|
+
|
75
|
+
Test your code by setting and getting `category` on the command line.
|
76
|
+
|
77
|
+
Neo.findFirst({ntype:'yelp-filter'}).category
|
78
|
+
|
79
|
+
Neo.findFirst({ntype:'yelp-filter'}).category = 'pizza'
|
80
|
+
|
81
|
+
Neo.findFirst({ntype:'yelp-filter'}).category
|
82
|
+
|
83
|
+
You should see the value updating and the value being logged.
|
@@ -0,0 +1,11 @@
|
|
1
|
+
`Neo.component.Base` also has a `reference` config.
|
2
|
+
|
3
|
+
If you code a component with `reference:'foo',`, then you can get
|
4
|
+
a reference from the view or controller via `this.getReference('foo')`.
|
5
|
+
|
6
|
+
This is similar to using the Neo find methods, but references are
|
7
|
+
resolved in a more efficient manner and the scope is limited to
|
8
|
+
what the view can "see".
|
9
|
+
|
10
|
+
<span style="color:lightgray">(Controllers keep a map of references, keyed by the reference name. The <code style="color:lightgray">getReference()</code> method
|
11
|
+
uses bracket notiation to retrieve the value from the map — it's lighting fast.)</span>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Those labs were lengthy because we worked _very_ slowly and methodically.
|
2
|
+
|
3
|
+
On a project, encapsulating code like this isn't usually needed. You code
|
4
|
+
views that show data, and you nest those in containers.
|
5
|
+
|
6
|
+
But if you need a propertly encapsulated class you'll do something like you
|
7
|
+
did with the `Yelp.view.businesses.Filter`.
|
8
|
+
|
9
|
+
But there isn't much code in there!
|
10
|
+
|
11
|
+
- It has a property
|
12
|
+
- Updates to the properties are reflected in the view
|
13
|
+
- Updates to the view are reflected in the properies
|
14
|
+
|
15
|
+
After you code a couple of such classes it becomes a matter of minutes
|
16
|
+
to code them.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
The following four labs are elaborate.
|
2
|
+
|
3
|
+
They give you
|
4
|
+
practice with a common coding task: creating a de-coupled
|
5
|
+
class with a well-defined API.
|
6
|
+
|
7
|
+
Neo has features that makes this easy. Later we'll cover
|
8
|
+
additional techniques for having a de-coupled class interact
|
9
|
+
with the rest of an application via events and bindings.
|
10
|
+
|
11
|
+
The labs feature common coding use-cases. Take your time —
|
12
|
+
make sure everything makes sense!
|
@@ -0,0 +1,131 @@
|
|
1
|
+
#Introduction
|
2
|
+
|
3
|
+
In this lab you'll udpate the text fields as the properties change.
|
4
|
+
|
5
|
+
#Steps
|
6
|
+
|
7
|
+
??Add `reference` to the fields
|
8
|
+
|
9
|
+
First, add a `reference:'city',` to the city field config
|
10
|
+
and `reference:'category',` to the category field.
|
11
|
+
|
12
|
+
As you recall from lecture, `reference` is used in component
|
13
|
+
or controller methods to get a reference to the field via
|
14
|
+
`this.getReference()`.
|
15
|
+
|
16
|
+
??Update the city field
|
17
|
+
You already have an `afterSetCity()` method.
|
18
|
+
|
19
|
+
Modify it to udpdate the city.
|
20
|
+
|
21
|
+
this.getReference('city').value = city;
|
22
|
+
|
23
|
+
If you save and run the code you get a runtime error!
|
24
|
+
That happens because when the value is first applied (to assign
|
25
|
+
the initial defined in `city_:'',`) the view hasn't
|
26
|
+
been rendered yet! `Neo.component.Base` has a `rendered` property.
|
27
|
+
We need a statement to test that. Add this statement before
|
28
|
+
you assign the city to the field.
|
29
|
+
|
30
|
+
if (!this.rendered) return;
|
31
|
+
|
32
|
+
<pre style="border: thin solid gray; padding: 8px; color: lightgray; font-size:14pt;">
|
33
|
+
import Base from '../../../../node_modules/neo.mjs/src/container/Base.mjs';
|
34
|
+
import TextField from '../../../../node_modules/neo.mjs/src/form/field/Text.mjs';
|
35
|
+
import Function from '../../util/Function.mjs';
|
36
|
+
class Filter extends Base {
|
37
|
+
static config = {
|
38
|
+
className: 'Yelp.view.businesses.Filter',
|
39
|
+
ntype: 'yelp-filter',
|
40
|
+
|
41
|
+
city_: '',
|
42
|
+
category_: '',
|
43
|
+
|
44
|
+
layout: { ntype: 'hbox' },
|
45
|
+
itemDefaults: {module: TextField, clearable: true,},
|
46
|
+
items: [
|
47
|
+
...
|
48
|
+
]
|
49
|
+
}
|
50
|
+
afterSetCity(city) {
|
51
|
+
console.log(city);
|
52
|
+
<span style="color:#b91010;">if (!this.rendered) return;
|
53
|
+
this.getReference('city').value = city;</span>
|
54
|
+
}
|
55
|
+
afterSetCategory(category) {
|
56
|
+
console.log(category);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
Neo.applyClassConfig(Filter);
|
61
|
+
|
62
|
+
export default Filter;
|
63
|
+
</pre>
|
64
|
+
|
65
|
+
??Test the code
|
66
|
+
|
67
|
+
In the Chrome debugger update the city property. You should see the
|
68
|
+
text field update to reflect the change.
|
69
|
+
|
70
|
+
Neo.findFirst({ntype:'yelp-filter'}).city = 'Madison'
|
71
|
+
|
72
|
+
??Add the same logic for category
|
73
|
+
|
74
|
+
Modify the `afterSetCategory()` method to work like the after city method.
|
75
|
+
|
76
|
+
Test it in the Chrome debugger. You should see the category text field updating.
|
77
|
+
|
78
|
+
Neo.findFirst({ntype:'yelp-filter'}).category = 'pizza'
|
79
|
+
|
80
|
+
??Notice a timing issue
|
81
|
+
|
82
|
+
Currently, the initial city and category are just empty strings.
|
83
|
+
But if there had some other values we'd want the city and category
|
84
|
+
text fields to reflect those values as we start the app.
|
85
|
+
|
86
|
+
For example, change the city and category like this:
|
87
|
+
|
88
|
+
city_: 'Madison',
|
89
|
+
category_: 'pizza',
|
90
|
+
|
91
|
+
Upon refresh these values are _not_ seen in the fields, but you _will_
|
92
|
+
see the values in the Crome debugger
|
93
|
+
|
94
|
+
console.log(Neo.findFirst({ntype:'yelp-filter'}).city); // Logs "Madison"
|
95
|
+
|
96
|
+
The initial values _are_ assigned, and the `afterSet...` methods are run,
|
97
|
+
but since the view hasn't been rendered the `after` methods can't initialize
|
98
|
+
the fields.
|
99
|
+
|
100
|
+
??Fix the issue
|
101
|
+
|
102
|
+
We need to detect when the view is rendered, then update
|
103
|
+
the text fields to their initial values.
|
104
|
+
|
105
|
+
Since `Neo.component.Base` has a `mounted` get/set,
|
106
|
+
there's a corresponding `afterSetMounted()` method. We'll add the code
|
107
|
+
there.
|
108
|
+
|
109
|
+
Use the following code. Note the 20ms delay. That's there because
|
110
|
+
after a view is mounted, the DOM may not update until one "frame"
|
111
|
+
later, which is about 18ms.
|
112
|
+
|
113
|
+
afterSetMounted() {
|
114
|
+
// Wait for one "frame" using a framerate of 60 per second = 17.7 ms
|
115
|
+
setTimeout(() => {
|
116
|
+
this.afterSetCity(this.city);
|
117
|
+
this.afterSetCategory(this.category);
|
118
|
+
}, 20);
|
119
|
+
}
|
120
|
+
|
121
|
+
Save and refresh. You should see the new default values as the initial
|
122
|
+
values for the city and category text fields.
|
123
|
+
|
124
|
+
??Make sure `city` and `category` have their normal default values
|
125
|
+
|
126
|
+
Change city and category back to their normal default values.
|
127
|
+
|
128
|
+
city_: '',
|
129
|
+
category_: '',
|
130
|
+
|
131
|
+
In an upcoming lab we'll use another method of initializing the city and category.
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#Introduction
|
2
|
+
|
3
|
+
In this lab you'll update the property as the text fields change.
|
4
|
+
|
5
|
+
#Steps
|
6
|
+
|
7
|
+
??Update `city` as the user types.
|
8
|
+
|
9
|
+
We want changes in the text field to be reflected in the filter's `city` property.
|
10
|
+
|
11
|
+
To do that, listen to the field's `change` event, and in the handler get a
|
12
|
+
reference to the parent container, and assign the value to it's `city` property.
|
13
|
+
|
14
|
+
listeners: {
|
15
|
+
change: (data) => data.component.up('yelp-filter').city = data.value
|
16
|
+
}
|
17
|
+
|
18
|
+
Test this by entering text in the city field — you should see a the console
|
19
|
+
log being run on each keypress.
|
20
|
+
|
21
|
+
??Do the same for `category`
|
22
|
+
|
23
|
+
Add a similer `listeners` config to the category field.
|
24
|
+
|
25
|
+
Test this by entering text in the category field — you should see a the console
|
26
|
+
log being run on each keypress.
|
27
|
+
|
28
|
+
??Plan a way to buffer or _debounce_ the updates
|
29
|
+
|
30
|
+
Conceptually, `Yelp.view.business.Filter` has `city` and `category` properties.
|
31
|
+
|
32
|
+
"Madison" is a city, but "M" and "Ma" and "Mad" are not cities, so the
|
33
|
+
_city_ property shouldn't reflect those intermediate values. Therefore,
|
34
|
+
we need code to defer updating the property until the user appears to have
|
35
|
+
finished typing.
|
36
|
+
|
37
|
+
There are various ways to create a _buffer_ or _debouce_ fuctions, and
|
38
|
+
we found one via an internet search. We need a place to hold our implementation.
|
39
|
+
|
40
|
+
??Add a utility class with a `debounce` function
|
41
|
+
|
42
|
+
Use a terminal to navigate to the Neo workspace, and run `npm run create-class`.
|
43
|
+
|
44
|
+
- Name the class "Yelp.util.Function"
|
45
|
+
- Extend `Neo.core.Base
|
46
|
+
- Make it a singleton
|
47
|
+
|
48
|
+
Edit the new file and add the debounce routine highlighted below.
|
49
|
+
|
50
|
+
<pre style="border: thin solid gray; padding: 8px; color: lightgray;font-size:14pt;">
|
51
|
+
import Base from '../../../node_modules/neo.mjs/src/core/Base.mjs';
|
52
|
+
|
53
|
+
class Function extends Base {
|
54
|
+
static config = {
|
55
|
+
className: 'Yelp.util.Function',
|
56
|
+
singleton: true
|
57
|
+
}
|
58
|
+
<span style="color:#b91010;">debounce(func, wait, immediate) {
|
59
|
+
let timeout
|
60
|
+
return function (...args) {
|
61
|
+
clearTimeout(timeout)
|
62
|
+
timeout = setTimeout(() => {
|
63
|
+
timeout = null
|
64
|
+
if (!immediate) func.apply(this, args)
|
65
|
+
}, wait)
|
66
|
+
if (immediate && !timeout) func.apply(this, [...args])
|
67
|
+
}
|
68
|
+
}</span>
|
69
|
+
}
|
70
|
+
|
71
|
+
Neo.applyClassConfig(Function);
|
72
|
+
|
73
|
+
let instance = Neo.create(Function);
|
74
|
+
|
75
|
+
Neo.applyToGlobalNs(instance);
|
76
|
+
|
77
|
+
export default instance;
|
78
|
+
</pre>
|
79
|
+
|
80
|
+
??Buffer the updates
|
81
|
+
|
82
|
+
Edit `view/businesses/Filter.mjs` and add this import.
|
83
|
+
|
84
|
+
import Function from '../../util/Function.mjs';
|
85
|
+
|
86
|
+
And add a method designed to do a buffered update to a property.
|
87
|
+
|
88
|
+
doBufferedUpdate(property, value) {
|
89
|
+
this._bufferedUpdate = this._bufferedUpdate || Function.debounce((property, value) => this[property] = value, 500);
|
90
|
+
this._bufferedUpdate(property, value);
|
91
|
+
}
|
92
|
+
|
93
|
+
??Use the new function when the city text field changes
|
94
|
+
|
95
|
+
Modify the city's `change` listener to use the new function.
|
96
|
+
|
97
|
+
listeners: {
|
98
|
+
change: (data) => data.component.up('yelp-filter').doBufferedUpdate('city', data.value)
|
99
|
+
}
|
100
|
+
|
101
|
+
Test the changes by running the app, and type a city name. After the 500ms delay
|
102
|
+
you should see the city name logged. Note that running
|
103
|
+
|
104
|
+
Neo.findFirst({ntype:'yelp-filter'}).city = 'Madison'
|
105
|
+
|
106
|
+
logs the city name immediately. Changing the city to a new value updates
|
107
|
+
immediately. We only need to buffer changes when the user is typing.
|
108
|
+
|
109
|
+
??Have the category field do the same thing
|
110
|
+
|
111
|
+
Make a similar change to the category field config.
|
112
|
+
|
113
|
+
listeners: {
|
114
|
+
change: (data) => data.component.up('yelp-filter').doBufferedUpdate('category', data.value)
|
115
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
You simply assign or read values to access a property.
|
2
|
+
|
3
|
+
console.log(component.bar); // Results in the secret getter being run
|
4
|
+
component.bar = 'hi'; // Results in the secret setter being run
|
5
|
+
|
6
|
+
You can set multiple values simultaneously via `Neo.component.Bases#set({})`
|
7
|
+
|
8
|
+
component.set({
|
9
|
+
bar: 'hi',
|
10
|
+
baz: 'there'
|
11
|
+
});
|
12
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
A tab container is a card-layout container with a tab bar and styled buttons.
|
2
|
+
Do not specify a `layout` for tab containers.
|
3
|
+
|
4
|
+
The buttons are configured via `tabButtonConfig`
|
5
|
+
|
6
|
+
activeIndex: 2,
|
7
|
+
tabBarPosition: 'left', // top, right, bottom, left
|
8
|
+
itemDefaults: { module: Button },
|
9
|
+
items: [{
|
10
|
+
tabButtonConfig: {
|
11
|
+
iconCls: 'fa fa-home',
|
12
|
+
text: 'Tab 1'
|
13
|
+
}
|
14
|
+
}, {
|
15
|
+
tabButtonConfig: {
|
16
|
+
iconCls: 'fa fa-play-circle',
|
17
|
+
text: 'Tab 2'
|
18
|
+
}
|
19
|
+
}, {
|
20
|
+
tabButtonConfig: {
|
21
|
+
iconCls: 'fa fa-bell',
|
22
|
+
text: 'Tab 3'
|
23
|
+
}
|
24
|
+
}]
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
<div class="expander" caption="High-level Goal">
|
4
|
+
<h2>To learn how to properly encapsulate a class with a well defined API.</h2>
|
5
|
+
<p>
|
6
|
+
You'll code a class that's encapsulated and de-coupled, where the code creating
|
7
|
+
the instance uses class properties and otherwise has no awareness of its
|
8
|
+
implementation details.
|
9
|
+
</p>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
|
13
|
+
<div class="expander" caption="Low-level Goal">
|
14
|
+
<h2>To get practice using the syntax and features we just learned.</h2>
|
15
|
+
<ul>
|
16
|
+
<li>Defining get/set properties
|
17
|
+
<li>Using `afterSet` methods to detect property change
|
18
|
+
<li>Using `reference` and `getReference()`
|
19
|
+
</ul>
|
20
|
+
</div>
|
21
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
- A view controller holds a view's event handlers
|
2
|
+
- The controller can hold any other logic you might need
|
3
|
+
|
4
|
+
|
5
|
+
The existence of a controller should be unknown outside of the class.
|
6
|
+
The decision of the view's author to use (or not use) a controller
|
7
|
+
should be transparent outside of the class.
|
8
|
+
|
9
|
+
this.lookup('someComponent').controller.someMethod(); // This is bad
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Within controller methods you can get a reference to a view component
|
2
|
+
via
|
3
|
+
|
4
|
+
- `this.getReference('name')` returns a component with the specified reference
|
5
|
+
- In the view, you specify the reference via `reference: 'somename`
|
6
|
+
|
7
|
+
- `onComponentConstructed()` is a controller lifecycle method you can override if you need to do something at time of component creation
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#Introduction
|
2
|
+
|
3
|
+
In this lab you'll put the view model into its own class.
|
4
|
+
|
5
|
+
#Steps
|
6
|
+
|
7
|
+
|
8
|
+
??Create the view model
|
9
|
+
|
10
|
+
Use `npm run create-class` to create`Yelp.view.MainViewModel` that extends `model/Component`.
|
11
|
+
|
12
|
+
??Use it
|
13
|
+
|
14
|
+
Move the `data` property from the main view to the view model.
|
15
|
+
|
16
|
+
Then import the view model, and change the `model` config to use the new class.
|
17
|
+
|
18
|
+
??Create and use a controller
|
19
|
+
|
20
|
+
We don't need controller logic yet, but we will, so while we're at it, create a
|
21
|
+
`Yelp.view.MainViewController` that extends `controller/Component`. Import it in the
|
22
|
+
main view, and configure a controller block to use it.
|
23
|
+
|
24
|
+
controller: {
|
25
|
+
module: MainViewController
|
26
|
+
}
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#Introduction
|
2
|
+
|
3
|
+
In this lab you'll detect changes to city and category.
|
4
|
+
When city changes you'll geocode it to find its latitude and longitude.
|
5
|
+
|
6
|
+
#Steps
|
7
|
+
|
8
|
+
??Remove the view model listener in the main view
|
9
|
+
|
10
|
+
To avoid being overwhelmed with `console.log()` output, edit
|
11
|
+
the main view and remove the `listeners` config in the
|
12
|
+
view model config. From now on on the view model listening logic
|
13
|
+
will be set up in the main view controller.
|
14
|
+
|
15
|
+
??Detect view model property changes
|
16
|
+
|
17
|
+
In the main view controller override the `onComponentConstructed()` method. The method
|
18
|
+
should check for changes to _city_ and if so, call a new method `onCityChange(city)`.
|
19
|
+
|
20
|
+
onComponentConstructed() {
|
21
|
+
const model = this.getModel();
|
22
|
+
this.onCityChange(model.data.city);
|
23
|
+
model.on('dataPropertyChange', data => {
|
24
|
+
if (data.key === 'city') this.onCityChange(data.value);
|
25
|
+
});
|
26
|
+
}
|
27
|
+
onCityChange(city) {
|
28
|
+
if (!city) return;
|
29
|
+
// The code to geocode the city goes here.
|
30
|
+
console.log(city);
|
31
|
+
}
|
32
|
+
|
33
|
+
Save, change the city, and look for the console log in the debugger console.
|
34
|
+
|
35
|
+
??Geocode the city
|
36
|
+
|
37
|
+
Use the following call to `Neo.main.addon.GoogleMaps.geocode`. The details of the
|
38
|
+
call and the response aren't important right now, although if you're curious you
|
39
|
+
can read <a href="https://developers.google.com/maps/documentation/geocoding/requests-geocoding" target="_blank">the Google Maps geocoding API</a>.
|
40
|
+
|
41
|
+
<pre style='padding: 4px; font-size: 13.5pt; border: thin solid gray; color:lightgray'>
|
42
|
+
onCityChange(city) {
|
43
|
+
if (!city) return;
|
44
|
+
<span style='color:firebrick'>Neo.main.addon.GoogleMaps.geocode({ address: city })
|
45
|
+
.then(data => this.getModel().data.center = data.results[0].geometry.location);</span>
|
46
|
+
}
|
47
|
+
</pre>
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
??Stub out a method that will eventually be fetching Yelp data
|
52
|
+
|
53
|
+
Add this method.
|
54
|
+
|
55
|
+
doFetchYelpData() {
|
56
|
+
const model = this.getModel();
|
57
|
+
console.log('Fetch yelp data', model.data.center, model.data.category);
|
58
|
+
}
|
59
|
+
|
60
|
+
And modify `onComponentConstructed()` to check for changes to _center_ and _category_.
|
61
|
+
|
62
|
+
<pre style='padding: 4px; border: thin solid gray; color:lightgray'>
|
63
|
+
onComponentConstructed() {
|
64
|
+
const model = this.getModel();
|
65
|
+
this.onCityChange(model.getData('city'));
|
66
|
+
model.on('dataPropertyChange', data => {
|
67
|
+
if (data.key === 'city') this.onCityChange(data.value);
|
68
|
+
<span style='color:firebrick'>if (data.key === 'center') this.doFetchYelpData();
|
69
|
+
if (data.key === 'category') this.doFetchYelpData();</span>
|
70
|
+
});
|
71
|
+
}
|
72
|
+
</pre>
|
73
|
+
|
74
|
+
Save, refresh, and verify that `doFetchYelpData()` is logging changes to the map center
|
75
|
+
(via changes to city), and category.
|
@@ -0,0 +1,33 @@
|
|
1
|
+
Some components, such as `Neo.table.Container`, have a `store` config.
|
2
|
+
|
3
|
+
<pre style="padding: 8px; border: thin solid lightgray; font-size: 11pt; ">
|
4
|
+
{
|
5
|
+
module: EarthquakesTable,
|
6
|
+
listeners: {
|
7
|
+
select: 'onTableSelect'
|
8
|
+
},
|
9
|
+
store: {
|
10
|
+
module: Store,
|
11
|
+
model: {
|
12
|
+
fields: [{
|
13
|
+
name: 'humanReadableLocation'
|
14
|
+
}, {
|
15
|
+
name: 'size',
|
16
|
+
ntype: 'data-field-float',
|
17
|
+
}, {
|
18
|
+
name: 'timestamp',
|
19
|
+
type: 'Date'
|
20
|
+
}, {
|
21
|
+
name: 'title',
|
22
|
+
calculate: (data, field, item) => item.humanReadableLocation
|
23
|
+
}, {
|
24
|
+
name: 'position',
|
25
|
+
calculate: (data, field, item) => ({ lat: item.latitude, lng: item.longitude })
|
26
|
+
}]
|
27
|
+
},
|
28
|
+
url: 'https://apis.is/earthquake/is',
|
29
|
+
responseRoot: 'results',
|
30
|
+
autoLoad: true
|
31
|
+
}
|
32
|
+
}
|
33
|
+
</pre>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
<pre style="padding: 8px; border: thin solid lightgray; font-size: 13pt; ">
|
3
|
+
class MainViewModel extends Base {
|
4
|
+
static getConfig() {
|
5
|
+
return {
|
6
|
+
className: 'Earthquakes.view.MainViewModel',
|
7
|
+
data: {},
|
8
|
+
stores: {
|
9
|
+
earthquakes: {
|
10
|
+
module: Store,
|
11
|
+
model: {
|
12
|
+
...
|
13
|
+
},
|
14
|
+
...
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}</pre>
|
20
|
+
|
21
|
+
<pre style="padding: 8px; border: thin solid lightgray; font-size: 13pt; ">
|
22
|
+
{
|
23
|
+
module: EarthquakesTable,
|
24
|
+
bind: {
|
25
|
+
store: 'stores.earthquakes'
|
26
|
+
},
|
27
|
+
}
|
28
|
+
</pre>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
If the record's value isn't a simple conversion from the value in the feed
|
2
|
+
you can provide a `calculate` method. For example:
|
3
|
+
|
4
|
+
{
|
5
|
+
name: 'position',
|
6
|
+
calculate: (record, field, data) => ({ lat: data.latitude, lng: data.longitude })
|
7
|
+
}
|
8
|
+
|
9
|
+
- _record_ is the record instance
|
10
|
+
- _field_ is the field config
|
11
|
+
- _data_ is the value from the data feed
|
12
|
+
|
13
|
+
You can use `calculate` to convert a value from the feed, or to define a new record value.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
A recod config contains a `fields:[]` that describes the record's fields.
|
2
|
+
|
3
|
+
The field config can have these values:
|
4
|
+
|
5
|
+
| Config Property | Description |
|
6
|
+
|-----------------|--------------------------------------------------------------------|
|
7
|
+
|`name` | Required. The name of the feed value. |
|
8
|
+
|`type` | Date/html/string |
|
9
|
+
|`mapping` | The path to feed property. |
|
10
|
+
| | |
|
11
|
+
|`calculate` | A function used to calculate the value of the field. |
|
12
|
+
| | |
|
13
|
+
|`maxLength` | Limits values to the specific length. |
|
14
|
+
|`minLength` | Limits values to the specific length. |
|
15
|
+
|`nullable` | Flags whether the value can be null/undefined. |
|