导航菜单AntdMenu与标签页AntdTabs的回调函数问题【Python+Dash+fac组件库】

需实现功能:通过点击导航菜单,新建标签页,并打开相应页面。
问题描述:新建标签页后,无法打开页面(如图)
望各位大家指点一二,帮忙修改代码,万分感谢!

img

代码如下:

import dash
from dash import dcc, html
import feffery_antd_components as fac
import feffery_utils_components as fuc
from dash.dependencies import Input, Output, State
import views
from server import app, server


app = dash.Dash(__name__)


menuItems = [
    {
        'component': '主页',
        'props': {
                'key': 'what-is-fac',
                'name': 'what-is-fac',
                'title': '主页',
                'href': '/what-is-fac'
            }
    },
    {
        'component': 'SubMenu',
        'props': {
            'key': '通用',
            'title': '通用'
        },
        'children': [
            {
                'component': 'Item',
                'props': {
                    'key': 'AntdIcon',
                    'name': 'AntdIcon',
                    'title': 'AntdIcon 图标',
                    'href': '/AntdIcon'
                }
            },
            {
                'component': 'Item',
                'props': {
                    'key': 'AntdButton',
                    'name': 'AntdButton',
                    'title': 'AntdButton 按钮',
                    'href': '/AntdButton'
                }
            },
            {
                'component': 'Item',
                'props': {
                    'key': 'baidu',
                    'name': 'baidu',
                    'title': '百度',
                    'href': 'https://www.baidu.com/'
                }
            }
        ]
    }
]

include_props = [
    'tabs_main.children'
]

key2open_keys = {
        '/what-is-fac': ['主页'],
        '/AntdIcon': ['图标'],
        '/AntdButton': ['按钮'],
        'https://www.baidu.com/': ['百度'],
}


app.layout = fuc.FefferyTopProgress(
    html.Div(
        [
            # 获取和设置url参数
            dcc.Location(id='url'),
            # 主界面
            fac.AntdRow(
                [
                    # 导航菜单
                    fac.AntdCol(
                        [
                            fac.AntdCol(
                                fac.AntdMenu(
                                    id='router-menu',
                                    mode='inline',
                                    menuItems=menuItems,
                                    style={
                                        'marginTop': '0px',
                                        'overflow': 'hidden'
                                    }
                                )
                            )
                        ],
                        flex='none',
                        span=24,
                        style={
                            'height': 50,
                            'lineHeight': 50,
                            'paddingLeft': 20,
                            'paddingRight': 20
                        }
                    ),
                    # 标签页
                    fac.AntdCol(
                        [
                            fac.AntdTabs(
                                id='tabs_main',
                                type='editable-card',
                                defaultActiveKey='/what-is-fac',
                                items=[
                                    {
                                        'label': '首页',
                                        'key': '/what-is-fac',
                                        'closable': False,
                                        'children': fuc.FefferyScrollbars(
                                            #views.what_is_fac.docs_content   #这里可能缺少主页
                                            id='/what-is-fac',
                                            style={
                                                'height': 'calc(100vh - 100px)'
                                            }
                                        )
                                    }
                                ]
                            )
                        ],
                        flex='auto'
                    )
                ],
                wrap=False
            )
        ]
    ),
    style={
        'height': '100vh',
        'minheight': '100vh',
        'maxheight': '100vh'
    },
    listenPropsMode='include',
    includeProps=include_props,
    minimum=0.33,
    speed=800,
    debug=True
)


@app.callback(
    [Output('tabs_main', 'children'),
     Output('tabs_main', 'items'),
     Output('tabs_main', 'activeKey')],
    [Input('url', 'pathname'),
     Input('tabs_main', 'latestDeletePane')],
    [State('tabs_main', 'items'),
     State('tabs_main', 'activeKey')]
)
def render_docs_content(pathname, latestDeletePane, origin_items, activeKey):
    # 获取触发回调的组件id
    triggered_id = dash.callback_context.triggered_id
    
    # 第1个标签页,打开首页what-is-fac
    if pathname in ['/what-is-fac', '/', '']:
        return [views.what_is_fac.docs_content, dash.no_update, '/what-is-fac']
    
    # 新增标签页,并加载页面
    elif pathname in key2open_keys.keys() and triggered_id == 'url':
        origin_keys = [item['key'] for item in origin_items]
        label = key2open_keys[pathname][0]
        children = getattr(views, pathname[1:]).docs_content   #这里有问题
        
        # 如果当前激活的标签页已经是要打开的页面,则不更新items和activeKey输出
        if pathname == activeKey:
            return [dash.no_update, dash.no_update, dash.no_update]
        
        # 如果要打开的页面已经存在于标签页中,则只更新activeKey输出
        elif pathname in origin_keys:
            return [dash.no_update, dash.no_update, pathname]
        
        # 否则,在标签页中添加新的页面,并更新activeKey输出
        else:
            panes = [
                *origin_items,
                {
                    'label': label,
                    'key': pathname,
                    'children': fuc.FefferyScrollbars(
                        #**children,   #这里不知怎么写,问题出在这里
                        id = pathname,
                        style={
                            'height': 'calc(100vh - 100px)'
                        }
                    )
                }
            ]
            
            return [dash.no_update, panes, pathname]
    
    # 关闭标签页
    elif triggered_id == 'tabs_main':
        return [
            dash.no_update,
            [
                item
                for item in origin_items
                if item['key'] != latestDeletePane
            ],
            '/what-is-fac' if latestDeletePane == activeKey else dash.no_update
        ]
    
    # 无效路径
    else:
        return [
            fac.AntdResult(
                status='404',
                title='您访问的页面不存在!',
                style={
                    'height': 'calc(100vh - 100px)'
                }
            ),
            dash.no_update,
            dash.no_update
        ]

