关于 variable-creation
这项技能用于在 Domo 卡片上创建下拉菜单、滑块和日期选择器等交互变量,面向构建假设分析的用户。它说明所需的 API 调用顺序及 community-domo-cli 操作流程。
主要功能
- 01创建下拉、选项块、滑块、文本框和日期控件
- 02支持字符串、数值和日期变量
- 03检查变量名称是否唯一
- 04注册控件并保存卡片定义
- 05通过 community-domo-cli 创建变量
适用场景
- 01为卡片添加区域选择器
- 02构建用于假设分析的可调输入
- 03为卡片公式创建日期控件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ stahura/ domo-ai-vibe-rules --skill variable-creation安装后在 Claude Code 中输入/variable-creation确认已加载。
详细介绍
变量创建
创建 Domo 卡片变量(交互式控件),并输出用于执行它们的 curl 命令或 CLI 命令。
变量是用户可调整的值,会传入 Beast Mode 公式,从而实现动态假设分析。它们以卡片和仪表板上的下拉框、胶囊按钮、滑块、文本框或日期选择器控件的形式出现。
何时使用此技能
- 用户要求在卡片上添加下拉框、滑块或交互式控件
- 用户提到 "变量"、"参数",或描述想要动态/可调整的值
- 卡片需要进行假设分析或用户可选择的输入
- 你正在构建卡片,并意识到某个 beast mode 需要用户控制的输入
核心工作流 — 三步创建
变量创建需要三次按顺序进行的 API 调用。三次调用均为必需 — 跳过中间步骤会导致卡片保存时出现 400 错误。
1. Check name uniqueness (GET /query/v1/functions/variables/uniqueName)
2. Create the function template WITH embedded control (POST /query/v1/functions/template)
3. Register the variable control (PUT /content/v1/variable/controls)
4. Read the current card definition (PUT /content/v3/cards/kpi/definition)
5. Save the card with the new control (PUT /content/v3/cards/kpi/{cardId})
先决条件
| 参数 | 来源 | 是否必需 |
|---|---|---|
instanceUrl | Domo 实例(例如 domo-gordon-pont.domo.com) | 始终必需 |
devToken | CLI 认证 / 开发者令牌 | 始终必需 |
cardId | 卡片 ID | 始终必需 |
dataSourceId | 数据集 UUID(来自卡片定义或列) | 用于验证和卡片保存 |
变量数据类型
| 数据类型 | 表达式示例 | 兼容的控件 |
|---|---|---|
string | 'TEST'、'Option A' | DROPDOWN、PILL、TEXTBOX |
numeric | 100、0.5 | DROPDOWN、PILL、SLIDER、TEXTBOX |
date | CURRENT_DATE()、'2024-01-01' | DROPDOWN、DATE_PICKER |
变量控件类型
| 类型 | 描述 | 最适合 |
|---|---|---|
DROPDOWN | 从预定义值列表中选择 | 分类选择、字符串/数值/日期 |
PILL | 内联切换胶囊按钮 | 少量选项(2-5 个) |
SLIDER | 数值范围滑块 | 带最小/最大值的数值范围 |
TEXTBOX | 自由文本输入 | 开放式的字符串/数值输入 |
DATE_PICKER | 日历日期选择器 | 日期变量 |
按数据类型划分的表达式类型
| 数据类型 | exprType |
|---|---|
string | STRING_VALUE |
numeric | NUMERIC_VALUE |
date | DATE_VALUE |
values 数组
对于 DROPDOWN 和 PILL 控件,values 数组定义可选择的选项:
{"expression": {"value": "Option Text", "exprType": "STRING_VALUE"}}
对于 SLIDER 控件,values 定义最小/最大范围:
[
{"expression": {"value": "0", "exprType": "NUMERIC_VALUE"}},
{"expression": {"value": "100", "exprType": "NUMERIC_VALUE"}}
]
步骤 1:检查名称唯一性
端点: GET /api/query/v1/functions/variables/uniqueName?name={name}
curl -X GET "https://{instanceUrl}/api/query/v1/functions/variables/uniqueName?name={variableName}" \
-H "X-DOMO-Developer-Token: {devToken}"
如果该名称可用,则返回 []。如果该名称已被使用,则返回一个函数模板 ID 数组。变量名称在整個 Domo 实例中必须全局唯一。
第 2 步:创建函数模板
端点: POST /api/query/v1/functions/template
这会创建变量的函数模板。请求体必须包含一个内嵌的 control 对象——这一点至关重要,并且与常规 beast mode 创建方式不同。
curl -X POST "https://{instanceUrl}/api/query/v1/functions/template" \
-H "X-DOMO-Developer-Token: {devToken}" \
-H "Content-Type: application/json" \
-d '{
"name": "{variableName}",
"formula": "{defaultExpression}",
"status": "VALID",
"dataType": "{dataType}",
"persistedOnDataSource": false,
"isAggregatable": true,
"bignumber": false,
"owner": null,
"nonAggregatedColumns": [],
"legacyId": "calculation_{uuid}",
"variable": true,
"isCalculation": true,
"initialPersistedOnDataSource": false,
"saved": true,
"query": "{defaultExpression}",
"control": {
"format": {"type": "default"},
"controlType": "VARIABLE",
"function": {
"name": "{variableName}",
"dataType": "{dataType}",
"expression": "{defaultExpression}",
"id": -201
},
"saveOverride": true,
"description": "",
"values": [
{"expression": {"value": "{value1}", "exprType": "{exprType}"}},
{"expression": {"value": "{value2}", "exprType": "{exprType}"}}
],
"type": "{controlType}",
"unsaved": true,
"name": "{variableName}",
"id": -101
},
"description": "",
"locked": false,
"cacheWindow": "non_dynamic",
"containsAggregation": false,
"containsAnalytic": false,
"invalidColumns": [],
"nonAggregatedExpressions": [],
"formulaTemplateDependencies": [],
"columnPositions": [],
"formulaId": "calculation_{another_uuid}",
"formulaDependencies": [],
"isControlled": false,
"global": true,
"unsaved": true,
"expression": "{defaultExpression}"
}'
关键字段:
variable: true— 将其标记为变量函数(而非常规 beast mode)control— 内嵌的 control 定义,带有占位符 ID(-201、-101)legacyId和formulaId— 生成格式为calculation_{uuid}的唯一 UUIDglobal: true— 变量在整个实例范围内有效owner: null— 由服务端分配 owner
响应 — 保存 id(数字型函数模板 ID):
{
"id": 1172,
"name": "{variableName}",
"legacyId": "calculation_{uuid}",
"variable": true,
...
}
第 3 步:注册变量 Control
端点: PUT /api/content/v1/variable/controls
此步骤将 control 注册到 Domo control 系统。若缺少此步骤,保存卡片将返回 400。
curl -X PUT "https://{instanceUrl}/api/content/v1/variable/controls" \
-H "X-DOMO-Developer-Token: {devToken}" \
-H "Content-Type: application/json" \
-d '[
{
"format": {"type": "default"},
"controlType": "VARIABLE",
"function": {
"name": "{variableName}",
"dataType": "{dataType}",
"expression": "{defaultExpression}",
"id": {functionTemplateId from Step 2}
},
"saveOverride": true,
"description": "",
"values": [
{"expression": {"value": "{value1}", "exprType": "{exprType}"}},
{"expression": {"value": "{value2}", "exprType": "{exprType}"}}
],
"type": "{controlType}",
"unsaved": false,
"name": "{variableName}"
}
]'
与第 2 步中 control 的关键区别:
function.id现在是第 2 步返回的真实模板 ID(不再是-201)unsaved: false(不再是true)- control 层级上不再有
id: -101 - 请求体是 control 对象的数组
响应 — 返回一个包含已注册 control 的数组,其中含有服务端分配的 id:
[
{
"id": 145,
"function": {"id": 1172, ...},
"type": "DROPDOWN",
"values": [...],
"controlType": "VARIABLE",
...
}
]
第 4 步:读取当前卡片定义
curl -X PUT "https://{instanceUrl}/api/content/v3/cards/kpi/definition" \
-H "X-DOMO-Developer-Token: {devToken}" \
-H "Content-Type: application/json" \
-d '{
"dynamicText": true,
"variables": true,
"urn": "{cardId}"
}'
保存完整响应。你需要 definition.subscriptions、definition.controls、definition.charts、definition.modified 等。
从响应中的 columns[].sourceId 获取 dataSourceId。
第 5 步:使用新 Control 保存卡片
端点: PUT /api/content/v3/cards/kpi/{cardId}
通过将新 control 合并到卡片定义中,构建更新请求体。
curl -X PUT "https://{instanceUrl}/api/content/v3/cards/kpi/{cardId}" \
-H "X-DOMO-Developer-Token: {devToken}" \
-H "Content-Type: application/json" \
-d '{
"definition": {
"subscriptions": {existing subscriptions from card def — do NOT add dataSourceId here},
"formulas": {"dsUpdated": [], "dsDeleted": [], "card": []},
"annotations": {"new": [], "modified": [], "deleted": []},
"conditionalFormats": {"card": [], "datasource": []},
"controls": [{existing controls with saveOverride: true}, {new control}],
"segments": {"active": [], "create": [], "update": [], "delete": []},
"charts": {existing charts},
"dynamicTitle": {existing dynamicTitle},
"dynamicDescription": {"text": []},
"chartVersion": "{existing chartVersion}",
"allowTableDrill": true,
"inputTable": false,
"modified": {existing modified timestamp},
"title": "{card title}",
"description": ""
},
"dataProvider": {"dataSourceId": "{dataSourceId}"},
"variables": true,
"columns": false
}'
请求体的关键注意事项:
- 顶层需有
variables: true和columns: false dataSourceId只放在dataProvider中——不要放在subscriptions.main中formulas使用{dsUpdated, dsDeleted, card}结构(而非读取响应中的数组格式)- 现有 control 必须以其完整的服务端格式传入,并添加
saveOverride: true - 新 control 使用简化格式,其中
function.id= 第 2 步返回的模板 ID modified时间戳必须与卡片定义中的值一致
可选:验证变量公式
端点: POST /api/query/v1/functions/validateFormulas
验证是可选的,但建议在创建前执行。公式条目必须带有 "variable": true。
curl -X POST "https://{instanceUrl}/api/query/v1/functions/validateFormulas" \
-H "X-DOMO-Developer-Token: {devToken}" \
-H "Content-Type: application/json" \
-d '{
"dataSourceId": "{dataSourceId}",
"columns": [{column schema array}],
"formulas": {
"{formulaId}": {
"id": "{formulaId}",
"name": "{variableName}",
"formula": "{defaultExpression}",
"status": "valid",
"dataType": "{dataType}",
"variable": true,
"templateId": null,
"legacyId": "{formulaId}",
"formulaDependencies": []
}
}
}'
在 Beast Mode 中使用变量
除非在 Beast Mode 公式中引用变量,否则它对卡片没有任何影响:
CASE
WHEN `My Variable` = 'Option A' THEN `column_a`
WHEN `My Variable` = 'Option B' THEN `column_b`
ELSE `column_a`
END
变量通过反引号中的名称来引用,就像数据集列一样。
三层 Control 层级结构
变量有三个层级的覆盖:
- 默认 Control — 在 Beast Mode 编辑器中设置(或通过 API)。基准值。
- 卡片变量 Control — 在 Analyzer 中为特定卡片覆盖。不会传递到仪表板。
- 仪表板变量 Control — 在特定仪表板上覆盖。页面刷新后重置。
使用 CLI
community-domo-cli 会自动处理完整的三步流程:
# Check if a variable name is available
community-domo-cli variables check-name "My Variable"
# List variables on a card
community-domo-cli variables list {cardId}
# Create a variable (handles all 3 steps internally)
community-domo-cli variables create {cardId} --body-file variable.json
# Validate a variable formula
community-domo-cli variables validate --body-file validate-payload.json
# Read full card definition (includes controls)
community-domo-cli cards definition {cardId}
示例:通过 CLI 创建字符串下拉变量
variable.json:
{
"name": "Region Selector",
"type": "DROPDOWN",
"function": {
"name": "Region Selector",
"dataType": "string",
"expression": "'North'"
},
"description": "Select a region to filter by",
"values": [
{"expression": {"value": "North", "exprType": "STRING_VALUE"}},
{"expression": {"value": "South", "exprType": "STRING_VALUE"}},
{"expression": {"value": "East", "exprType": "STRING_VALUE"}},
{"expression": {"value": "West", "exprType": "STRING_VALUE"}}
]
}
community-domo-cli variables create 1810280719 --body-file variable.json --yes
CLI 会自动:
- 检查名称唯一性
- 创建带有内嵌 control 的函数模板
- 通过
PUT /content/v1/variable/controls注册 control - 读取卡片定义
- 合并并保存卡片
故障排查
| 问题 | 原因 | 修复方法 |
|---|---|---|
| 变量在卡片上不可见 | 未在任何 beast mode 中引用 | 创建一个使用该变量的 beast mode |
| 卡片保存返回 400 | 缺少 PUT /content/v1/variable/controls 步骤 | 必须在保存卡片前注册该控件 |
| 卡片保存返回 400 | subscriptions.main 中的 dataSourceId | 将其移除 — 只把 dataSourceId 放在 dataProvider 中 |
| 卡片保存返回 400 | 现有控件不是完整的服务器格式 | 从卡片定义中原样传入现有控件,并设置 saveOverride: true |
| 500 内部数据库错误 | 变量名重复 | 先用 GET /query/v1/functions/variables/uniqueName 检查名称 |
校验返回 INVALID | 表达式语法错误 | 检查字符串的引号、日期的函数语法 |
| 仪表板不显示变量控件 | 卡片级覆盖不会向上传播 | 在仪表板级设置该控件 |
| 仪表板刷新时变量重置 | 预期行为 | 仪表板控件在页面加载时重置为默认值 |
输出格式
在为用户生成命令时,请提供:
- 它的作用 — 用一句话说明该变量
- 变量定义 — 名称、类型、默认值、控件类型、选项
- 编号命令 — 按执行顺序(全部 3 个步骤),可直接复制/粘贴
- 如何处理每个响应 — 尤其是保存第 2 步中的函数模板 ID
- Beast mode 集成 — 展示引用该变量的公式
- 验证 — 告诉他们在运行后于 Domo 中检查该卡片