Unplanned
Last Updated: 17 Sep 2024 07:08 by ADMIN
Alexa
Created on: 10 Sep 2024 14:19
Category: Kendo UI for jQuery
Type: Feature Request
1
TileLayout - dynamically add/remove tiles (without using setOptions/destroying the widget)

Hello!

 

I was recommended to submit a feature request for this in this feature request. I also commented on a similar forum question.

Dynamically adding/removing tiles via the setOptions method works, however in my case I'm using the containers/tiles to display other widgets (like charts and data grids) in a dashboard. Re-initializing the TileLayout via setOptions forces me to recreate my data widgets, some of which are loading fairly large datasets.

I've been able to work around this using the internal source code for the kendoUI TileLayout, which I dislike doing and am always just one update away from my solution breaking. So far it works - I can add/remove tiles without destroying and re-initializing. I did run into some trouble with resizing and reordering, but I think I've gotten around that.

 

It seems a common usage for the TileLayout is to display dashboards/remote data. I do think implementing a solution to add/remove tiles without re-initializing would be beneficial for many developers using this widget.

 

Thank you,

 

-Alexa

/**
     * At the time of this writing, the only kosher way to dynamically add/remove tiles to a kendoUI TileLayout is
     * to use the `setOptions` method and pushing/slicing the `containers` array. However, doing this destroys the
     * TileLayout and re-initializes it. We would have to re-initialize all the data widgets and submit requests to
     * the server all over again. So... I lifted this from the KendoUI TileLayout source code and modified it to
     * suit our needs.
     * It seems to work, but it just one update away from breaking. I guess I like living on the edge.
     *
     * @deprecated
     * @param options {Object} the kendo.ui.TileLayout `containers` item configuration
     * @param idx {Number} the index of the tile to add
     * @param kendoTileLayout {kendo.ui.TileLayout} the kendo tile layout instance
     */
    const addContainer = (options, idx, kendoTileLayout) => {
        const body = $(`<div></div>`).addClass('k-tilelayout-item-body k-card-body');
        const headerSettings = options.header;
        const id = kendo.guid();

        const container = $(`<div></div>`)
            .addClass('k-tilelayout-item k-card')
            .attr({
                id: id,
                role: 'listitem',
                'aria-keyshortcuts': 'Enter',
            });

        if (headerSettings && (headerSettings.template || headerSettings.text)) {
            const header = $('<div></div>').addClass('k-tilelayout-item-header k-card-header');
            const headerContent = headerSettings.text ? `<div class="k-card-title">${headerSettings.text}</div>` : null;

            if (kendoTileLayout.options.reorderable) {
                header.addClass('k-cursor-move');
            }

            header.append(headerContent || kendo.template(headerSettings.template)({}));
            header.appendTo(container);
        }

        body.append(kendo.template(options.bodyTemplate)({}));
        body.appendTo(container);
        container.appendTo(kendoTileLayout.element);

        kendoTileLayout._addContainer(container, options, idx, id);
    };


    /**
     * @deprecated
     * This also is using KendoUI internal source code. If/when the folks at Telerik decide to implement a different
     * solution for dynamically adding/removing tiles, that should be used instead and this should be removed.
     *
     * @param widgetId {Number} the id of the widget to remove
     * @param kendoTileLayout {kendo.ui.TileLayout} the kendo tile layout instance
     */
    const removeContainer = (widgetId, kendoTileLayout) => {
        const widgetRegex = new RegExp(`${widgetId}`);
        const matchedContainer = kendoTileLayout.options.containers.find(container => container.bodyTemplate.match(widgetRegex));

        const containerGuid = matchedContainer.id;
        const containerItem = kendoTileLayout.itemsMap[containerGuid];
        const containerItemIdx = kendoTileLayout.items.indexOf(containerItem);

        kendoTileLayout.options.containers.splice(containerItemIdx, 1);
        delete kendoTileLayout.itemsMap[containerGuid];
        kendoTileLayout.items.splice(containerItemIdx, 1);

        $(`#widget-${widgetId}`).closest('.k-tilelayout-item.k-card').remove();
        kendoTileLayout._updateContainers();

        // I've got a bad feeling about this.
        kendoTileLayout.element.off('mousemove'); // after removing a container, the resize handles weren't working.
        kendoTileLayout.resizable.destroy();
        kendoTileLayout.element.find('.k-resize-handle').remove();
        kendoTileLayout.resizeHandle = null;
        kendoTileLayout._resizable();
    };

1 comment
ADMIN
Nikolay
Posted on: 17 Sep 2024 07:08

Hello Alexa,

Thank you for taking the time and submitting this feature request and the workaround you came up with. 

I see the value in it and as soon as it becomes popular and collects votes we will consider including it in the RoadMap.

Regards,
Nikolay
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.