Utilizing SubHeaders in Material UI Select Menu for Enhanced Organization

I'm facing a challenge in setting up a lengthy list of Menu Items on a Select control that incorporates sticky SubHeaders. The issue arises when the items scroll, as they end up obstructing the subheaders.

To tackle this problem, I examined the Material UI examples of grouped Select items as a reference point. My goal is to achieve a similar behavior to the Material UI example featuring pinned subHeader Lists.

You can find a working example on codeSandbox showcasing what I've been attempting.

Below is a snippet from my code:

<Select
        className={classes.root}
        MenuProps={{ className: classes.menu }}
        value="Pick one"
        onChange={e => {}}
      >
        {subHeaders.map(header => (
          <li key={header}>
            <ul>
              <ListSubheader>{header}</ListSubheader>
              {items.map(item => (
                <MenuItem key={item} value={item}>
                  {item}
                </MenuItem>
              ))}
            </ul>
          </li>
        ))}
      </Select>

This snapshot depicts the issue faced:

https://i.sstatic.net/ii2Vy.png

Answer №1

Utilizing the Select component, we can replicate the desired behavior with some adjustments. However, it may not be suitable for your specific needs as the Select component does not support nested items within child elements, making it difficult to identify the selected element.

Alternatively, you can explore the functionalities of the Autocomplete component which may better cater to your requirements.

https://i.sstatic.net/KcjhL.png

In reference to the provided example, there are possible solutions available, although maintaining the state of the selected item might pose a challenge. To align the behavior with the list, similar actions need to be applied to the menu that will be rendered by the Select component. Utilizing the prop MenuListProps, you can mimic the behavior from the list example.

I have made the necessary adjustments to your example.

https://codesandbox.io/s/select-menu-subheaders-z23fi

I hope this information proves helpful.

Answer №2

I successfully implemented a solution using Material-ui select with sticky MenuItems.

Instead of using all the

<li>, <ul>, <ListSubheader>
, utilize MaterialUI MenuItem.

    const [isOpen, setIsOpen] = useState(false);
    const [value, setValue] = useState();
    
    const onToggle = () => {
        setIsOpen((prev) => !prev);
      };
    
    const onClose = () => {
        setIsOpen(false);
      };
    
    const _onChange = (event: React.ChangeEvent<{ value: unknown }>) => {
        const valueToSelect = event.target.value as Value;
        if (
          isResetSeletced(valueToSelect) ||
          (multiple
            ? !valueToSelect.length ||
              valueToSelect.length < minSelections ||
              (valueToSelect as string[]).some((option) => !option)
            : !valueToSelect?.length && minSelections > 0)
        ) {
          return;
        }
        event.persist();
        onChange(valueToSelect);
      };
    
      const renderValue = (selected: any) => {
        if (!selected.length) {
          return '';
        }
        if (multiple) {
          const isReachedLimit = selected.length > MAX_SELECTIONS;
          const hiddenTags = isReachedLimit ? (
            <span>+{value.length - MAX_SELECTIONS}</span>
          ) : null;
          const selectionsToShow = isReachedLimit
            ? selected.slice(0, MAX_SELECTIONS)
            : selected;
          return (
            <StyledTagsContainer>
              <Tags values={selectionsToShow} onRemoveTag={onRemoveTag} />
              {hiddenTags}
            </StyledTagsContainer>
          );
        }
        return selected;
      };


  const resetMenuItem = secondaryOptions?.map((resetItem, index) => {
    return (
      <MenuItem
        key={resetItem.value + index}
        onClick={() => {
          resetItem.onClick();
        }}
        isLast={!index}
        isSelected={
          resetItem.value === resetSelected?.value ||
          resetItem.value === value ||
          (multiple && resetItem.value === value[0])
        }
        value={resetItem.value}
        icon={<RadioIcon />}
      >
        {resetItem.text}
      </MenuItem>
    );
  });
    
    
    <Select
        displayEmpty
        onClose={onClose}
        value={value}
        onChange={_onChange}
        renderValue={renderValue}
        open={isOpen}
      >
        {menuItems}

        <div style={{ position: 'sticky', bottom: 0 }}>
          {resetMenuItem}
        </div>

    </Select>

Answer №3

I encountered a similar issue that required a specific solution to resolve. For optimal functionality, ensure that you have just one list structured in the following format:

[
  {
     value,
     text,
     isParent (is section)
  }
]

It is crucial for this list to be organized in the following order: Parent 1 - Child 1 (parent 1) - Child 2 (parent 1) - Parent 2 - Child 1 (parent 2)....

Subsequently:

const array = [
  { text: 'parent 1', isParent: true }, 
  { text: 'child 1 parent 1', value: 2, isParent: false }, 
  { text: 'child 2 parent 1', value: 3, isParent: false }, 
  { text: 'parent 2', isParent: true }, 
  { text: 'child 1 parent 2', value: 4, isParent: false }, 
  { text: 'child 2 parent 2', value: 5, isParent: false }, 
]

<Select>
  {array.map(option => {
    if(option.isParent)
      return (
        <ListSubheader>
          {option.text}
        </ListSubheader>
      )
    else
      return (
        <MenuItem 
          value={option.value}
        >
          {option.text}
        </MenuItem>
      )
  })}
