Custom Dash component: Dual-listbox

Hello everyone<

I have published a new Dash Component that renders dual-listbox. Please check it out at GitHub - vivekvs1/dash-dual-listbox: Dual listbox for Dash. Original component: https://rawgit.com/jyotirmaybanerjee/react-duallist/master/example/examples.html#
listbox

5 Likes

Wow, very nice. Thanks for sharing!

1 Like

Thanks for sharing, it looks good. Here’s a quick review:

You are not actually using the state, you should remove the state and only use the props.

Uncomment the setProps so you can get the selected callback on the backend.

You can remove the outer div and change the DualList props to:

<DualList {...this.props} onMove={this.onMove} />

It will apply every props from the backend to the wrapped react Duallist and register the onMove handler without all the keys setting.

Hope this help you in your creation of components.

1 Like

Thank you very much @Philippe. I learned a lot from your comments above.

I have one question for you:

If the original component had a prop that was ‘unexposed’, would it be able to pass a reference to that prop in react? This would be useful incase I would like to extend the component myself by binding it to a custom function for a button or so.

Another question would be:

Would it be possible to write callbacks in Dash for function triggers? Like OnClick etc? If yes, how should I define the proptype such that Dash would understand it?

Hi @Philippe:
I tried implementing your comments. If I don’t set the state the code isn’t working. As in everything is rendering fine when I directly use the props, but clicking any ‘move’ buttons isn’t triggering the onMove callback. I will PR the updated code soon.

Shouldn’t the ‘selected’ have set state?

I am trying to use the dash_dual_listbox component to create a list box style similar to what is seen in
the react component example seen in the example here however I cannot get it even close to look like this:

https://rawgit.com/jyotirmaybanerjee/react-duallist/master/example/examples.html

I am more of a python programmer than a web designer. Is there some example python code to generate a dash
page that looks like this? I am finding that there is not a lot of example code usage on the dash_dual_listbox on
the web.

Hi jmtkelly, you can get the css from that link https://rawgit.com/jyotirmaybanerjee/react-duallist/master/example/examples.html

Here is the code:

.react-listbox-dual-list {
display: flex;
align-items: center;
box-sizing: border-box;
}
.react-listbox-dual-list * {
box-sizing: border-box;
}
.react-listbox-dual-list input:disabled, .react-listbox-dual-list select:disabled {
background: #eee;
cursor: not-allowed;
}
.react-listbox-dual-list button, .react-listbox-dual-list select {
line-height: 1.42857;
font-family: inherit;
}
.react-listbox-dual-list .react-listbox-list-box {
display: flex;
flex: 1 1 0;
flex-direction: column;
align-self: stretch;
}
.react-listbox-dual-list .react-listbox-list-box .search-bar {
margin-bottom: 5px;
}
.react-listbox-dual-list .react-listbox-list-box select {
min-height: 150px;
}
.react-listbox-dual-list .react-listbox-list-box .list-filter, .react-listbox-dual-list .react-listbox-list-box .list-control {
display: block;
border: 1px solid #ccc;
border-radius: 2px;
padding: 8px 12px;
width: 100%;
color: #333;
font-size: 14px;
}
.react-listbox-dual-list .react-listbox-list-box .list-filter {
margin-bottom: 10px;
}
.react-listbox-dual-list .react-listbox-center-toolbar {
display: flex;
flex: 0 0 auto;
flex-direction: column;
margin: 55px 10px 0 10px;
}
.react-listbox-dual-list .react-listbox-center-toolbar .move-left, .react-listbox-dual-list .react-listbox-center-toolbar .move-right {
display: flex;
flex-direction: column;
}
.react-listbox-dual-list .react-listbox-center-toolbar .move-right {
margin-bottom: 10px;
}
.react-listbox-dual-list .react-listbox-right-toolbar {
display: flex;
flex: 0 0 auto;
flex-direction: column;
margin: 55px 10px 0 10px;
}
.react-listbox-dual-list .react-listbox-right-toolbar .move-top, .react-listbox-dual-list .react-listbox-right-toolbar .move-bottom {
display: flex;
flex-direction: column;
}
.react-listbox-dual-list .react-listbox-right-toolbar .move-top {
margin-bottom: 10px;
}
.react-listbox-dual-list .btn-move {
margin-bottom: 5px;
border: 1px solid #ccc;
border-radius: 2px;
background: #fff;
cursor: pointer;
padding: 5px 10px;
color: #333;
font-size: 12px;
}
.react-listbox-dual-list .btn-move:active:not(:disabled), .react-listbox-dual-list .btn-move:focus:not(:disabled) {
border-color: #8c8c8c;
background: #e6e6e6;
}
.react-listbox-dual-list .btn-move:focus:not(:disabled) {
outline: thin dotted;
outline-offset: -2px;
}
.react-listbox-dual-list .btn-move:hover:not(:disabled) {
border-color: #adadad;
background: #e6e6e6;
}
.react-listbox-dual-list .btn-move:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.react-listbox-dual-list .btn-move:last-child {
margin-bottom: 0;
}
.react-listbox-dual-list .btn-move i {
margin: 0 -1px;
}
.react-listbox-dual-list .list-container {
display: flex;
flex: 1 0 auto;
}
.react-listbox-dual-list .list-label {
position: absolute;
clip: rect(0 0 0 0);
}
.react-listbox-dual-list .list-control {
flex: 1 0 auto;
}
.react-listbox-dual-list .list-control optgroup {
font: inherit;
font-weight: 700;
}

