Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Dropdown Button Component #7291

Open
mrjohn0011 opened this issue Mar 14, 2019 · 6 comments

Comments

Projects
None yet
5 participants
@mrjohn0011
Copy link
Contributor

commented Mar 14, 2019

The Problem

Create a button that allows a user to change an action to be executed.

The Proposed Solution

We plan to add a new DropDownButton component. This component will allow a user to select an action to be executed from the drop-down list and re-execute this action on a button click.

The DropDownButton consists of three elements: the drop-down list; the toggle button that opens and closes the drop-down list; the action button that executes an action.

dropdownbutton

This component will have the following API:

let dropDownButtonOptions = {
    itemTemplate: template, // The template for action items in the drop-down list.
    keyExpr: string, // The data field which provides key values.
    displayExpr: string, // The data field that provides values to be displayed.
    selectedItem: object, // The initially or currently selected item. This object can contain the key field only.
    useSelectMode: boolean, // Specifies whether to change the action button's text according to the selected item.
    splitButton: boolean, // Specifies whether to show the toggle button.
    dropDownOptions: object, // Customizes the drop-down list. Accepts the same fields as the Popup configuration.
    onActionButtonClick: function, // A function that is executed when a user clicks the action button.
    onSelectionChanged: function, // A function that is executed when a user selects an item from the drop-down list.
    onItemClick: function, // A function that is executed when a user clicks an item from the drop-down list.
    items: Array, // An array of items to be displayed in the drop-down list. 
    dataSource: Array, DataSourceConfig // A DataSource or store that contains items to be displayed in the drop-down list. 
};

Use with DevExtreme data layer components

The DropDownBox works with all DevExtreme data layer components.

let dropDownButtonOptions = {
    dataSource: new DevExpress.data.DataSource({
        store: new DevExpress.data.ArrayStore({
            data: [
                {id: 1, name: "Left", icon: "alignleft"},
                {id: 4, name: "Right", icon: "alignright"},
                {id: 2, name: "Center", icon: "aligncenter"},
                {id: 3, name: "Justify", icon: "alignjustify"}
            ]
        })
    }),
    displayExpr: "name",
    keyExpr: "id"
};

Use select mode

When a user selects an action from the drop-down list, the action button's text changes accordingly. Set the useSelectMode option to true to enable this behavior:

let dropDownButtonOptions = {
    useSelectMode: true
};

Use custom content in the drop-down list

dropDownOptions customize the drop-down list and its content. In the following example, the drop-down list allows a user to select icons. Note that in the case of custom content, you should change the selectedItem option.

dropdownbutton

let dropDownButton = $("#dropDownButtonContainer").dxDropDownButton({
    items: [
        { icon: "email" },
        { icon: "airplane" },
        { icon: "user" },
        { icon: "money" }
    ],
    keyExpr: "icon",
    displayExpr: "",
    selectedItem: { icon: "airplane" },
    dropDownOptions: {
        width: 230,
        contentTemplate: ($container) => {
            $("<h3>").text("Select an icon").appendTo($container);
            dropDownButton.option("items").forEach((itemData) => {
                $("<div>").appendTo($container).dxButton({
                    onClick: () => {
                        dropDownButton.option("selectedItem", itemData);
                    },
                    icon: itemData.icon
                }).css({
                    margin: "5px"
                });
            });
        }
    }
}).dxDropDownButton("instance");

We Need Your Feedback

Take a Quick Poll

Do you find the DropDownBox useful?

Get Notified of Updates

Subscribe to this thread or to our Facebook and Twitter accounts for updates on this topic.

@hakimio

This comment has been minimized.

Copy link

commented Mar 14, 2019

Will it be possible to hide the arrow from the button? Would be nice if it could show up as just an icon.

@mrjohn0011

This comment has been minimized.

Copy link
Contributor Author

commented Mar 14, 2019

Yes, it will be possible to hide the toggle button. In this case, a click on the action button will open and close the widget and a click on the list item will execute an action.

@dxbykov dxbykov changed the title dxDropDownButton - A new component New Dropdown Button Component Mar 15, 2019

@cfsean

This comment has been minimized.

Copy link

commented Apr 1, 2019

If I'm honest. I think you've missed the point of a drop down button a little bit.

I really can't think of many scenarios where I would want to populate the items in the button from the data source and then have the text on the button change. I think the concept of a currently selected item doesn't make a lot of sense for this component and to me, it seems a lot like your select-box component with some different styling.

In my experience a drop-down button is more useful for executing once-off actions and knowing the currently selected item doesn't have a lot of relevance. Buttons in most cases, are stateless clickable elements.

