arya-blue
luna-amber
luna-blue
luna-green
luna-pink
nova-dark
nova-light
saga-blue
vela-blue
Kanban

The Kanban widget exposes a client-side API for programmatic control via PF('widgetVar').methodName(). The following methods are available:

  • addElement(boardId, itemConfig, position) — adds an item to a board
  • findElement(itemId) — finds a DOM element by item ID
  • findBoard(boardId) — finds a DOM element by board ID
  • getParentBoardID(itemId) — returns the parent board ID for an item
  • getBoardElements(boardId) — returns all item elements in a board
  • replaceElement(itemId, itemConfig) — replaces an item's content
  • removeBoard(boardId) — removes an entire board
Board
Item
Selected: click a task
Source

<h:outputScript>
        var KanbanDemo = KanbanDemo || {};

        KanbanDemo.widget = function() {
            return PF('kanbanWidget');
        };

        KanbanDemo.boardId = function() {
            return $('#boardSelect_input').val();
        };

        KanbanDemo.itemId = function() {
            return $('#itemIdInput').val();
        };

        KanbanDemo.notify = function(summary, detail, severity) {
            severity = severity || 'info';
            PF('growl').show([{
                summary: summary,
                detail: detail,
                severity: severity
            }]);
        };

        KanbanDemo.notifyError = function(summary, detail) {
            KanbanDemo.notify(summary, detail, 'error');
        };

        KanbanDemo.notifyWarn = function(summary, detail) {
            KanbanDemo.notify(summary, detail, 'warn');
        };

        KanbanDemo.flashBoard = function(boardEl) {
            boardEl.classList.add('board-highlight');
            setTimeout(function() {
                boardEl.classList.remove('board-highlight');
            }, 2000);
        };

        KanbanDemo.flashItem = function(itemEl) {
            itemEl.classList.add('item-highlight');
            setTimeout(function() {
                itemEl.classList.remove('item-highlight');
            }, 2000);
        };

        KanbanDemo.showPill = function(pillId, text) {
            var $pill = $('#' + pillId);
            $pill.text(text).addClass('visible');
            setTimeout(function() {
                $pill.removeClass('visible');
            }, 3000);
        };

        KanbanDemo.hidePill = function(pillId) {
            $('#' + pillId).removeClass('visible').text('');
        };

        KanbanDemo.assertItemId = function() {
            var id = KanbanDemo.itemId();
            if (!id) {
                KanbanDemo.notifyError('No ID', 'Click a task or type an ID');
                return null;
            }
            return id;
        };

        KanbanDemo.onAddItem = function() {
            var widget = KanbanDemo.widget();
            var board = KanbanDemo.boardId();

            if (!widget.findBoard(board)) {
                KanbanDemo.notifyError('Board not found', 'Board "' + board + '" no longer exists');
                return;
            }

            widget.addElement(board, {
                id: 't-' + Date.now(),
                title: 'New Task',
                description: 'Added via client API'
            });

            KanbanDemo.notify('Item Added', 'New task added to ' + board);
        };

        KanbanDemo.onRemoveBoard = function() {
            var widget = KanbanDemo.widget();
            var board = KanbanDemo.boardId();

            if (!widget.findBoard(board)) {
                KanbanDemo.notifyWarn('Already removed', 'Board "' + board + '" does not exist');
                return;
            }

            widget.removeBoard(board);
            KanbanDemo.notifyWarn('Board Removed', 'Board removed: ' + board);
        };

        KanbanDemo.onCountItems = function() {
            var widget = KanbanDemo.widget();
            var board = KanbanDemo.boardId();
            var boardEl = widget.findBoard(board);
            var pillId = 'countResult';

            KanbanDemo.hidePill(pillId);

            if (!boardEl) {
                KanbanDemo.notifyError('Board not found', 'Board "' + board + '" no longer exists');
                return;
            }

            var count = boardEl.querySelectorAll('.kanban-item').length;
            KanbanDemo.flashBoard(boardEl);
            KanbanDemo.showPill(pillId, count + ' items');
            KanbanDemo.notify(count + ' items', 'Board "' + board + '" has ' + count + ' items');
        };

        KanbanDemo.onFindItem = function() {
            var widget = KanbanDemo.widget();
            var id = KanbanDemo.assertItemId();
            if (!id) return;

            var itemEl = widget.findElement(id);
            if (itemEl) {
                KanbanDemo.flashItem(itemEl);
                KanbanDemo.notify('Found', 'Item "' + id + '" highlighted');
            } else {
                KanbanDemo.notifyError('Not found', 'No item with ID "' + id + '"');
            }
        };

        KanbanDemo.onParentBoard = function() {
            var widget = KanbanDemo.widget();
            var id = KanbanDemo.assertItemId();
            var pillId = 'parentResult';
            KanbanDemo.hidePill(pillId);
            if (!id) return;

            var board = widget.getParentBoardID(id);
            if (board) {
                var boardEl = widget.findBoard(board);
                if (boardEl) {
                    KanbanDemo.flashBoard(boardEl);
                    KanbanDemo.showPill(pillId, 'In: ' + board);
                }
            }

            if (board) {
                KanbanDemo.notify('Parent Board', 'Item "' + id + '" is in board "' + board + '"');
            } else {
                KanbanDemo.notifyError('Not found', 'Item "' + id + '" not found');
            }
        };

        KanbanDemo.onReplaceItem = function() {
            var widget = KanbanDemo.widget();
            var id = KanbanDemo.assertItemId();
            if (!id) return;

            var itemEl = widget.findElement(id);
            if (!itemEl) {
                KanbanDemo.notifyError('Not found', 'No item with ID "' + id + '"');
                return;
            }

            widget.replaceElement(id, {
                title: 'Updated at ' + new Date().toLocaleTimeString()
            });

            KanbanDemo.notify('Replaced', 'Content replaced for "' + id + '"');
        };

        KanbanDemo.onHighlightBoard = function() {
            var widget = KanbanDemo.widget();
            var board = KanbanDemo.boardId();
            var boardEl = widget.findBoard(board);

            if (!boardEl) {
                KanbanDemo.notifyError('Board not found', 'Board "' + board + '" no longer exists');
                return;
            }

            KanbanDemo.flashBoard(boardEl);
            KanbanDemo.notify('Board Found', 'Board "' + board + '" highlighted');
        };

        KanbanDemo.onItemClick = function(args) {
            if (args.itemId) {
                $('#itemIdInput').val(args.itemId);
            }
        };
    </h:outputScript>

    <p:remoteCommand name="rcAddItem"       actionListener="#{kanbanClientApiController.onClientApiCommand}" update="@none" process="@this" oncomplete="KanbanDemo.onAddItem()" />
    <p:remoteCommand name="rcRemoveBoard"   actionListener="#{kanbanClientApiController.onClientApiCommand}" update="@none" process="@this" oncomplete="KanbanDemo.onRemoveBoard()" />
    <p:remoteCommand name="rcCountItems"    actionListener="#{kanbanClientApiController.onClientApiCommand}" update="@none" process="@this" oncomplete="KanbanDemo.onCountItems()" />
    <p:remoteCommand name="rcFindItem"      actionListener="#{kanbanClientApiController.onClientApiCommand}" update="@none" process="@this" oncomplete="KanbanDemo.onFindItem()" />
    <p:remoteCommand name="rcParentBoard"   actionListener="#{kanbanClientApiController.onClientApiCommand}" update="@none" process="@this" oncomplete="KanbanDemo.onParentBoard()" />
    <p:remoteCommand name="rcReplaceItem"   actionListener="#{kanbanClientApiController.onClientApiCommand}" update="@none" process="@this" oncomplete="KanbanDemo.onReplaceItem()" />
    <p:remoteCommand name="rcHighlightBoard" actionListener="#{kanbanClientApiController.onClientApiCommand}" update="@none" process="@this" oncomplete="KanbanDemo.onHighlightBoard()" />

    <div class="api-toolbar">
        <div class="row">
            <span style="font-weight:bold;min-width:50px">Board</span>
            <p:selectOneMenu id="boardSelect" style="width:150px">
                <f:selectItem itemLabel="Backlog" itemValue="backlog" />
                <f:selectItem itemLabel="In Progress" itemValue="inprogress" />
                <f:selectItem itemLabel="Done" itemValue="done" />
            </p:selectOneMenu>
            <p:commandButton value="Add Item" icon="pi pi-plus" type="button"
                             styleClass="ui-button-sm"
                             onclick="rcAddItem()" />
            <p:commandButton value="Count Items" icon="pi pi-list" type="button"
                             styleClass="ui-button-sm"
                             onclick="rcCountItems()" />
            <span class="result-pill" id="countResult"></span>
            <p:commandButton value="Remove Board" icon="pi pi-trash" type="button"
                             styleClass="ui-button-sm ui-button-danger"
                             onclick="rcRemoveBoard()" />
            <p:commandButton value="Highlight Board" icon="pi pi-eye" type="button"
                             styleClass="ui-button-sm"
                             onclick="rcHighlightBoard()" />
        </div>
        <div class="row">
            <span style="font-weight:bold;min-width:50px">Item</span>
            <p:inputText id="itemIdInput" placeholder="e.g. t-1" style="width:130px" />
            <h:panelGroup id="selectedItemBadge" layout="block" style="display:inline">
                <span class="selected-badge">
                    Selected: #{kanbanClientApiController.lastClickedItemId != null ? kanbanClientApiController.lastClickedItemId : 'click a task'}
                </span>
            </h:panelGroup>
            <span class="sep"></span>
            <p:commandButton value="Find" icon="pi pi-search" type="button"
                             styleClass="ui-button-sm"
                             onclick="rcFindItem()" />
            <p:commandButton value="Parent Board" icon="pi pi-arrow-right" type="button"
                             styleClass="ui-button-sm"
                             onclick="rcParentBoard()" />
            <span class="result-pill" id="parentResult"></span>
            <p:commandButton value="Replace Title" icon="pi pi-pencil" type="button"
                             styleClass="ui-button-sm"
                             onclick="rcReplaceItem()" />
        </div>
    </div>

    <pe:kanban id="kanban"
                widgetVar="kanbanWidget"
                value="#{kanbanClientApiController.columns}"
                draggable="true"
                addItemButton="true"
                style="height:400px">
        <p:ajax event="itemClick" listener="#{kanbanClientApiController.onItemClick}" update="growl selectedItemBadge"
                oncomplete="KanbanDemo.onItemClick(args)" />
        <p:ajax event="itemAdd" update="kanban growl" />
    </pe:kanban>
            
