ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

marimo form 表单组件:延迟提交 UI 值、组合多元素与自定义校验的完整指南

marimo form 表单组件:延迟提交 UI 值、组合多元素与自定义校验的完整指南 marimo form 表单组件延迟提交 UI 值、组合多元素与自定义校验的完整指南【免费下载链接】marimoA reactive notebook for Python — run reproducible experiments, query with SQL, execute as a script, deploy as an app, and version with git. Stored as pure Python. All in a modern, AI-native editor.项目地址: https://gitcode.com/GitHub_Trending/ma/marimo导读在 marimo 交互式笔记本中大部分 UI 元素如滑块、文本框的值变化会实时推送到 Python 运行时并触发下游单元格重新执行。但很多场景下我们希望用户先完成一组输入、再统一提交例如填写完整个表单后点击提交按钮才运行计算。marimo 的form组件正是为此设计的它把任意 UI 元素包装成一个可提交表单值只有在点击 Submit 按钮后才会传回 Python。本文基于 docs/api/inputs/form.md 与仓库源码marimo/_plugins/ui/_impl/input.py展开介绍form的两种创建方式、全部构造参数、batch多元素组合、自定义校验函数、与on_change的交互机制并通过测试用例印证其行为。form 是什么门控 UI 值提交的包装器核心语义从源码看form是一个继承自UIElement[JSONTypeBound | None, T | None]的类marimo/_plugins/ui/_impl/input.py它的职责在类文档字符串中写得很明确Use aformto prevent sending UI element values to Python until a button is clicked.使用 form 来阻止 UI 元素值在按钮被点击之前发送到 Python。form的值是底层元素在最后一次提交时的值The value of aformis the value of the underlying element the last time the form was submitted。也就是说用户在表单里拖动滑块、修改文本Python 端form.value不会跟着变只有点击 Submit 按钮完成一次提交后form.value才会更新为当前元素的快照值在未提交过任何内容时form.value为None构造时initial_valueNone。form组件还有两个值得注意的属性value最后一次点击提交按钮时被包装元素的值element被包装元素的一个拷贝源码中通过element._clone()获得input.py。值转换的底层机制form的前端值经过_convert_value转换为 Python 值input.pydef _convert_value(self, value: JSONTypeBound | None) - T | None: if value is None: return None self.element._update_value(value) return self.element.value即提交的值value会先更新到内部克隆元素self.element上然后返回该元素转换后的值。这意味着form.value的类型与被包装元素一致slider.form().value是数值、text.form().value是字符串、batch(...).form().value是字典。创建表单的两种方式方式一链式调用.form()任何UIElement都有.form()方法定义于 marimo/_plugins/ui/_core/ui_element.py它本质上是form类的便捷构造函数把参数原样转发给form插件import marimo as mo # 一个文本框表单占位符为 ... form mo.ui.text_area(placeholder...).form()方式二直接实例化mo.ui.form也可以显式传入被包装元素form mo.ui.form(elementmo.ui.slider(1, 100))两种方式等价UIElement.form()内部会执行return form_plugin( elementself, labellabel, borderedbordered, ... )见 ui_element.py。一个最小的可运行示例原文档 form.md 给出了最简示例——用mo.vstack把表单和它的值显示并排展示import marimo as mo app.cell def __(): form mo.ui.text_area(placeholder...).form() return app.cell def __(): mo.vstack([form, mo.md(fHas value: {form.value})]) return注意示例把form的创建与读取分放在两个单元格这是 marimo 的约束——在创建该 UI 元素的同一单元格内直接读取form.value会抛出RuntimeErrorAccessing the value of a UIElement in the cell that created it is not allowed见 ui_element.py。因此务必将创建元素与消费元素值分离到不同单元格。未提交前form.value为None页面显示Has value: None在文本框中输入内容并点击Submit后form.value才会变为所输入的字符串。构造参数详解form的完整构造签名input.pyform( element, # 被包装的 UIElement *, # 以下全部为关键字参数 bordered: bool True, loading: bool False, submit_button_label: str Submit, submit_button_tooltip: str | None None, submit_button_disabled: bool False, clear_on_submit: bool False, show_clear_button: bool False, clear_button_label: str Clear, clear_button_tooltip: str | None None, validate: Callable[[JSONType | None], str | None] | None None, label: str , on_change: Callable[[T | None], None] | None None, )参数默认值说明element必填被包装的UIElementborderedTrue表单是否显示边框loadingFalse表单是否处于加载loading状态submit_button_labelSubmit提交按钮的文本submit_button_tooltipNone提交按钮的悬浮提示submit_button_disabledFalse提交按钮是否禁用可与校验配合在条件不满足时禁止提交clear_on_submitFalse提交后是否清空表单内容show_clear_buttonFalse是否显示清空按钮clear_button_labelClear清空按钮的文本clear_button_tooltipNone清空按钮的悬浮提示validateNone校验函数接收表单值返回错误消息字符串返回None表示校验通过label表单的 Markdown 标签on_changeNone当元素值改变即表单被提交时执行的回调这些参数会被序列化到前端组件参数中input.py其中should-validate: validate is not None控制前端是否开启校验流程validate函数本身通过Function(namevalidate, arg_clsValueArgs, functionself._validate)注册为可被前端调用的后端函数input.py。组合多个元素.batch(...).form(...)单个表单往往需要包含多个输入。marimo 提供了mo.md模板插值配合.batch()的方法batch把一段带{占位符}的 Markdown/HTML 模板与若干 UI 元素绑定形成一个值为字典的复合 UI 元素定义于 marimo/_output/hypertext.py。结合form可以构建填写姓名 选择日期的复合表单import marimo as mo form ( mo.md( **Your form.** {name} {date} ) .batch( namemo.ui.text(labelname), datemo.ui.date(labeldate), ) .form(show_clear_buttonTrue, borderedFalse) )其值为字典结构form.value[name]是提交时的姓名文本form.value[date]是提交时的日期。这正是原文档中Create a form with multiple elements的官方示例input.py。batch生成的元素值形如{name: ..., date: ...}提交时form.value即为该字典。使用校验函数validate拦截无效输入validate是form最实用的高级特性它接收表单的值JSONType | None返回错误消息字符串或None通过时。例如import marimo as mo # 要求输入至少 5 个字符 form mo.ui.text(placeholder用户名).form( validatelambda value: ( None if value is not None and len(value) 5 else 用户名至少需要 5 个字符 ) )源码层面的工作方式构造时should-validate: validate is not None告诉前端需要调用后端校验input.py前端提交时通过Function通道调用后端_validateinput.pydef _validate(self, value: ValueArgs) - str | None: if self.validate is None: return None return self.validate(value.value)校验失败时返回错误消息字符串前端据此展示错误并阻止本次提交生效校验通过返回None则正常提交。validate也可以与submit_button_disabled配合实现条件未满足时禁用提交按钮的交互。提交语义与 on_change不触发被包装元素的回调一个常见疑惑是提交表单时被包装元素如text、array自身的on_change会不会被触发答案是不会。form提交时通过self.element._update_value(value)更新内部元素值input.py。与_update会调用on_change不同_update_value明确注释为 Update value, given a value from the frontendwithout calling on_changeui_element.py。仓库测试 tests/_plugins/ui/_impl/test_input.py 用三个用例系统地验证了这一行为test_form_submits_without_triggering_element_on_change约 L866单个元素包成表单提交时不触发元素自身的on_changetest_form_with_array_submits_without_triggering_elements_on_change约 L885元素位于array中时同样不触发test_form_with_batch_submits_without_triggering_elements_on_change约 L907元素来自batch组合时同样不触发。而form自己声明的on_change构造时的on_change参数会在表单提交、值更新后被调用回调收到的参数是提交后的值T | None。测试test_form_in_array_retains_on_change约 L734与test_form_in_dictionary_allowed约 L742还验证了form可以嵌套在array/dictionary等容器元素中并保留自身的on_change行为。典型应用场景小结结合以上机制form的适用场景包括延迟执行把昂贵的计算包装在表单之后用户确认参数再点击 Submit避免每次拖动滑块都触发下游重算批量输入用mo.md(...).batch(...).form()把多个字段组织成一个结构化字典一次性提交输入校验用validate在提交前校验格式、范围把错误提示留在前端受控提交用clear_on_submit清空内容、show_clear_button提供重置能力、loading表达异步处理中状态。如需进一步了解与其他输入组件的组合用法可参考 docs/api/inputs/index.md 与 examples/ui/batch_and_form.py 中的完整示例batch的更多细节见 docs/api/inputs/batch.md 与 marimo/_plugins/ui/_impl/batch.py。【免费下载链接】marimoA reactive notebook for Python — run reproducible experiments, query with SQL, execute as a script, deploy as an app, and version with git. Stored as pure Python. All in a modern, AI-native editor.项目地址: https://gitcode.com/GitHub_Trending/ma/marimo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表