if __name__ == '__main__':
    app.run(debug=True)

该回答引用ChatGPT-3.5,仅供参考,不保证完全正确

根据代码的描述,您希望通过点击导航菜单在标签页中打开相应的页面。在代码中,存在一些问题导致标签页无法正确打开页面。以下是需要修改的地方:

  1. render_docs_content函数中,需要将views.what_is_fac.docs_content更改为views.what_is_fac.docs_content(),以调用docs_content函数并获取其返回的内容。

  2. 在相应的elif语句中,您需要使用getattr(views, pathname[1:]).docs_content()来调用对应页面的docs_content函数并获取内容。

  3. 在新增标签页的逻辑中,您需要将children传递给FefferyScrollbars组件时使用**来展开children字典,即**children

请注意,我假设了您的views模块中包含了各个页面的定义,并且每个页面都有一个名为docs_content的函数来返回相应的内容。


修改后的代码如下所示:

...

@app.callback(
    [Output('tabs_main', 'children'),
     Output('tabs_main', 'items'),
     Output('tabs_main', 'activeKey')],
    [Input('url', 'pathname'),
     Input('tabs_main', 'latestDeletePane')],
    [State('tabs_main', 'items'),
     State('tabs_main', 'activeKey')]
)
def render_docs_content(pathname, latestDeletePane, origin_items, activeKey):
    # 获取触发回调的组件id
    triggered_id = dash.callback_context.triggered_id

    # 第1个标签页,打开首页what-is-fac
    if pathname in ['/what-is-fac', '/', '']:
        return [views.what_is_fac.docs_content(), dash.no_update, '/what-is-fac']

    # 新增标签页,并加载页面
    elif pathname in key2open_keys.keys() and triggered_id == 'url':
        origin_keys = [item['key'] for item in origin_items]
        label = key2open_keys[pathname][0]
        children = getattr(views, pathname[1:]).docs_content()

        # 如果当前激活的标签页已经是要打开的页面,则不更新items和activeKey输出
        if pathname == activeKey:
            return [dash.no_update, dash.no_update, dash.no_update]

        # 如果要打开的页面已经存在于标签页中,则只更新activeKey输出
        elif pathname in origin_keys:
            return [dash.no_update, dash.no_update, pathname]

        # 否则,在标签页中添加新的页面,并更新activeKey输出
        else:
            panes = [
                *origin_items,
                {
                    'label': label,
                    'key': pathname,
                    'children': fuc.FefferyScrollbars(
                        **children,
                        id=pathname,
                        style={
                            'height': 'calc(100vh - 100px)'
                        }
                    )
                }
            ]

            return [dash.no_update, panes, pathname]

    # 关闭标签页
    elif triggered_id == 'tabs_main':
        return [
            dash.no_update,
            [
                item
                for item in origin_items
                if item['key'] != latestDeletePane
            ],
            '/what-is-fac' if latestDeletePane == active

Key else dash.no_update
        ]

    # 无效路径
    else:
        return [
            fac.AntdResult(
                status='404',
                title='您访问的页面不存在!',
                style={
                    'height': 'calc(100vh - 100px)'
                }
            ),
            dash.no_update,
            dash.no_update
        ]

...

请注意,以上代码修改假设了您的views模块中包含了各个页面的定义,并且每个页面都有一个名为docs_content的函数来返回相应的内容。如果您的实际情况与此不符,请相应地进行修改。另外,确保views模块已正确导入并包含了所需的页面定义和函数。

antd Pagination 组件绑定回调函数问题整理
可以参考下


记录使用antd中的menu组件,以及使用中碰到的问题_antd menu_Joey_iSleepy的博客-CSDN博客 记录使用antd中的menu组件,以及使用中碰到的问题。一、功能要求二、实现思路一、功能要求页面左侧是菜单栏,菜单栏中有分类,分类下有子分类,鼠标移入子分类上需要显示三个点,显示下拉操作选项。点击子分类右侧需要展示对应的表单,是用的套用的组件方式。之后因为同事也需要使用左侧菜单,但是右侧展示的内容不一样,所以抽离了一些代码,有些地方可以自行优化。全新的界面设计 ,将会带来全新的写作体验;在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;二、实现思路首_antd menu https://blog.csdn.net/qq_60178319/article/details/124667560

新建标签页后,无法打开页面,可能是AntdMenu和AntdTabs组件之间的回调函数有问题,或者被打开的标签页页面有问题。确保你在AntdMenu组件的回调函数中正确地创建了AntdTabs组件,并为每个AntdTabs组件设置了相应的页面。并且需要使用fac.State()函数来更新AntdTabs组件的状态。