@fui-org/fui-cli 2.1.4 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -7
- package/dist/fui-qrb1j9jz.js +397 -0
- package/dist/fui.js +1 -1
- package/package.json +1 -1
- package/skills/fui/SKILL.md +143 -38
- package/skills/fui/agents/fui-builder.md +62 -0
- package/skills/fui/agents/fui-tester.md +77 -0
- package/skills/{fui-skill → fui}/assets/projectdefaultstyle.css +489 -489
- package/skills/{fui-skill → fui}/examples/component.vue +162 -162
- package/skills/{fui-skill → fui}/references/INDEX.md +5 -4
- package/skills/{fui-skill → fui}/references/advanced-techniques.md +170 -168
- package/skills/{fui-skill → fui}/references/component-design.md +2 -2
- package/skills/{fui-skill → fui}/references/component-quickref.md +78 -78
- package/skills/{fui-skill → fui}/references/component-table.md +287 -287
- package/skills/{fui-skill → fui}/references/components-dialog.md +191 -191
- package/skills/{fui-skill → fui}/references/components-display.md +141 -141
- package/skills/{fui-skill → fui}/references/components-echart.md +316 -316
- package/skills/{fui-skill → fui}/references/components-input.md +335 -335
- package/skills/{fui-skill → fui}/references/controls-patterns.md +2 -2
- package/skills/{fui-skill → fui}/references/controls-styling-vocabulary.md +173 -173
- package/skills/{fui-skill → fui}/references/db-workflow.md +9 -9
- package/skills/{fui-skill → fui}/references/default-function.md +456 -456
- package/skills/{fui-skill → fui}/references/design-modes.md +57 -57
- package/skills/{fui-skill → fui}/references/echart-templates.md +489 -489
- package/skills/{fui-skill → fui}/references/fastproject.md +99 -99
- package/skills/{fui-skill → fui}/references/fullstack-workflow.md +314 -313
- package/skills/{fui-skill → fui}/references/module-data-patterns.md +117 -117
- package/skills/{fui-skill → fui}/references/module-json-anatomy.md +132 -132
- package/skills/{fui-skill → fui}/references/module-structure.md +144 -144
- package/skills/{fui-skill → fui}/references/new-session.md +1 -2
- package/skills/{fui-skill → fui}/references/pdfmake.md +60 -60
- package/skills/{fui-skill → fui}/references/permission-system.md +1 -1
- package/skills/{fui-skill → fui}/references/platform-architecture.md +269 -269
- package/skills/{fui-skill → fui}/references/project-config.md +303 -303
- package/skills/{fui-skill → fui}/references/project-provisioning.md +4 -4
- package/skills/{fui-skill → fui}/references/script-map.md +262 -262
- package/skills/{fui-skill → fui}/references/sql-clr-functions.md +225 -225
- package/skills/{fui-skill → fui}/references/system-design.md +2 -2
- package/skills/{fui-skill → fui}/references/tapi-permission-patterns.md +156 -156
- package/skills/{fui-skill → fui}/references/tapi-reference.md +474 -474
- package/skills/fui/references/team-run.md +141 -0
- package/skills/fui/references/tools-registry.md +211 -0
- package/skills/{fui-skill → fui}/references/ui-crosswindow-patterns.md +321 -321
- package/skills/{fui-skill → fui}/references/ui-dialog-patterns.md +255 -255
- package/skills/{fui-skill → fui}/references/ui-layout-patterns.md +176 -176
- package/skills/{fui-skill → fui}/references/ui-patterns.md +303 -303
- package/skills/{fui-skill → fui}/references/ui-screenshot-review.md +95 -95
- package/skills/{fui-skill → fui}/references/ui-table-cell-patterns.md +318 -318
- package/skills/{fui-skill → fui}/references/verification.md +11 -11
- package/skills/{fui-skill → fui}/references/watcher-patterns.md +163 -163
- package/skills/{fui-skill → fui}/references/websocket-realtime.md +271 -271
- package/skills/{fui-skill → fui}/scripts/component-3.0.js +2715 -2715
- package/skills/{fui-skill → fui}/scripts/component.js +3147 -3147
- package/skills/{fui-skill → fui}/scripts/componentTable-3.0.js +1038 -1038
- package/skills/{fui-skill → fui}/scripts/componentTable.js +891 -891
- package/skills/{fui-skill → fui}/scripts/defaultfunction-3.0.js +866 -866
- package/skills/{fui-skill → fui}/scripts/defaultfunction.js +1051 -1051
- package/skills/{fui-skill → fui}/scripts/fastproject-3.0.js +870 -870
- package/skills/{fui-skill → fui}/scripts/fastproject.js +828 -828
- package/dist/fui-h4z7zhk2.js +0 -381
- package/skills/fui-skill/SKILL.md +0 -139
- package/skills/fui-skill/references/tools-registry.md +0 -84
- /package/skills/{fui-skill → fui}/assets/projectdefaultstyle-3.0.css +0 -0
- /package/skills/{fui-skill → fui}/design-md/airbnb/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/airbnb/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/airtable/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/airtable/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/apple/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/apple/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/asu/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/asu/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/binance/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/binance/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw-m/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw-m/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bugatti/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bugatti/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cal/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cal/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/claude/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/claude/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clay/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clay/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clickhouse/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clickhouse/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cohere/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cohere/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/coinbase/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/coinbase/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/composio/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/composio/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cursor/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cursor/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/elevenlabs/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/elevenlabs/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/expo/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/expo/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ferrari/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ferrari/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/figma/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/figma/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/framer/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/framer/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/fui/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/hashicorp/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/hashicorp/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ibm/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ibm/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/intercom/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/intercom/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/kraken/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/kraken/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lamborghini/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lamborghini/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/linear.app/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/linear.app/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lovable/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lovable/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mastercard/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mastercard/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/meta/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/meta/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/minimax/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/minimax/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mintlify/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mintlify/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/miro/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/miro/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mistral.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mistral.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mongodb/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mongodb/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nike/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nike/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/notion/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/notion/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nvidia/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nvidia/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ollama/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ollama/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/opencode.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/opencode.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/pinterest/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/pinterest/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/playstation/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/playstation/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/posthog/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/posthog/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/raycast/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/raycast/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/renault/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/renault/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/replicate/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/replicate/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/resend/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/resend/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/revolut/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/revolut/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/runwayml/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/runwayml/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sanity/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sanity/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sentry/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sentry/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/shopify/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/shopify/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/slack/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spacex/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spacex/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spotify/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spotify/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/starbucks/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/starbucks/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/stripe/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/stripe/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/supabase/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/supabase/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/superhuman/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/superhuman/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/tesla/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/tesla/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/theverge/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/theverge/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/together.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/together.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/uber/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/uber/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vercel/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vercel/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vodafone/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vodafone/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/voltagent/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/voltagent/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/warp/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/warp/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/webflow/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/webflow/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wired/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wired/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wise/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wise/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/x.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/x.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/zapier/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/zapier/README.md +0 -0
- /package/skills/{fui-skill → fui}/examples/f-table-patterns.json +0 -0
- /package/skills/{fui-skill → fui}/examples/module-patterns.json +0 -0
- /package/skills/{fui-skill → fui}/examples/project-patterns.json +0 -0
- /package/skills/{fui-skill → fui}/references/coding-standards.md +0 -0
- /package/skills/{fui-skill → fui}/references/db-table-design.md +0 -0
- /package/skills/{fui-skill → fui}/references/fsheet.md +0 -0
- /package/skills/{fui-skill → fui}/references/tapi-file-api.md +0 -0
- /package/skills/{fui-skill → fui}/references/ui-templates.md +0 -0
- /package/skills/{fui-skill → fui}/scripts/fechart.js +0 -0
- /package/skills/{fui-skill → fui}/scripts/fsheet.js +0 -0
|
@@ -1,321 +1,321 @@
|
|
|
1
|
-
# FUI Cross-window Patterns — openWindow & data exchange
|
|
2
|
-
|
|
3
|
-
> Owns: **`openWindow`, cross-window data exchange (`#PARENT`/`#Win`), `set.menu` for child modules, `onclose`**.
|
|
4
|
-
|
|
5
|
-
Open a module as a sub-window and exchange data between windows/iframes (`#PARENT`, `#WinID`). From project **security-manager** and `ex-v3-*` examples. See also [ui-patterns.md](ui-patterns.md), [default-function.md](default-function.md) (`openWindow`, `windowSendMessage`).
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 1. openWindow
|
|
10
|
-
|
|
11
|
-
Opens another module as a separate popup window. `id` is the handle for later references.
|
|
12
|
-
|
|
13
|
-
```json
|
|
14
|
-
{
|
|
15
|
-
"FUN": "openWindow",
|
|
16
|
-
"IN": {
|
|
17
|
-
"id": "`Win1",
|
|
18
|
-
"title": "`User Permission",
|
|
19
|
-
"url": "`/UserPermission",
|
|
20
|
-
"data": "danhSachChoTable",
|
|
21
|
-
"width": "`800px",
|
|
22
|
-
"height": "`600px",
|
|
23
|
-
"onclose": {
|
|
24
|
-
"CALL": "reloadData"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
| Param | Required | Description |
|
|
31
|
-
| ------------------ | -------- | --------------------------------------------------------------------------- |
|
|
32
|
-
| `id` | ✅ | Window id (backtick = literal) — referenced as `#Win1` |
|
|
33
|
-
| `url` | ✅ | Module URL — no `?menu=0`; child declares `"set": { "menu": false }` itself |
|
|
34
|
-
| `title` | ❌ | Dialog title |
|
|
35
|
-
| `data` | ❌ | Data passed to the child — child reads `#PARENT.data` |
|
|
36
|
-
| `width` / `height` | ❌ | Window size (`"800px"`, `"50%"`) |
|
|
37
|
-
| `onclose` | ❌ | Action run after the sub-window closes |
|
|
38
|
-
|
|
39
|
-
> **Child module:** never pass `?menu=0` in the URL. The child declares `"set": { "menu": false }` in its module.json to hide the menu permanently, regardless of how it's opened. URL carries only the IDs needed to query the DB.
|
|
40
|
-
|
|
41
|
-
**`onclose` targeting another window:**
|
|
42
|
-
|
|
43
|
-
```json
|
|
44
|
-
"onclose": {
|
|
45
|
-
"#Win1": { "CALL": "cmdThongBao" }
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
> When Win2 closes → runs `cmdThongBao` in Win1 (not the current window).
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## 2. Cross-window data exchange
|
|
54
|
-
|
|
55
|
-
`#PARENT` and `#WinID` exchange data between windows (iframes). Works same-domain and cross-domain (via `postMessage`).
|
|
56
|
-
|
|
57
|
-
### Read (value position)
|
|
58
|
-
|
|
59
|
-
```json
|
|
60
|
-
"data": [
|
|
61
|
-
{
|
|
62
|
-
"sUserID": "#PARENT.sUserID",
|
|
63
|
-
"sFullName": "#PARENT.sFullName",
|
|
64
|
-
"dataFromWin1": "#Win1.apiChart"
|
|
65
|
-
}
|
|
66
|
-
]
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
| Syntax | Meaning |
|
|
70
|
-
| ----------------- | ------------------------------------------ |
|
|
71
|
-
| `"#PARENT.field"` | Read `vueData.field` from parent |
|
|
72
|
-
| `"#Win1.field"` | Read `vueData.field` from iframe id `Win1` |
|
|
73
|
-
|
|
74
|
-
### Write (key position)
|
|
75
|
-
|
|
76
|
-
```json
|
|
77
|
-
"data": [
|
|
78
|
-
{
|
|
79
|
-
"#PARENT.abcdef": 1234567890,
|
|
80
|
-
"#Win1.dulieuTuForm2": "`huynh cao tuan"
|
|
81
|
-
}
|
|
82
|
-
]
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
```json
|
|
86
|
-
":action": {
|
|
87
|
-
"#PARENT.val4": "DauRaTuCauTruc_IN"
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
| Syntax | Meaning |
|
|
92
|
-
| ------------------------ | --------------------------------- |
|
|
93
|
-
| `"#PARENT.field": value` | Write to parent's `vueData.field` |
|
|
94
|
-
| `"#Win1.field": value` | Write to Win1's `vueData.field` |
|
|
95
|
-
|
|
96
|
-
### Call an action in another window
|
|
97
|
-
|
|
98
|
-
```json
|
|
99
|
-
":action": {
|
|
100
|
-
"#PARENT": { "CALL": "cmdSETData" }
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
```json
|
|
105
|
-
"#Win1": { "CALL": "cmdThongBao" }
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
- `"#PARENT"` (no field) with an action value → `runAction(value)` in parent
|
|
109
|
-
- `"#Win1"` with an action value → `runAction(value)` in Win1
|
|
110
|
-
|
|
111
|
-
### Receive data passed by openWindow
|
|
112
|
-
|
|
113
|
-
Parent opens child with `"data": "sourceData"`:
|
|
114
|
-
|
|
115
|
-
```json
|
|
116
|
-
"data": [
|
|
117
|
-
{
|
|
118
|
-
"LayDuLieuWinCha": "#PARENT.Win1"
|
|
119
|
-
}
|
|
120
|
-
]
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
> `#PARENT.Win1` reads parent variable `Win1`. When the parent calls `openWindow` with `id: "Win1"`, FUI sets `vueData.Win1 = passed_data` in the parent before opening.
|
|
124
|
-
|
|
125
|
-
### Full pattern — child receives parent data
|
|
126
|
-
|
|
127
|
-
**Parent (ex-v3-1SetData):**
|
|
128
|
-
|
|
129
|
-
```json
|
|
130
|
-
":action": {
|
|
131
|
-
"FUN": "openWindow",
|
|
132
|
-
"IN": {
|
|
133
|
-
"id": "`Win1",
|
|
134
|
-
"url": "`/ex/ex-v3-2CauTruc",
|
|
135
|
-
"data": "danhSachChoTable"
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
**Child (ex-v3-2CauTruc):**
|
|
141
|
-
|
|
142
|
-
```json
|
|
143
|
-
"data": [
|
|
144
|
-
{
|
|
145
|
-
"IF": "typeof menu != 'undefined' && menu=='0'",
|
|
146
|
-
"THEN": { "v_Set.menu": false }
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
"LayDuLieuWinCha": "#PARENT.Win1",
|
|
150
|
-
"GiaTriTuCHA.thu.xem": "#PARENT.val7",
|
|
151
|
-
"GiaTriSetTuCHA": null
|
|
152
|
-
}
|
|
153
|
-
]
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
> Put `#PARENT.*` BEFORE startup CALLs so data is ready before the first API runs.
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## 3. Sub-window checklist
|
|
161
|
-
|
|
162
|
-
A module opened via `openWindow` needs:
|
|
163
|
-
|
|
164
|
-
- `"set": { "menu": false }` — hides the navigation header (in module.json, not `?menu=0` in the URL)
|
|
165
|
-
- URL params are injected into `vueData` before `data[]` runs — a trailing `{ "CALL": "apiLoad" }` is enough
|
|
166
|
-
- URL passes only the parent record **ID** the child actually uses — no names or fields re-queryable from the DB
|
|
167
|
-
|
|
168
|
-
```json
|
|
169
|
-
// module.json của module con
|
|
170
|
-
"set": { "menu": false },
|
|
171
|
-
"data": [
|
|
172
|
-
{ "ContestID": null },
|
|
173
|
-
{
|
|
174
|
-
"getDetail": {
|
|
175
|
-
"API": "/SM_Contest_Detail",
|
|
176
|
-
"IN": { "ContestID": "ContestID" },
|
|
177
|
-
"OUT": "dsDetail"
|
|
178
|
-
}
|
|
179
|
-
},
|
|
180
|
-
{ "CALL": "getDetail" }
|
|
181
|
-
]
|
|
182
|
-
// ContestID tự động inject từ URL ?ContestID=xxx trước khi data[] chạy
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
## 4. Complete parent ↔ child example (`ex-v3-1SetData` → `ex-v3-2CauTruc`)
|
|
188
|
-
|
|
189
|
-
Standard: **parent opens child via `openWindow` passing table data; child reads/writes/calls back up to parent.**
|
|
190
|
-
|
|
191
|
-
### 4.1 Parent — f-table + open button, pass `data`
|
|
192
|
-
|
|
193
|
-
`openWindow.IN.data` passes an object/array (here table list `danhSachChoTable`) to the child; child reads `#PARENT.<id>`.
|
|
194
|
-
|
|
195
|
-
```json
|
|
196
|
-
{
|
|
197
|
-
"el": "f-table",
|
|
198
|
-
"attr": {
|
|
199
|
-
"label": "Danh sách",
|
|
200
|
-
":items": "danhSachChoTable",
|
|
201
|
-
":headers": [
|
|
202
|
-
{ "text": "STT", "value": "STT" },
|
|
203
|
-
{ "text": "Họ", "value": "ho" },
|
|
204
|
-
{ "text": "Tên", "value": "ten" }
|
|
205
|
-
]
|
|
206
|
-
},
|
|
207
|
-
"w": "6"
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
"el": "f-button",
|
|
211
|
-
"attr": {
|
|
212
|
-
"label": "Open Window",
|
|
213
|
-
":action": {
|
|
214
|
-
"FUN": "openWindow",
|
|
215
|
-
"IN": {
|
|
216
|
-
"id": "`Win1",
|
|
217
|
-
"title": "`Chỉnh sửa cho module",
|
|
218
|
-
"url": "`/ex/ex-v3-2CauTruc",
|
|
219
|
-
"data": "danhSachChoTable"
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
},
|
|
223
|
-
"w": "3"
|
|
224
|
-
}
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
Parent can also declare **named actions** for the child to call, and write into the child from `data[]`:
|
|
228
|
-
|
|
229
|
-
```json
|
|
230
|
-
"data": [
|
|
231
|
-
{ "#PARENT.abcdef": 1234567890, "#Win1": { "CALL": "cmdTHONGBao" } },
|
|
232
|
-
{
|
|
233
|
-
"cmdSETData": [
|
|
234
|
-
{ "MESS": "Lệnh của form CHA được gọi từ form CON" },
|
|
235
|
-
{ "#Win1.GiaTriSetTuCHA": "Giá trị set từ CHA" }
|
|
236
|
-
]
|
|
237
|
-
}
|
|
238
|
-
]
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### 4.2 Child — read parent, write back, call parent, open another child
|
|
242
|
-
|
|
243
|
-
```json
|
|
244
|
-
// data[] của con: đọc dữ liệu cha NGAY đầu tiên
|
|
245
|
-
"data": [
|
|
246
|
-
{
|
|
247
|
-
"LayDuLieuWinCha": "#PARENT.Win1", // = data cha đã truyền qua openWindow (id=Win1)
|
|
248
|
-
"GiaTriTuCHA.thu.xem": "#PARENT.val7",
|
|
249
|
-
"GiaTriSetTuCHA": null
|
|
250
|
-
}
|
|
251
|
-
],
|
|
252
|
-
"set": { "menu": false, "login": false }
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
```json
|
|
256
|
-
// Các nút trong controls của con:
|
|
257
|
-
{ "el": "f-button", "attr": { "label": "Lấy dữ liệu từ cha",
|
|
258
|
-
":action": { "USERINFO": "#PARENT.val4" } } },
|
|
259
|
-
|
|
260
|
-
{ "el": "f-button", "attr": { "label": "Set dữ liệu xuống cha",
|
|
261
|
-
":action": { "#PARENT.val4": "DauRaTuCauTruc_IN" } } },
|
|
262
|
-
|
|
263
|
-
{ "el": "f-button", "attr": { "label": "Gọi lệnh ở cha",
|
|
264
|
-
":action": { "#PARENT": { "CALL": "cmdSETData" } } } },
|
|
265
|
-
|
|
266
|
-
{ "el": "f-button", "attr": { "label": "Mở thêm form con",
|
|
267
|
-
":action": { "FUN": "openWindow", "IN": {
|
|
268
|
-
"id": "`Win2",
|
|
269
|
-
"url": "`https://fui.vn/ex/ex-v3-1SetData",
|
|
270
|
-
"onclose": { "#Win1": { "CALL": "cmdThongBaoCuaFormNay" } }
|
|
271
|
-
} } } }
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
**Syntax summary (value = read, key = write):**
|
|
275
|
-
|
|
276
|
-
| Syntax | Meaning |
|
|
277
|
-
| ------------------------------ | ------------------------------------------------------ |
|
|
278
|
-
| `"x": "#PARENT.field"` | Read parent `field` into `x` |
|
|
279
|
-
| `"x": "#Win1.field"` | Read `field` of window `Win1` |
|
|
280
|
-
| `"#PARENT.field": "src"` | Write `src` to parent `field` |
|
|
281
|
-
| `"#Win1.field": "src"` | Write to window `Win1` |
|
|
282
|
-
| `"#PARENT": { "CALL": "cmd" }` | Call action `cmd` in parent |
|
|
283
|
-
| `"#Win1": { "CALL": "cmd" }` | Call action in `Win1` |
|
|
284
|
-
| `openWindow.IN.data` | Pass object/array to child; child reads `#PARENT.<id>` |
|
|
285
|
-
| `openWindow.IN.onclose` | Action after child closes (may target `#WinX`) |
|
|
286
|
-
|
|
287
|
-
> Works **same-domain and cross-domain** (runtime uses `postMessage` across domains).
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
## 5. f-table / f-sheet + detail window
|
|
292
|
-
|
|
293
|
-
Common: list table → click a row → open child window to view/edit that row.
|
|
294
|
-
|
|
295
|
-
- In `f-table` `headers`, use `t-button` or `t-menu` with `:action` calling `openWindow`; `item` is the current row.
|
|
296
|
-
- Pass **only the row ID** via URL (child queries DB), or the whole row object via `openWindow.IN.data`.
|
|
297
|
-
|
|
298
|
-
```json
|
|
299
|
-
{
|
|
300
|
-
"el": "t-button",
|
|
301
|
-
"text": "Chi tiết",
|
|
302
|
-
"value": "ID",
|
|
303
|
-
"align": "center",
|
|
304
|
-
"attr": {
|
|
305
|
-
"icon-text": "mdi-eye",
|
|
306
|
-
"color": "primary",
|
|
307
|
-
":action": {
|
|
308
|
-
"FUN": "openWindow",
|
|
309
|
-
"IN": {
|
|
310
|
-
"id": "`WinDetail",
|
|
311
|
-
"title": "`Chi tiết",
|
|
312
|
-
"url": "`/DetailModule?RecordID={{item.ID}}",
|
|
313
|
-
"onclose": { "CALL": "reloadList" }
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
- **`f-sheet`** (grid-entry spreadsheet) works the same: a button/menu in the sheet calls `openWindow`, or save the sheet's `vueData` then open a child for extra input; the child writes back via `#PARENT.<field>` on close.
|
|
321
|
-
- Reload after child closes: `onclose: { "CALL": "reloadList" }` (runs in the opener window) — see §1.
|
|
1
|
+
# FUI Cross-window Patterns — openWindow & data exchange
|
|
2
|
+
|
|
3
|
+
> Owns: **`openWindow`, cross-window data exchange (`#PARENT`/`#Win`), `set.menu` for child modules, `onclose`**.
|
|
4
|
+
|
|
5
|
+
Open a module as a sub-window and exchange data between windows/iframes (`#PARENT`, `#WinID`). From project **security-manager** and `ex-v3-*` examples. See also [ui-patterns.md](ui-patterns.md), [default-function.md](default-function.md) (`openWindow`, `windowSendMessage`).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. openWindow
|
|
10
|
+
|
|
11
|
+
Opens another module as a separate popup window. `id` is the handle for later references.
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"FUN": "openWindow",
|
|
16
|
+
"IN": {
|
|
17
|
+
"id": "`Win1",
|
|
18
|
+
"title": "`User Permission",
|
|
19
|
+
"url": "`/UserPermission",
|
|
20
|
+
"data": "danhSachChoTable",
|
|
21
|
+
"width": "`800px",
|
|
22
|
+
"height": "`600px",
|
|
23
|
+
"onclose": {
|
|
24
|
+
"CALL": "reloadData"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Param | Required | Description |
|
|
31
|
+
| ------------------ | -------- | --------------------------------------------------------------------------- |
|
|
32
|
+
| `id` | ✅ | Window id (backtick = literal) — referenced as `#Win1` |
|
|
33
|
+
| `url` | ✅ | Module URL — no `?menu=0`; child declares `"set": { "menu": false }` itself |
|
|
34
|
+
| `title` | ❌ | Dialog title |
|
|
35
|
+
| `data` | ❌ | Data passed to the child — child reads `#PARENT.data` |
|
|
36
|
+
| `width` / `height` | ❌ | Window size (`"800px"`, `"50%"`) |
|
|
37
|
+
| `onclose` | ❌ | Action run after the sub-window closes |
|
|
38
|
+
|
|
39
|
+
> **Child module:** never pass `?menu=0` in the URL. The child declares `"set": { "menu": false }` in its module.json to hide the menu permanently, regardless of how it's opened. URL carries only the IDs needed to query the DB.
|
|
40
|
+
|
|
41
|
+
**`onclose` targeting another window:**
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
"onclose": {
|
|
45
|
+
"#Win1": { "CALL": "cmdThongBao" }
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
> When Win2 closes → runs `cmdThongBao` in Win1 (not the current window).
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 2. Cross-window data exchange
|
|
54
|
+
|
|
55
|
+
`#PARENT` and `#WinID` exchange data between windows (iframes). Works same-domain and cross-domain (via `postMessage`).
|
|
56
|
+
|
|
57
|
+
### Read (value position)
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
"data": [
|
|
61
|
+
{
|
|
62
|
+
"sUserID": "#PARENT.sUserID",
|
|
63
|
+
"sFullName": "#PARENT.sFullName",
|
|
64
|
+
"dataFromWin1": "#Win1.apiChart"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
| Syntax | Meaning |
|
|
70
|
+
| ----------------- | ------------------------------------------ |
|
|
71
|
+
| `"#PARENT.field"` | Read `vueData.field` from parent |
|
|
72
|
+
| `"#Win1.field"` | Read `vueData.field` from iframe id `Win1` |
|
|
73
|
+
|
|
74
|
+
### Write (key position)
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
"data": [
|
|
78
|
+
{
|
|
79
|
+
"#PARENT.abcdef": 1234567890,
|
|
80
|
+
"#Win1.dulieuTuForm2": "`huynh cao tuan"
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
":action": {
|
|
87
|
+
"#PARENT.val4": "DauRaTuCauTruc_IN"
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
| Syntax | Meaning |
|
|
92
|
+
| ------------------------ | --------------------------------- |
|
|
93
|
+
| `"#PARENT.field": value` | Write to parent's `vueData.field` |
|
|
94
|
+
| `"#Win1.field": value` | Write to Win1's `vueData.field` |
|
|
95
|
+
|
|
96
|
+
### Call an action in another window
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
":action": {
|
|
100
|
+
"#PARENT": { "CALL": "cmdSETData" }
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
"#Win1": { "CALL": "cmdThongBao" }
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- `"#PARENT"` (no field) with an action value → `runAction(value)` in parent
|
|
109
|
+
- `"#Win1"` with an action value → `runAction(value)` in Win1
|
|
110
|
+
|
|
111
|
+
### Receive data passed by openWindow
|
|
112
|
+
|
|
113
|
+
Parent opens child with `"data": "sourceData"`:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
"data": [
|
|
117
|
+
{
|
|
118
|
+
"LayDuLieuWinCha": "#PARENT.Win1"
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
> `#PARENT.Win1` reads parent variable `Win1`. When the parent calls `openWindow` with `id: "Win1"`, FUI sets `vueData.Win1 = passed_data` in the parent before opening.
|
|
124
|
+
|
|
125
|
+
### Full pattern — child receives parent data
|
|
126
|
+
|
|
127
|
+
**Parent (ex-v3-1SetData):**
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
":action": {
|
|
131
|
+
"FUN": "openWindow",
|
|
132
|
+
"IN": {
|
|
133
|
+
"id": "`Win1",
|
|
134
|
+
"url": "`/ex/ex-v3-2CauTruc",
|
|
135
|
+
"data": "danhSachChoTable"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Child (ex-v3-2CauTruc):**
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
"data": [
|
|
144
|
+
{
|
|
145
|
+
"IF": "typeof menu != 'undefined' && menu=='0'",
|
|
146
|
+
"THEN": { "v_Set.menu": false }
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"LayDuLieuWinCha": "#PARENT.Win1",
|
|
150
|
+
"GiaTriTuCHA.thu.xem": "#PARENT.val7",
|
|
151
|
+
"GiaTriSetTuCHA": null
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
> Put `#PARENT.*` BEFORE startup CALLs so data is ready before the first API runs.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 3. Sub-window checklist
|
|
161
|
+
|
|
162
|
+
A module opened via `openWindow` needs:
|
|
163
|
+
|
|
164
|
+
- `"set": { "menu": false }` — hides the navigation header (in module.json, not `?menu=0` in the URL)
|
|
165
|
+
- URL params are injected into `vueData` before `data[]` runs — a trailing `{ "CALL": "apiLoad" }` is enough
|
|
166
|
+
- URL passes only the parent record **ID** the child actually uses — no names or fields re-queryable from the DB
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
// module.json của module con
|
|
170
|
+
"set": { "menu": false },
|
|
171
|
+
"data": [
|
|
172
|
+
{ "ContestID": null },
|
|
173
|
+
{
|
|
174
|
+
"getDetail": {
|
|
175
|
+
"API": "/SM_Contest_Detail",
|
|
176
|
+
"IN": { "ContestID": "ContestID" },
|
|
177
|
+
"OUT": "dsDetail"
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
{ "CALL": "getDetail" }
|
|
181
|
+
]
|
|
182
|
+
// ContestID tự động inject từ URL ?ContestID=xxx trước khi data[] chạy
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 4. Complete parent ↔ child example (`ex-v3-1SetData` → `ex-v3-2CauTruc`)
|
|
188
|
+
|
|
189
|
+
Standard: **parent opens child via `openWindow` passing table data; child reads/writes/calls back up to parent.**
|
|
190
|
+
|
|
191
|
+
### 4.1 Parent — f-table + open button, pass `data`
|
|
192
|
+
|
|
193
|
+
`openWindow.IN.data` passes an object/array (here table list `danhSachChoTable`) to the child; child reads `#PARENT.<id>`.
|
|
194
|
+
|
|
195
|
+
```json
|
|
196
|
+
{
|
|
197
|
+
"el": "f-table",
|
|
198
|
+
"attr": {
|
|
199
|
+
"label": "Danh sách",
|
|
200
|
+
":items": "danhSachChoTable",
|
|
201
|
+
":headers": [
|
|
202
|
+
{ "text": "STT", "value": "STT" },
|
|
203
|
+
{ "text": "Họ", "value": "ho" },
|
|
204
|
+
{ "text": "Tên", "value": "ten" }
|
|
205
|
+
]
|
|
206
|
+
},
|
|
207
|
+
"w": "6"
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"el": "f-button",
|
|
211
|
+
"attr": {
|
|
212
|
+
"label": "Open Window",
|
|
213
|
+
":action": {
|
|
214
|
+
"FUN": "openWindow",
|
|
215
|
+
"IN": {
|
|
216
|
+
"id": "`Win1",
|
|
217
|
+
"title": "`Chỉnh sửa cho module",
|
|
218
|
+
"url": "`/ex/ex-v3-2CauTruc",
|
|
219
|
+
"data": "danhSachChoTable"
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
"w": "3"
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Parent can also declare **named actions** for the child to call, and write into the child from `data[]`:
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
"data": [
|
|
231
|
+
{ "#PARENT.abcdef": 1234567890, "#Win1": { "CALL": "cmdTHONGBao" } },
|
|
232
|
+
{
|
|
233
|
+
"cmdSETData": [
|
|
234
|
+
{ "MESS": "Lệnh của form CHA được gọi từ form CON" },
|
|
235
|
+
{ "#Win1.GiaTriSetTuCHA": "Giá trị set từ CHA" }
|
|
236
|
+
]
|
|
237
|
+
}
|
|
238
|
+
]
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 4.2 Child — read parent, write back, call parent, open another child
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
// data[] của con: đọc dữ liệu cha NGAY đầu tiên
|
|
245
|
+
"data": [
|
|
246
|
+
{
|
|
247
|
+
"LayDuLieuWinCha": "#PARENT.Win1", // = data cha đã truyền qua openWindow (id=Win1)
|
|
248
|
+
"GiaTriTuCHA.thu.xem": "#PARENT.val7",
|
|
249
|
+
"GiaTriSetTuCHA": null
|
|
250
|
+
}
|
|
251
|
+
],
|
|
252
|
+
"set": { "menu": false, "login": false }
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
// Các nút trong controls của con:
|
|
257
|
+
{ "el": "f-button", "attr": { "label": "Lấy dữ liệu từ cha",
|
|
258
|
+
":action": { "USERINFO": "#PARENT.val4" } } },
|
|
259
|
+
|
|
260
|
+
{ "el": "f-button", "attr": { "label": "Set dữ liệu xuống cha",
|
|
261
|
+
":action": { "#PARENT.val4": "DauRaTuCauTruc_IN" } } },
|
|
262
|
+
|
|
263
|
+
{ "el": "f-button", "attr": { "label": "Gọi lệnh ở cha",
|
|
264
|
+
":action": { "#PARENT": { "CALL": "cmdSETData" } } } },
|
|
265
|
+
|
|
266
|
+
{ "el": "f-button", "attr": { "label": "Mở thêm form con",
|
|
267
|
+
":action": { "FUN": "openWindow", "IN": {
|
|
268
|
+
"id": "`Win2",
|
|
269
|
+
"url": "`https://fui.vn/ex/ex-v3-1SetData",
|
|
270
|
+
"onclose": { "#Win1": { "CALL": "cmdThongBaoCuaFormNay" } }
|
|
271
|
+
} } } }
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**Syntax summary (value = read, key = write):**
|
|
275
|
+
|
|
276
|
+
| Syntax | Meaning |
|
|
277
|
+
| ------------------------------ | ------------------------------------------------------ |
|
|
278
|
+
| `"x": "#PARENT.field"` | Read parent `field` into `x` |
|
|
279
|
+
| `"x": "#Win1.field"` | Read `field` of window `Win1` |
|
|
280
|
+
| `"#PARENT.field": "src"` | Write `src` to parent `field` |
|
|
281
|
+
| `"#Win1.field": "src"` | Write to window `Win1` |
|
|
282
|
+
| `"#PARENT": { "CALL": "cmd" }` | Call action `cmd` in parent |
|
|
283
|
+
| `"#Win1": { "CALL": "cmd" }` | Call action in `Win1` |
|
|
284
|
+
| `openWindow.IN.data` | Pass object/array to child; child reads `#PARENT.<id>` |
|
|
285
|
+
| `openWindow.IN.onclose` | Action after child closes (may target `#WinX`) |
|
|
286
|
+
|
|
287
|
+
> Works **same-domain and cross-domain** (runtime uses `postMessage` across domains).
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 5. f-table / f-sheet + detail window
|
|
292
|
+
|
|
293
|
+
Common: list table → click a row → open child window to view/edit that row.
|
|
294
|
+
|
|
295
|
+
- In `f-table` `headers`, use `t-button` or `t-menu` with `:action` calling `openWindow`; `item` is the current row.
|
|
296
|
+
- Pass **only the row ID** via URL (child queries DB), or the whole row object via `openWindow.IN.data`.
|
|
297
|
+
|
|
298
|
+
```json
|
|
299
|
+
{
|
|
300
|
+
"el": "t-button",
|
|
301
|
+
"text": "Chi tiết",
|
|
302
|
+
"value": "ID",
|
|
303
|
+
"align": "center",
|
|
304
|
+
"attr": {
|
|
305
|
+
"icon-text": "mdi-eye",
|
|
306
|
+
"color": "primary",
|
|
307
|
+
":action": {
|
|
308
|
+
"FUN": "openWindow",
|
|
309
|
+
"IN": {
|
|
310
|
+
"id": "`WinDetail",
|
|
311
|
+
"title": "`Chi tiết",
|
|
312
|
+
"url": "`/DetailModule?RecordID={{item.ID}}",
|
|
313
|
+
"onclose": { "CALL": "reloadList" }
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
- **`f-sheet`** (grid-entry spreadsheet) works the same: a button/menu in the sheet calls `openWindow`, or save the sheet's `vueData` then open a child for extra input; the child writes back via `#PARENT.<field>` on close.
|
|
321
|
+
- Reload after child closes: `onclose: { "CALL": "reloadList" }` (runs in the opener window) — see §1.
|