Arpit Pathak
Arpit Pathak

Reputation: 19

Creating Sidemenu from a List

Hi I have a sharepoint site , There i have created a List now i want to create a sidemenu from this List. Basically when we add item in the list it shows up as a nav menu in side bar .

The list items are :

  1. Title
  2. url
  3. order
  4. Visible to ( people picker ) these three are the main component of my list

What i want is to create a visual web part using c# , office to create a solution .

Please tell me how to do so

I tried creating it myself but i am new to this job so my solution was not very successfull

Upvotes: 0

Views: 16

Answers (1)

KDM
KDM

Reputation: 30

I have created a solution similar to what you need using JSOM (JavaScript Object Model) and JQuery. So basically you need to place this JS, HTML and CSS code somewhere in the page:

$(document).ready(function () {
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', loadMenuItems)
})

function loadMenuItems() {
    var clientContext = new SP.ClientContext.get_current()
    var web = clientContext.get_web()
    var list = web.get_lists().getByTitle('RightMenu')
    var camlQuery = new SP.CamlQuery()
    camlQuery.set_viewXml('<View><Query><OrderBy><FieldRef Name="Orderby" Ascending="TRUE" /></OrderBy></Query></View>')
    var listItems = list.getItems(camlQuery)
    clientContext.load(listItems)
    clientContext.executeQueryAsync(
        function () { 
            createMenuObject(listItems)
        },
        function (sender, args) { 
            console.log('Error: ' + args.get_message())
        }
    )
}
function createMenuObject(listItems) {
    var currentUser = _spPageContextInfo.userId
    var allItems = []

    // Process items into an array for sorting
    var enumerator = listItems.getEnumerator()
    while (enumerator.moveNext()) {
        var item = enumerator.get_current()
        var orderby = item.get_item('Orderby')
        var permissions = item.get_item('UserGroup')
        if (isUserInPermissionsField(permissions, currentUser)) {
            allItems.push({
                id: item.get_item('ID'),
                title: item.get_item('Title'),
                url: item.get_item('Url'),
                icon: item.get_item('Iconimg'),
                parentID: item.get_item('Child') ? item.get_item('Child').get_lookupId() : null,
                orderby: orderby,
                children: []
            })
        }
    }

    // Sort
    allItems.sort((a, b) => a.orderby - b.orderby)

    // Build the hierarchical menu structure
    var menuItems = []
    var itemMap = {}

    // First pass: Add all items to the lookup map
    allItems.forEach(item => {
        itemMap[item.id] = item

        // Root-level items
        if (!item.parentID) {
            menuItems.push(item)
        }

    })

    // Second pass: Assign children to their parents
    allItems.forEach(item => {
        if (item.parentID && itemMap[item.parentID]) {
            itemMap[item.parentID].children.push(item)
        }
    })

    // Build the HTML
    buildMenu(menuItems)

}
function isUserInPermissionsField(permissions, currentUserId) {

    // If no permissions are defined, assume all users have access
    if (!permissions || permissions.length === 0) {
        return true
    }

    // Use Array.prototype.some for a concise and efficient check
    return permissions.some(permission => permission.get_lookupId() === currentUserId)

}
function buildMenu(menuItems) {
    const buildChildMenu = (children) => {
        return children.map(childItem => {
            const childIconHtml = childItem.icon ? `<img src="${childItem.icon}" alt="" class="menu-icon"/>` : ''
            const hasChildren = childItem.children.length > 0
            return `
                <li>
                    <a title="${childItem.title}" href="${childItem.url}" class="${hasChildren ? 'parent-item' : ''}">
                        ${childIconHtml}${childItem.title}${hasChildren ? '<span class="crossKDM">➕</span>' : ''}
                    </a>
                    ${hasChildren ? `<ul class="child-menu" style="display:none;">${buildChildMenu(childItem.children)}</ul>` : ''}
                </li>`
        }).join('')
    };

    // Build top-level menu
    const menuHtml = `
        <ul>
            ${menuItems.map(parentItem => {
                const parentIconHtml = parentItem.icon ? `<img src="${parentItem.icon}" alt="" class="menu-icon"/>` : ''
                const hasChildren = parentItem.children.length > 0

                return `
                    <li>
                        <a title="${parentItem.title}" href="${parentItem.url}" class="${hasChildren ? 'parent-item' : ''}">
                            ${parentIconHtml}${parentItem.title}${hasChildren ? '<span class="crossKDM">➕</span>' : ''}
                        </a>
                        ${hasChildren ? `<ul class="child-menu" style="display:none;">${buildChildMenu(parentItem.children)}</ul>` : ''}
                    </li>`
            }).join('')}
        </ul>`

    // Append menu HTML to placeholder
    $('#menuPlaceholder').html(menuHtml)

    // Add toggle functionality to parent items
    $('.parent-item').on('click', function (e) {
        e.preventDefault()
        $(this).next('.child-menu').slideToggle('fast')
        $(this).find('.crossKDM').toggleClass('crossRotated')
    })

}
#menuPlaceholder li {
    list-style: none;
    border-bottom: 1px dashed #7caad0;
    padding-bottom: .25em;
    padding-top: .25em;
}
#menuPlaceholder a {
    color: white;
}
#menuPlaceholder li:last-child {
    border-bottom: none
}
#menuPlaceholder ul.child-menu {
    background: #ebffff;
    border-radius: .5em;
    padding: .5em;
    margin-top: .5em;
    margin-bottom: .5em;
}
#menuPlaceholder ul.child-menu a {
    color: #0c497c
}
.crossKDM {
    transition: .2s all;
    top: .15em;
    float: left;
    position: relative;
    filter: invert(1);
}
.crossRotated {
    rotate: 135deg;
    transform: scale(1.3);
}
<div id="menuPlaceholder"></div>
In the above code, the RightMenu is the name of my SharePoint list which contains menu items and the Orderby is the name of the column for specifying item orders.

Upvotes: 1

Related Questions