Why does the toolbar not support submenu structuring?

Hello Syncfusion team, 
I have an issue with the Syncfusion Toolbar. I would like to create a toolbar (especially for a grid) that should be able to have submenus. 

After reading the documentation I think that this is not possible, since the Toolbar elements only support ItemModel that does not support items as attribute. I tried to bind a MenuItemModel instead, but it did not create the according submenus.

I thought about using an ejs-menu instead that relies on MenuItemModel, which again is nestable, but then I would lose advantages that are built-in in toolbars e.g. the automatically working operations (Add, Delete, Print, ...) of a grid and especially the column chooser. 

It is also not that easy to adapt the ng-template of the toolbar because it should be created dynamically due to a JSON config. 

So, my question is: Is there really no other way to make a toolbar nestable and if so, why is that the case?

Thanks in regard,
Jonas Czeslik


8 Replies 1 reply marked as answer

SK Satheesh Kumar Balasubramanian Syncfusion Team April 4, 2022 02:53 PM UTC

Hi Jonas,

 

We have prepared sample to integrate menu inside toolbar item based on your requirement.

 

 

app.component.html:   

<div class="control-section">

  <div class="toolbar-menu-control">

    <div id="shoppingMenu">

      <ejs-menu [items]="data"></ejs-menu>

    </div>

    <!-- Render the Toolbar Component -->

    <ejs-toolbar [items]="toolbarItems" #toolbar (created)="onCreated()">

    </ejs-toolbar>

  </div>

</div>

 

app.component.ts:   

public data: MenuItemModel[] = [

    {

      text: 'Appliances',

      items: [

        {

          text: 'Kitchen',

          items: [

            { text: 'Electric Cookers' },

            { text: 'Coffee Makers' },

            { text: 'Blenders' },

          ],

        },

      ],

    },

  ];

 

  public toolbarItems = [

    {

      text: 'Add',

      id: 'Add',

    },

    {

      text: 'Edit',

      id: 'Edit',

    },

    {

      text: 'Delete',

      id: 'Delete',

    },

    {

      text: 'Update',

      id: 'Update',

    },

    {

      template: '#shoppingMenu',

    },

  ];

 

Kindly try the above sample and let us know if this meets your requirement.

 

Regards,

Satheesh Kumar B



JC Jonas Czeslik April 4, 2022 07:59 PM UTC

Hello and thanks for the answer! That indeed sounds like it could be the solution, but how can I make that generic? Depending on a config, I want to dynamically add the toolbar and therefore it could be possible that there are no nested submenu at all or there could be 7 in the same toolbar. 

I thought of something like that:

      "toolbarSettingsAsMenu": [
        {
          "text": "Add"
        },
        {
          "text": "Edit"
        },
        {
          "text": "Delete"
        },
        {
          "text": "Process",
          "isSubMenu": true,
          "items":[
            {
              "text": "Print"
            },
            {
              "text": "CSV Export"
            }
          ]
        }
      ]


And then, in an initializing function, I would iterate through this array and - if !isSubMenu === true, I would push it to the items array for the toolbar and otherwise I would have to use the template property, but I am not sure how to do that generically. 

Creating a big number of possible ejs-menus to bind them too does not seem to be a good solution. I tried to use a template string like 

template: '<ejs-menu [items]="?"></ejs-menu>'


but I dont know how to fill the items input in this case?



SK Satheesh Kumar Balasubramanian Syncfusion Team April 5, 2022 11:24 AM UTC

Hi Jonas,

 

No, it is not possible to render submenu structure on toolbar which is the default behavior of our toolbar control. As mentioned in the previous update you can use template property to render our menu bar control in toolbar item.

 

Please let us know for further assistance.

 

Regards,

Satheesh Kumar B



JC Jonas Czeslik April 5, 2022 11:45 AM UTC

"As mentioned in the previous update you can use template property to render our menu bar control in toolbar item."

That is what I am trying, but like I said, I dont know how to do that, when I have multiple possible submenus.

The template property can take an HTML ID or an HTML template string.

If I chose to bind the menu to an HTML element and its ID (like you did in your example), I would have to create an amount of ejs-menus according to the amount of submenus I want to support in the toolbar. That is a good solution for a static toolbar, but like I said, I want to create the toolbar generically in each of my components and sometimes it gets no submenu at all, other times it can get a few at the same time.

The other way would be to define an HTML template string, which would look like that:
template: '<ejs-menu [items]="?"></ejs-menu>'
But here I would have to fill in the items input property with the according items I want to render in the ejs-menu and I still dont know how to do that in such an HTML string.



JC Jonas Czeslik April 5, 2022 12:04 PM UTC

To make the issue a bit clearer, I adapted the Stackblitz example and added some explanations:

https://stackblitz.com/edit/angular-menu-integration-toolbar-using-items-xakx1e?file=app.component.ts



SK Satheesh Kumar Balasubramanian Syncfusion Team April 7, 2022 02:38 PM UTC

Hi Jonas,

We have modified the sample to achieve your requirement using toolbar template property.


app.componnent.html:

<div class="control-section">
  <div class="toolbar-menu-control">
    <ng-container *ngFor="let backendItem of toolbarItems">
      <div *ngIf="backendItem.isSubMenu" id="{{ backendItem.id }}">
        <ejs-menu [items]="backendItem.items"></ejs-menu>
      </div>
    </ng-container>
    <!-- Render the Toolbar Component -->
    <ejs-toolbar [items]="toolbarItems" #toolbar (created)="onCreated()">
    </ejs-toolbar>
  </div>
</div>

app.componnent.ts:

ngOnInit() {
    this.toolbarDataFromBackend = [
      {
        text: 'Add',
        isSubMenu: false,
      },
      {
        text: 'Edit',
        isSubMenu: false,
      },
      {
        text: 'Delete',
        isSubMenu: false,
      },
      {
        text: 'Process',
        isSubMenu: true,
        id: 'shoppingMenu',
        items: [
          {
            text: 'Appliances',
            items: [
              {
                text: 'Kitchen',
                items: [
                  { text: 'Electric Cookers' },
                  { text: 'Coffee Makers' },
                  { text: 'Blenders' },
                ],
              },
            ],
          },
          {
            text: 'CSV Export',
          },
        ],
      },
    ];
    // Here the toolbar items should be inserted accordingly
    for (let backendItem of this.toolbarDataFromBackend) {
      if (backendItem.isSubMenu !== true) {
        // Just push the normal items into the toolbar
        this.toolbarItems.push(backendItem);
      } else {
        this.data = backendItem.items;
        let toolbarSubMenuItem = {
          items: backendItem.items,
          text: backendItem.text,
          id: backendItem.id,
          isSubMenu: backendItem.isSubMenu,
          template: '#' + backendItem.id, // TODO: That is the tricky part! Here I want to create an
          // ejs-menu based on backendItem and containing backendItem.items
        };
        this.toolbarItems.push(toolbarSubMenuItem);
      }
    }
  }

Kindly try the above sample and let us know if this meets your requirement.

Regards,
Satheesh Kumar B

Marked as answer

JC Jonas Czeslik replied to Satheesh Kumar Balasubramanian April 10, 2022 11:53 AM UTC

That indeed meets the requirements. 


As always: Thank you very much for the support!





VM Vengatesh Maniraj Syncfusion Team April 11, 2022 03:24 AM UTC

You are most welcome!!!


Loader.
Up arrow icon