Components and more
Documentation pe:kanban
Attributes (move mouse over the names to see data types)
Name Description
addItemButtonEnable add item button on each board.Default is false.
bindContextMenuClient-side id of a PrimeFaces contextMenu component to bind to right-click events.
bindingAn EL expression referring to a server side UIComponent instance in a backing bean.Default is generated.
dragBoardsEnable board (column) dragging and reordering.Default is true.
dragHandleEnable drag handle on items. When enabled, only the handle area is draggable, preventing accidental drags on the card body.Default is false.
draggableEnable drag-and-drop functionality.Default is true.
extenderJavaScript function to extend the widget configuration.
gutterGutter (spacing) between boards in CSS units, e.g. "15px".Default is 15px.
idUnique identifier of the component in a namingContainer.Default is generated.
renderedBoolean value to specify the rendering of the component, when set to false component will not be rendered.Default is true.
responsivePercentageIf true, boards use percentage-based widths instead of fixed pixel widths.Default is false.
styleInline CSS style of the component.
styleClassStyle class of the component.
valueList of KanbanColumn objects representing the kanban board columns and items.
widgetVarName of the client side widget.Default is generated ('widget_' + componentClientId).
widthBoardDefault width of each board in CSS units, e.g. "250px".Default is 250px.
PrimeFaces Extensions Showcase - © 2011-2026,PrimeFaces: 16.0.0-RC1,PrimeFaces Extensions: 16.0.0-SNAPSHOT,JSF: Apache MyFaces Core 4.0 - Impl 4.0.3,Server: Apache Tomcat (TomEE)/10.1.52 (10.1.4),Build time: 2026-07-24 12:41