Search code examples
javascripthtmltypescriptnext.js

Menu select value is the next menu select


I am trying to achieve this:

My_goal

So you have a select options menu with labels and depending what you select a corresponding value shows.

This value, better said these values should be a next select options menu with labels. The values become labels then basically.

I can show the corresponding values to the selected labels from the first menu but how to make those values selectable labels in a second menu?

So basically:

The_idea

My code:

import { SetStateAction, useState } from "react";

export default function Sort() {
  let selecciones = [
    {
      label: "Price",
      subsorter: [
        { sorter: "cheap to expensive" },
        { sorter: "expensive to cheap" },
        { sorter: "small to big" },
        { sorter: "big to small" }
      ],
    },
    { label: "Distance",
      subsorter: [
        { sorter: "close to far" },
        { sorter: "far to close" },
        { sorter: "beach nearby" },
        { sorter: "restaurant nearby" }
      ],
  },
    { label: "Reviews", colour: "lowest to highest" },
  ];
  let [selecciones, setSelecciones] = useState("Make a seleccion");
  let handleSeleccionChange = (e: {
    target: { value: SetStateAction<string> };
  }) => {
    setSeleccion(e.target.value);
  };
  return (
    <div>
      <div className="flex">
        <div className="">{seleccion}</div>
        <select
          onChange={handleSeleccionChange}>
          <option value="Make a seleccion">-- Filter -- </option>
          {selecciones.map((seleccion) => (
            <option key={seleccion.label} value={seleccion.sorter}>
              {seleccion.label}
            </option>
          ))}
        </select>
      </div>
      <div className="flex">
        <div className="">{seleccion}</div>
        <select
          onChange={handleSeleccionChange}>
          <option value="Select a fruit">-- By -- </option>
          {selecciones.map((seleccion) => (
            <option key={seleccion.label} value={seleccion.sorter}>
              {seleccion.label}
            </option>
          ))}
        </select>
      </div>
    </div>
  );
}

I tried different things and settled in the end with a submenu underneath Price and Distance that needs to be selected (so everything in one menu instead of two). Not what I want sadly but I got stuck.


Solution

  • From my understanding of the problem i tried to show the selection of two dropdown values stored in seperate states or you can use single state using objects.

    import React, { useState, ChangeEvent } from "react";
    
    interface Subsorter {
      sorter: string;
    }
    
    interface Selection {
      label: string;
      subsorter?: Subsorter[];
    }
    
    const selecciones: Selection[] = [
      {
        label: "Price",
        subsorter: [
          { sorter: "cheap to expensive" },
          { sorter: "expensive to cheap" },
          { sorter: "small to big" },
          { sorter: "big to small" },
        ],
      },
      {
        label: "Distance",
        subsorter: [
          { sorter: "close to far" },
          { sorter: "far to close" },
          { sorter: "beach nearby" },
          { sorter: "restaurant nearby" },
        ],
      },
      {
        label: "Reviews",
        subsorter: [{ sorter: "lowest to highest" }],
      },
    ];
    
    export default function Sort() {
      const [selected, setSelected] = useState<string>("Make a selection");
      const [subSelected, setSubSelected] = useState<string>("");
    
      const handleSelectionChange = (e: ChangeEvent<HTMLSelectElement>) => {
        const selectedLabel = e.target.value;
        setSelected(selectedLabel);
    
        // Reset sub-selection when main selection changes
        setSubSelected("");
      };
    
      const handleSubSelectionChange = (e: ChangeEvent<HTMLSelectElement>) => {
        setSubSelected(e.target.value);
      };
    
      // Filter the selected category to get the subsorter options
      const selectedCategory = selecciones.find(
        (category) => category.label === selected
      );
    
      return (
        <div>
          <div className="flex">
            <div className="">{selected}</div>
            <select onChange={handleSelectionChange}>
              <option value="Make a selection">-- Filter --</option>
              {selecciones.map((seleccion) => (
                <option key={seleccion.label} value={seleccion.label}>
                  {seleccion.label}
                </option>
              ))}
            </select>
          </div>
          {selectedCategory && selectedCategory.subsorter && (
            <div className="flex">
              <div className="">{subSelected}</div>
              <select onChange={handleSubSelectionChange}>
                <option value="">-- By --</option>
                {selectedCategory.subsorter.map((sub) => (
                  <option key={sub.sorter} value={sub.sorter}>
                    {sub.sorter}
                  </option>
                ))}
              </select>
            </div>
          )}
        </div>
      );
    }

    hope this helps.