How fix updating

Hi, everybody.

I have encountered one problem in my work. I have a Dropdown Menu in which I have implemented several elements. Such as search-input and checklist. My main problem is that when using search-input, the page is constantly updated. Tell me how I can avoid this. Thank you very much in advance
anim1

my code :

import dash_bootstrap_components as dbc
from dash import Dash, html, dcc, Input, Output, State, callback_context, no_update, callback, exceptions
from sql_execute import get_lpu, create_counter


app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])

lpu_list = [{'label': f'lpu{lpu}', 'value': f'lpu{lpu}'} for lpu in range(10)]

app.layout = html.Div([
    html.Div(
        html.Div(
            [
                html.Div(
                    id='view',
                    style={
                        'display': 'flex',
                        'height': '38px',
                        'width': '29vw',
                        'border': '1px solid',
                        'padding-right': '5px',
                        'textAlign': 'center',
                        'overflow': 'hidden',
                        'font-size': '20px'
                    },
                ),
                dbc.DropdownMenu(
                    id="dropdown-menu",
                    align_end=True,
                    children=[
                        html.Div(
                            id='select_all', className='noselect', children=html.Div(
                            children=[html.Img(src="/assets/bx-list-check.svg"),
                             html.Span("Выбрать все"),
                                ]
                            ),
                        ),
                        html.Div(
                            [
                                dcc.Input(
                                    id="search-input",
                                    type="text",
                                    placeholder="Type to filter",
                                    autoComplete="off",
                                    style={'margin-left': '.5rem'}
                                ),
                            ],
                            id="input-container",
                        ),
                        dbc.DropdownMenuItem(divider=True),
                        dbc.Checklist(
                            id = 'checklist',
                            options=lpu_list,
                            persistence_type='session',
                            persistence='unique_id_for_checklist'
                        ),
                    ]
                ),
                html.Div(id='output_div')
            ],
            className='selector_containerFinal',
            style={
                'justify-content': 'center'
            },
        ),
    ),
])


@callback(
    Output('checklist', 'value'),
    Input('select_all', 'n_clicks'),
    State('checklist', 'options'),
    State('checklist', 'value'))
def handle_select_all(n_clicks, options, curr_value):
    if not n_clicks:
        return no_update
    triggered_element = callback_context.triggered[0]["prop_id"].split(".")[0]
    if triggered_element == "select_all":
        if curr_value is None:
            curr_value = []
        if len(curr_value) == len(options):
            return []
        return [option['value'] for option in options]

@callback(
    Output("checklist", "options"),
    Input("search-input", "value"),
)
def update_checklist_options(search_value):
    if not search_value:
        return lpu_list
    filtered_options = [option for option in lpu_list if search_value.lower() in option["label"].lower()]

    return filtered_options

(mb i can use Background Callback Caching | Dash for Python Documentation | Plotly, But I do not know how to do it)

How i can fix multiple updating

Hello @zaphire121,

You are looking for the debounce property, this will keep it from trying to update before you are ready for it.

Hi @jinnyzor ,
this solution doesn’t help me
anim2

I need the search to work fast

Like this. the page is not updated at the same time
anim3

hmm…

Instead of this, have you looked into using the Grid along with a quick filter?

Just have the grid allow for multiple selections.

To disable the “Updating…” you can pass this to the app init.

update_title=None,

app = dash.Dash(__name__, update_title=None)

If it doesn’t bother you, can you give an example of an implementation?

Sure, here is a basic example:

import dash_bootstrap_components as dbc
from dash import Dash, html, dcc, Input, Output, State, callback_context, no_update, callback, exceptions
import dash_ag_grid as dag


app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], update_title=None)

lpu_list = [{'option': f'lpu{lpu}'} for lpu in range(10)]

app.layout = html.Div([
    html.Div(
        html.Div(
            [
                html.Div(
                    id='view',
                    style={
                        'display': 'flex',
                        'height': '38px',
                        'width': '29vw',
                        'border': '1px solid',
                        'padding-right': '5px',
                        'textAlign': 'center',
                        'overflow': 'hidden',
                        'font-size': '20px'
                    },
                ),
                dbc.DropdownMenu(
                    id="dropdown-menu",
                    align_end=True,
                    children=[
                        html.Div(
                            id='select_all', className='noselect', children=html.Div(
                            children=[html.Img(src="/assets/bx-list-check.svg"),
                             html.Span("Выбрать все"),
                                ]
                            ),
                        ),
                        html.Div(
                            [
                                dcc.Input(
                                    id="search-input",
                                    type="text",
                                    placeholder="Type to filter",
                                    autoComplete="off",
                                    style={'margin-left': '.5rem'},
                                    debounce=False
                                ),
                            ],
                            id="input-container",
                        ),
                        dbc.DropdownMenuItem(divider=True),
                        dag.AgGrid(
                            id='checklist',
                            columnDefs=[{'field': 'option', 'checkboxSelection': True,
                                         'headerCheckboxSelection': True, 'headerName': ''}],
                            rowData=lpu_list,
                            persistence_type='session',
                            persistence=True,
                            dashGridOptions={'rowSelection': 'multiple',
                                             'rowMultiSelectWithClick': True,
                                             "headerCheckboxSelectionFilteredOnly": True,
                                             # 'headerHeight': 0
                                             }
                        ),
                    ]
                ),
                html.Div(id='output_div')
            ],
            className='selector_containerFinal',
            style={
                'justify-content': 'center'
            },
        ),
    ),
])