Hi Vivek. Were you able to get the Selected part working?

hey :slight_smile: great component, it’s really useful for my project so thank you first of all!

wanted to ask if you know whether it’s possible to remove the right toolbar somehow since I don’t need it for my application.
hope you will read this since its been over 3 year but anyways thanks for the component xD

is this still being monitored? I cannot for the life of me get a callback to work. i dynamically add the duallist like:

   component_list = []
   selected_dict = [{'label': 'a', 'value': '123'} ... {'label': 'z', 'value': '2343'}]
   default_selected = ['a', 'b', 'z'] 
   component_list.append(html.Div([
            DualList(id={'type': 'duallist', 'index': 'ret_dl'}, 
                     available=selected_dict, 
                     selected=default_selected,
                     leftLabel='Available',
                     rightLabel='Selected',
                     sortable=False,
                     searchable=False),
             html.Br()],
            id='my_div'))

I have one callback:

    @dashapp.callback(
        Output({'type': 'duallist', 'index': MATCH}, 'selected'),
        [Input({'type': 'duallist', 'index': MATCH}, 'id'),
         Input({'type': 'duallist', 'index': MATCH}, 'selected')]
    )
    def duallist_change(dropdown_id, selected_items_id):
        dashapp.logger.info(f'{dropdown_id} was clicked: {selected_items_id}')
        return selected_items_id

which gets called only once when the page first loads, but i would like it to be called whenever any of the 4 buttons moving left to right or whatever are pressed (ie, whenever the right selected list changes) but I cannot for the life of me figure out how to do this, any help would be amazing. thanks -

I love this component, but I can’t figure out how to use the Selected values in a callback. It keeps getting returned as an empty list. Has anyone else figured out a solution for this?

You can use AntdTransfer in my dash components library fac ( GitHub - CNFeffery/feffery-antd-components: Dash + Antd = 😍 ), install it via pip install feffery-antd-components, import it via import feffery_antd_components as fac, here is a simple demo:



html.Div(
    fac.AntdTransfer(
        id='transfer-demo',
        locale='en-us',
        dataSource=[
            {
                'key': str(i),
                'title': f'item {i}'
            }
            for i in range(20)
        ]
    )
),

html.Br(),
html.Em(id='transfer-demo-output')
...
@app.callback(
    Output('transfer-demo-output', 'children'),
    [Input('transfer-demo', 'targetKeys'),
     Input('transfer-demo', 'moveDirection'),
     Input('transfer-demo', 'moveKeys')],
    prevent_initial_call=True
)
def transfer_callback_demo(targetKeys, moveDirection, moveKeys):

    return [
        f'targetKeys: {targetKeys}',
        html.Br(),
        f'moveDirection: {moveDirection}',
        html.Br(),
        f'moveKeys: {moveKeys}'
    ]

1 Like

It would be nice if you could highlight multiple values at a time or shift+click, but I think this will do the job for now. Thanks!

1 Like