kibatic / ux-bundle
Requires
- php: >=8.2.0
- symfony/config: ^6.0|^7.0
- symfony/dependency-injection: ^6.0|7.0
- symfony/http-kernel: ^6.0|^7.0
README
安装
composer require kibatic/ux-bundle yarn install --force
要使用 modal stayOnSuccess 选项,请将以下内容添加到您的 app.js 中
import TurboHelper from "@kibatic/ux-bundle/dist/turbo-helper";
待办:下一步应该用 flex 自动完成
// assets/controllers.json
{
"controllers": {
// ...
"@kibatic/ux-bundle": {
"modal": {
"enabled": true,
"fetch": "eager"
},
"global-modal-stack": {
"enabled": true,
"fetch": "eager"
},
"global-modal-trigger": {
"enabled": true,
"fetch": "eager"
},
"alert": {
"enabled": true,
"fetch": "eager"
}
}
}
// ...
}
然后构建您的资产。
利用
打开全局 modal
1 - 链接
{% include '@KibaticUX/_turbo-modal-link.html.twig' with { 'link_url': path('ma_route', {'clef': 'valeur'}), 'link_text': 'Mon lien', 'link_class': 'jolie_lien', 'frame_target_top': false, 'close_on_success': false, } %}
frame_target_top
: (默认:true
) 如果false
,则来自 modal 框架的链接和重定向将在其中跟随。
(更多选项信息见下方)
2 - 按钮
{% include '@KibaticUX/_turbo-offcanvas-btn.html.twig' with { 'btn_url': path('app_user_edit', {'id': 123}), 'btn_text': 'Modifier', 'btn_icon': 'edit', 'btn_size': 'large', 'frame_target_top': false, 'close_on_success': false, } %}
btn_text
: (默认:显示
)btn_class
: (默认:btn btn-{btn_size}
)btn_size
: (默认:medium
)
(更多选项信息见下方)
打开本地 modal
与全局 modal 不同,全局 modal 主要用于通过 URL 载入 turbo-frame(尤其是同时载入多个),本地 modal 允许将页面的一部分 HTML 放入 modal 中。例如,表单的一部分。
<button type="button" data-bs-toggle="modal" data-bs-target="#ma-modal">Plus de préférences</button> {% embed 'common/stimulus-modal.html.twig' with {modal_id: 'ma-modal'} %} {% set modal_title %}Mes préférences{% endset %} {% set modal_content %} {{ form_row(form.sports) }} {{ form_row(form.films) }} {{ form_row(form.plats) }} {% endset %} {% endembed %}
页面内容框架的原理
通过网站的布局,将所有页面的内容包裹在一个具有 id
"page-content" 的 turbo-frame 中。这允许通过将相同的 id 和页面的 URL 传递给 turbo-frame 来轻松地将页面插入到另一个页面中。
这是 modal turbo-frame 通过目标 URL 搜索的默认 id。
不同的选项和行为
1 - 在 modal 中成功提交后关闭
使用 close_on_success
选项(true/false),当从 modal 中提交表单且提交成功(因此不是状态 40x/50x)时,该 modal 将自动关闭。
如果您想使用此选项,同时排除特定表单的行为(例如:modal 中的列表过滤表单),您可以在表单上添加 data-ignored-by-modal="true"
属性。
2 - 成功提交后是否重定向(stay/follow)
当一个 canvas 打开(全局或非全局)并包含一个 turbo-frame 时,如果它不是第一个打开的 modal,则认为它是嵌套的(从另一个 modal 打开或“嵌套”在代码中)。
当包含 turbo-frame 的嵌套全局 modal 显示时,它包含的表单将自动标记为 data-turbo-on-success="stay"
。
第一个打开的全局 modal 将具有 data-turbo-on-success="follow"
属性。
此属性的效果是向表单请求中添加一个 HTTP 头 Turbo-On-Success
,然后后端会考虑这个头,以决定在成功的情况下,响应将是重定向(follow
)还是包含可能的 flash 消息的 turbo-stream(stay
)。此行为由 Kibatic\UX\EventListener\ResponseListener
管理。
从另一个 modal 更新 modal
案例 1:最常见的情况
最常见的情况是,您希望在从 modal 执行操作后更新主页面内容。例如,您在 /user/list
页面,您想打开一个 modal 来修改列表中的一个用户,并在表单提交成功时更新 "page-content" 块,以便您的修改反映在列表中。
{% include 'common/_turbo-modal-btn.html.twig' with { 'btn_url': path('app_user_edit', {'id': user.id}), 'btn_text': 'Modifier', 'btn_icon': 'edit', 'related_turbo_frames': ['#page-content'] } %}
如果您的页面包含多个 turbo frame,例如包含用户列表、订单列表等的仪表板,您也可以添加比 #page-content
更精确的选择器,并精确地定位到相关的 turbo frame。
存在一个与使用(上文已解释)"page-content" id有关的问题,尤其是在您使用"relatedTurboFrames"功能时。由于模态框默认基于此id来隔离目标URL的内容,如果您打开多个模态框并想更新其中一个,您将只能使用"page-content" id来定位模态框,但这个id将对应页面中的多个frame,这将导致更新比预期更多的内容。这种情况通常不会造成太大麻烦,但如果您的"page-content"内容非常丰富,就需要注意这一点。
案例2:Live组件
这是一个更高级的案例,在发票的Live组件中,对于每一行发票,我们都可以选择一个产品。这个选择通过发票表单中的下拉列表实现,但由于Live组件的自动更新机制,我们不能简单地在一个模态框中放置该字段并展示给用户,因为每当Live组件更新时,它都会覆盖其DOM,导致模态框被重置为关闭状态。未来,Live组件应该能够更智能地处理这种类型的场景,即需要保留围绕某个要更新的DOM的部分DOM修改。为了解决这个问题,组件的JS会复制下拉列表字段(updateProductFieldProxy),并将这个“代理”放入模态框中。这样,我们就可以通过"数据-live-ignore"属性排除模态框中的所有DOM。因此,真正的表单字段可以继续由Live组件更新,而不会影响模态框。然后,每当Live组件刷新时,账单行的JS会负责更新代理,并保留模态框。
当从模态框(从产品选择打开)添加新产品时,这一点尤其有用。一般来说,在账单的Live组件中,每当模态框关闭时(通过<span data-action="modal.closed@window->live#$render"></span>
),我们会“手动”触发Live组件的刷新。由于创建产品的模态框设置为"close-on-success=true",一旦表单提交成功,模态框就会关闭。这会触发Live组件的更新,真正的隐藏选择产品字段会更新为新创建的产品选择,然后这个新选项会复制到代理中(正如前面描述的账单行的JS所做的那样)。