@callback(
    Output('checklist', 'selectAll'),
    Input('select_all', 'n_clicks'),
    prevent_initial_call=True
)
def handle_select_all(n_clicks):
    return True

@callback(
    Output("checklist", "quickFilterText"),
    Input("search-input", "value"),
    prevent_initial_call=True
)
def update_checklist_options(search_value):
    return search_value

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

You can even allow the selectAll from the header row be something that selects all the filtered rows instead of everything. Just uncomment the headerHeight from the dashGridOptions. :slight_smile:

@jinnyzor you solution like good, but search-input does many post Requests (I don’t know for sure if it will be bad)
anim3
idk how fix many posts

Here you go:

import dash_bootstrap_components as dbc
from dash import Dash, html, dcc, Input, Output, State, callback_context, no_update, callback, exceptions
import dash_ag_grid as dag


app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], update_title=None)

lpu_list = [{'option': f'lpu{lpu}'} for lpu in range(10)]

app.layout = html.Div([
    html.Div(
        html.Div(
            [
                html.Div(
                    id='view',
                    style={
                        'display': 'flex',
                        'height': '38px',
                        'width': '29vw',
                        'border': '1px solid',
                        'padding-right': '5px',
                        'textAlign': 'center',
                        'overflow': 'hidden',
                        'font-size': '20px'
                    },
                ),
                dbc.DropdownMenu(
                    id="dropdown-menu",
                    align_end=True,
                    children=[
                        html.Div(
                            id='select_all', className='noselect', children=html.Div(
                            children=[html.Img(src="/assets/bx-list-check.svg"),
                             html.Span("Выбрать все"),
                                ]
                            ),
                        ),
                        html.Div(
                            [
                                dcc.Input(
                                    id="search-input",
                                    type="text",
                                    placeholder="Type to filter",
                                    autoComplete="off",
                                    style={'margin-left': '.5rem'},
                                    debounce=False
                                ),
                            ],
                            id="input-container",
                        ),
                        dbc.DropdownMenuItem(divider=True),
                        dag.AgGrid(
                            id='checklist',
                            columnDefs=[{'field': 'option', 'checkboxSelection': True,
                                         'headerCheckboxSelection': True, 'headerName': ''}],
                            rowData=lpu_list,
                            persistence_type='session',
                            persistence=True,
                            dashGridOptions={'rowSelection': 'multiple',
                                             'rowMultiSelectWithClick': True,
                                             "headerCheckboxSelectionFilteredOnly": True,
                                             # 'headerHeight': 0
                                             }
                        ),
                    ]
                ),
                html.Div(id='output_div')
            ],
            className='selector_containerFinal',
            style={
                'justify-content': 'center'
            },
        ),
    ),
])


app.clientside_callback(
    """function () {return true}""",
    Output('checklist', 'selectAll'),
    Input('select_all', 'n_clicks'),
    prevent_initial_call=True
)

app.clientside_callback(
    """function (v) { return v}""",
    Output("checklist", "quickFilterText"),
    Input("search-input", "value"),
    prevent_initial_call=True
)

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

How about no post requests? :stuck_out_tongue:

3 Likes

I don’t try use app.clientside_callback

Thx

but in this case i need use dbc.Checklist. I should do app.clientside_callback for ‘search-input’ on JS ?

i learn python ))

Thx for your help

You will have a bunch of POST requests if you use regular callbacks, using AG Grid is just passing the value and a True, very simple JS / Python if you wanted to use regular callbacks with the POST requests.

AG Grid itself isnt the reason for the POST requests, but the Dash app and callbacks. :wink:

I can’t figure out if I can make such a callback without using AG Grid ?

You can, it becomes more tricky because of the functions that you had to feed back the selected options to the checklist.

But, it will be more JS function work and not Python.

And other callback options won 't work ?

What other callback options? There are only two… regular (Python - backend server POST requests) or clientside (JS - browser JS no requests)

Thx you @jinnyzor
:slightly_smiling_face:

1 Like