It seems you may have taken inspiration from the Kendo equivalent which again, I think this is a poor implementation.

Better examples include the bootstrap demos found here https://getbootstrap.com/docs/4.1/components/dropdowns/#single-button and the material design menu which can function in a similar way to the bootstrap example, demo here https://yjpabykempbo.angular.stackblitz.io

Furthermore, you implementation of items as a data source has the same frustrating problem that I find with your context menu component in that you cannot easily define the click events for the items. In order to define a click event you need to handle the onItemClick event and inspect the index or some other arbitrary string which is prone to errors when changing of refactoring the items. It makes the entire experience needlessly complicated. As I mentioned before, I think your select-box component would be better suited to the scenarios where items are being populated from a data source.

Since I mostly use the components in Angular, it would be very handy to be able to define the menu in a similar fashion to the below

<dx-button-group text="Actions" icon="fa fa-cog" [showArrow]="true">
  <dx-button-group-item text="Edit" icon="fa fa-pencil" routerLink="edit"></dx-button-group-item>
  <dx-button-group-item text="Delete" icon="fa fa-trash" (click)="delete()"></dx-button-group-item>
</dx-button-group>

This is much simpler than your currently proposed implementation.

The last piece of feedback I have would be that it should at least be optional that clicking anywhere on the button, not just on the arrow should show the drop-down.

@dxbykov

This comment has been minimized.

Copy link
Contributor

commented Apr 3, 2019

Hi @cfsean,
 
Thank you for your valuable feedback. I'd like to address some of the points you've mentioned.

I really can't think of many scenarios where I would want to populate the items in the button from the data source and then have the text on the button change. I think the concept of a currently selected item doesn't make a lot of sense for this component and to me, it seems a lot like your select-box component with some different styling.

I've made examples of simpler use cases we will support to better demonstrate the functionality of our dropdown button. Take a look at the Angular examples below. Note that we reconsidered some initial option names.

Furthermore, you implementation of items as a data source has the same frustrating problem that I find with your context menu component in that you cannot easily define the click events for the items.

You can use static items instead. Each item can have its own click handler as shown in the examples below.

The last piece of feedback I have would be that it should at least be optional that clicking anywhere on the button, not just on the arrow should show the drop-down.

This behavior is supported in the dropdown button stateless mode.

These four primary modes are supported:

1. Stateless one-section dropdown button:

<dx-dropdown-button text="Actions" icon="my-icon">
  <dxi-item text="Action 1" icon="icon1" (onClick)="myHandler1()"></dxi-item>
  <dxi-item text="Action 2" icon="icon2" (onClick)="myHandler2()"></dxi-item>
</dx-dropdown-button>

2. Stateless two-section dropdown button:

<dx-dropdown-button text="Primary Action" icon="my-icon" [splitButton]="true" (onActionButtonClick)="myHandler($event)">
  <dxi-item text="Secondary Action 1" icon="icon1" (onClick)="myHandler1()"></dxi-item>
  <dxi-item text="Secondary Action 2" icon="icon2" (onClick)="myHandler2()"></dxi-item>
</dx-dropdown-button>

3. One-section dropdown button with selection enabled:

<dx-dropdown-button [useSelectMode]="true" (onSelectedItemChanged)="myHandler($event)" keyExpr="id" selectedItemKey="item1">
  <dxi-item id="item1" text="Item 1" icon="icon1"></dxi-item>
  <dxi-item id="item2" text="Item 2" icon="icon2"></dxi-item>
</dx-dropdown-button>

4. Two-section dropdown button with selection enabled:

<dx-dropdown-button [useSelectMode]="true" [splitButton]="true" (onActionButtonClick)="myHandler($event)" keyExpr="id" selectedItemKey="item1">
  <dxi-item id="item1" text="Item 1" icon="icon1"></dxi-item>
  <dxi-item id="item2" text="Item 2" icon="icon2"></dxi-item>
</dx-dropdown-button>

If you have any other suggestions or/and questions, I'd be happy to hear them.

@cfsean

This comment has been minimized.

Copy link

commented Apr 3, 2019

Thank you for the clarification @dxbykov. From what you've described this should work great.

It seems like the splitButton option does not exist and the ability to correctly define the dx-items inside a dropdown button is not currently working properly in devextreme-angular 19.1.1-alpha-19085-0305

I assume this is still a work in progress? Is there somewhere I can look to check for when these features have been implemented so I can test?

@hakimio

This comment has been minimized.

Copy link

commented Apr 4, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.