</Select>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for obtaining authorization to access user information?

I am facing a perplexing issue with my app settings. Despite setting everything up correctly, I am unable to authenticate my account on my website using the Javascript SDK. Whenever I try to console.log(me), I only receive public information. Upon furthe ...

Creating interactive JSON objects through the use of JavaScript and AngularJS

When using AngularJS to build a dynamic JSON from server data, I encountered an issue where my current declaration only works if the server data contains one item in the object array. How can I modify this to handle multiple items dynamically? $scope.it ...

A guide on transforming a JSON object representing an HTML element into a live HTML element for display on a webpage using C#, JavaScript, or jQuery

I am looking to retrieve a JSON object from a database and convert it into HTML format. Here is an example of the JSON structure: {"input":{ "name":"fname", "type":"text", "placeholder":"Ente ...

What is the most efficient method for storing and accessing a large matrix in JavaScript?

With 10000 items, creating a matrix of 10000 rows * 10000 columns using a one-dimensional array would be massive. Additionally, setting specific values to cells (i,j) where 0 < i, j < 10000 would require a large number of iterations. I am facing cha ...

Tips for resolving a blank screen issue when attempting to render components using the `:is="component"` attribute

Working with NativeScript-Vue for Android, my goal is to display a component based on button taps. To achieve this, I am utilizing this plugin which helps in integrating a global SideDrawer for smooth navigation. The buttons within the SideDrawer are used ...

The option to clear searches is missing from the iOS interface

My application is designed to perform searches using post codes, and for the most part, it functions properly. However, I have encountered an issue where the clear icon on the right-hand side of the field does not display in certain browsers. To investiga ...

Issue encountered while configuring server using express.js

Here is the server.js file I am working on, but I encounter a specific error when trying to set up the server with Express.js var express = require('express'); var app = express(); var PORT = process.env.PORT || 3000; app.all('/*', ...

Make the object rotate around a specified vector point

I have been trying to figure out how to make an object orbit around the vector coordinates 0,0,0. Specifically, if the object is at X300, Y50, Z200, I want it to revolve around 0,0,0 without changing the position on the Y axis. Math isn't my strong su ...

Trouble arises when attempting to delete rows from my database with the use of HTML, PHP, and

I am developing an application where I have implemented this table: <?php require_once 'Connect2db3.php'; ?> <form> <fieldset> <article class="rondehoeken"> <header> <div class="streep1"></div& ...

Error: The function or method save() has not been resolved

The function model.save() for mongoose is not being properly defined. models/genre.js 'use strict'; const mongoose = require('mongoose'); const Schema = mongoose.Schema; const GenreSchema = new Schema({ name: {type: String, requi ...

Setting a class in AngularJS when there is a change in ng-repeat with pagination

I am currently attempting to assign a class to an item in a paginated list by simulating a click on the element within the directive's link property: link : function (scope, element, attrs) { element.bind('click', function () { ...

Angular directive becomes disabled when transferred between different DOM elements

In my app, I utilize a modal service that handles the opening and closing of modals. The modal retrieves its content from a specific div with an ID located within a hidden container element. This process typically functions correctly. The issue I am encou ...

Is it possible to assign variables inside an http call from a function in AngularJS?

Seeking urgent assistance. I need help with a function that resembles the following: $scope.getData = function(id) { $http.get('/url' + id).success(function (data) { return data.a.b.c; }); }; In another function, I have the fol ...

Extract specific nested elements

Looking for assistance with extracting specific nested objects from a series structured like so: data = {"12345":{"value":{"1":"2","3":"4"}}, {"12346":{"value":{"5":"6","7":"8"}}, {"12347":{"value":{"9":"0","11":"22"}} In need of creating a functio ...

Attempting to reduce the width of the dig when it reaches 400

I have a square element with a click event that increases its size by 50 pixels on each click. However, once it reaches a size of 400 pixels, the size decreases by 50 pixels with every click instead. Additionally, when the size of the square reaches 100 p ...

What is the best way to extract user input and pass it to an AJAX request URL?

Recently, I successfully completed an AJAX request using AngularJS. You can check out the code here. Everything was working perfectly until I tried to add a dynamic variable (city) to the link like this: $http.get('http://api.wunderground.com/api/KEY ...

What is causing the 'transitionend' event to trigger multiple times?

Currently, I'm honing my JavaScript skills by taking on the 30 days of JavaScript challenge. I'm puzzled by why the 'transitioned' event is triggered twice in the code snippet below. My CSS only contains one property called transform, ...

Executing a function right away when it run is a trait of a React functional component

Having a fully functional React component with useState hooks, and an array containing five text input fields whose values are stored in the state within an array can be quite challenging. The main issue I am facing is that I need to update the inputfields ...

Javascript program that generates drag and drop elements using HTML5 features:

Whenever I attempt to drag and drop elements that are normally created by HTML, everything works fine. However, when I try to drag and drop elements generated by JavaScript, I encounter the following error: Uncaught TypeError: Cannot read property 'p ...

Error: Unable to assign value to property 'className' of undefined object

On my http://localhost:3000/renewal page, the code looks like this: import Link from 'next/link' export default function Renewal() { return ( <header> <Link href="/"> <a> Go to home page ...