Hover on an option element? - javascript

Can I hover an option element to show more options?
I want to have a dropdown nested component like the following screenshot
I have this array of objects and pass it to the DropDown component, if the first object has a field called modules and it has an array of two objects how can I display it as a nested dropdown?
index.js
import React from "react";
import ReactDOM from "react-dom";
import DropDown from "./DropDown";
const availableModules = [
{
text: "environment",
value: "Environment",
modules: [{ key: "greenhouse" }, { key: "protected species" }],
},
{
text: "mobility",
value: "Mobility",
modules: [
{ key: "walk accessibility" },
{ key: "transit accessibility" },
{ key: "travel patterns" },
],
},
{
text: "resiliency",
value: "Resiliency",
modules: [{ key: "flood" }, { key: "fire" }, { key: "earthquake" }],
},
];
ReactDOM.render(
<DropDown availableModules={availableModules} />,
document.getElementById("root")
);
Dropdown.js
const DropDown = ({availableModules}) => {
return (
<div>
<p>Select Option </p>
<select >
{availableModules.map((item, index) => (
<option
value={item.text}
key={index}
>
{item.text}
</option>
))}
</select>
</div>
)
}

Yes, you can. Just render the entire div structure, with all ULs and LIs, and use css to show/hide the menus and submenus.
There is no need to use state for this - showing/hiding via css and detecting hover via css - css alone can handle the job.
On desired LI items, add your click handler as per normal.
<li
onClick={handleDoThisParticularThing}
>
This particular item
</li>
There are many examples online. Just google something like create a nested menu system css
https://css-tricks.com/solved-with-css-dropdown-menus/
https://www.smashingmagazine.com/2017/11/building-accessible-menu-systems/

Related

selected option text not showing in semantic ui dropdown field

I am using React semantic UI. I am rendering a dropdown. I have written code such that, once an option is selected, the options text is shown in the field. But when I select an option from the dropdown, the selected value's text is not displayed, rather it shows an empty field.
Here is my dropdown code:
options = [
{ key:"a", value: 1, name: 'uni', text: "first"},
{ key:"b", value: 2, name: 'duo', text: 'second'},
{ key:"c", value: 3, name: 'tri', text: ' third'},
{ key:"d", value: 4, name: 'quart', text: 'fourth'},
{ key:"e", value: 5, name: 'cinq', text: 'sixth'},
{ key:"f", value: 6, name: 'dernier', text: 'last'}
];
const handleDropDownSelect = (event, data) => {
onChangeValue(data.value)
};
const Dropdown = () => (
return(
<Dropdown
placeholder = abc"
fluid
selection
options={options}
onChange={handleDropDownSelect}
/>)
<DropDownContainer className="Dropdown">
<Dropdown />
</DropDownContainer>
onChangeValue is a function I am using in a different component where I get the value from this dropdown and update other components. So the issue is, when I select an option, the text should be shown in the dropdown field, not left blanc

disable current selection until some value is inputed in the previous selection

I'm working with BootstrapVue.
I have following problem. I have a b-form-input where I'm searching for my number over my b-form-select. So I'm selecting 3 values and get a number in my input field and other way around - so it's an Autofill.
This works fine - and because of that I think I don't need to show you the code.
The problem is that I want to disable all selects (instead of the first) till the field before was selected.
I have problem that if I have multiple elements all will be updated. So if I input something in Input1 in the first element the second Input of all other elements will be !disabled
Additional Info: IDParent is a prop!
If you need any additional code, I can update my question!
<template>
<div>
<div class="mt-2" v-for="(IDChild, indexChild) in inputs" :key="indexChild">
<div>
<div class="mt-2">Number</div>
<b-form-input type="number" v-model="IDChild.Number" :value="IDChild.Number"></b-form-input>
</div>
<div>
<div class="mt-2">Input 1</div>
<b-form-select v-model="IDChild.Input1" :value="IDChild.Input1" :options="optionsInput1" #input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
<div>
<div class="mt-2">Input 2</div>
<b-form-select :disabled="disabledInput2" v-model="IDChild.Input2" :value="IDChild.Input2" :options="optionsInput2" #input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
<div>
<div class="mt-2">Input 3</div>
<b-form-select :disabled="disabledInput3" v-model="IDChild.Input3" :value="IDChild.Input3" :options="optionsInput3" #input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
</div>
<!-- add new element when button was clicked -->
<div class="mt-4 mb-5 ml-3 mr-3">
<b-button #click="addElement"> Add Element </b-button>
</div>
</div>
</template>
my script:
<script>
import json from "./json/json.json";
export default {
name: "Test",
methods: {
addElement() {
this.inputs.push({});
},
searchNumber(input, IDParent, indexChild) {
input.Number = "";
this.json.forEach((element) => {
if (
element.Input1 == input.Input1 &&
element.Input2 == input.Input2 &&
element.Input3 == input.Input3
) {
for (const key of Object.keys(element)) {
input[key] = element[key];
}
}
});
if(input.Input1) {
this.disabledInput2 = false;
}
if(input.Input2) {
this.disabledInput3 = false;
}
},
},
props: [
"IDParent",
],
data() {
return {
inputs: [{}],
json: json,
disabledInput2: true,
disabledInput3: true,
};
},
};
</script>
What you are missing is a multi-layer model for your data which you can call in your searchNumber function and call for your :disabled attribute.
In your v-for="(IDChild, indexChild) in inputs" you could use IDChild or indexChild for that. For example you would call :disabled="disabledInput2[indexChild]". That way you would refer to disabledInput2 with the specific indexChild.
You also need to handle this in your function, for example this.disabledInput2[indexChild] = false;.
Basically it´s the same as storing multi-layer data in the same object with v-model.
EDIT: Generally Example
I´ve created the following properties for this example. We have myNumberInput as an object to handle multiple input fields for numbers. mySelectionData provides a simple collection of two objects with 3 selection arrays each. myDisableData is the object that will handle multiple disabled attributes for this selections:
myNumberInput: {},
mySelectionData: {
1: {
1: [
{ name: "1A", value: 1 }, { name: "2A", value: 2 }, { name: "3A", value: 3 }
],
2: [
{ name: "4A", value: 4 }, { name: "5A", value: 5 }, { name: "6A", value: 6 }
],
3: [
{ name: "7A", value: 7 }, { name: "8A", value: 8 }, { name: "9A", value: 9 }
]
},
2: {
1: [
{ name: "1B", value: 11 }, { name: "2B", value: 21 }, { name: "3B", value: 31 }
],
2: [
{ name: "4B", value: 41 }, { name: "5B", value: 51 }, { name: "6B", value: 61 }
],
3: [
{ name: "7B", value: 71 }, { name: "8B", value: 81 }, { name: "9B", value: 91 }
]
}
},
myDisableData: {}
From the mySelectionData object, we will build our myDisableData with this function:
setupMyDisableData() {
Object.keys(this.mySelectionData).forEach(parent_key => {
Object.assign(this.myDisableData, {[parent_key]: {}})
Object.keys(this.mySelectionData[parent_key]).forEach(child_key => {
Object.assign(this.myDisableData[parent_key], {[child_key]: true})
});
});
}
This will loop trough our "parents", assign their index to myDisableData and also loop trough the "childs" and assign their index to myDisableData with the "parent"-index as a pointer. After that we have a multi-layer object which is able to provide diabled= true or false for each selection.
The html for this example looks like this:
<div v-for="(item,index) in mySelectionData" :key="index">
<input type="number" v-model="myNumberInput[index]" #input="enableMySelection(index, myNumberInput[index])">
<div v-for="(child_item, child_index) in item" :key="child_index">
<select :disabled="myDisableData[index][child_index]">
<option v-for="(child_option, child_option_index) in child_item" :key="child_option_index" :value="child_option.value">{{child_option.name}}</option>
</select>
</div>
</div>
As I don´t use BootstrapVue, my html looks different, but I guess you will get the trick. You simply now refer to the three object by the index of "parent" and "child". In this example the function enableMySelection will enable a selection depending on the number entered in the input. The function looks like this:
enableMySelection(parent_index, input_number) {
Object.keys(this.myDisableData[parent_index]).forEach(child_key => {
this.myDisableData[parent_index][child_key] = true;
});
this.myDisableData[parent_index][input_number] = false;
}
So if you enter "2" in your first input, it will enable the second selection of the first block. If you enter 1 in the second input, it will enable the first selection in the second block.
As I said, this is just a generally example but this should be enough to help you define the structure to handle your multiple inputs and selections.

display options in react search box when clicking on the box

I am trying the following code
import React, { Component } from 'react'
import ReactSearchBox from 'react-search-box'
export default class App extends Component {
data = [
{
key: 'john',
value: 'John Doe',
},
{
key: 'jane',
value: 'Jane Doe',
},
{
key: 'mary',
value: 'Mary Phillips',
},
{
key: 'robert',
value: 'Robert',
},
{
key: 'karius',
value: 'Karius',
},
]
render() {
return (
<ReactSearchBox
placeholder="Placeholder"
value="Doe"
data={this.data}
callback={record => console.log(record)}
/>
)
}
}
and it works really. However the search options only show when I start typing in the searchbox. What I am trying to do is when the user clicks in the search, show them some options, Can you help with understanding how to achieve that.
there is a method called
onFocus - A function which acts as a callback when the input is focussed.
which does get called when I click in the search box, but I am not able to work out how to display the options in the dropdown.
import React, { Component } from 'react'
import Select from 'react-select'
export default class App extends Component {
state = {
selectedValue:null
}
data = [
{
label: 'john',
value: 'John Doe',
},
{
label: 'jane',
value: 'Jane Doe',
},
{
label: 'mary',
value: 'Mary Phillips',
},
{
label: 'robert',
value: 'Robert',
},
{
label: 'karius',
value: 'Karius',
},
]
render() {
return (
<Select
options={this.data}
isSearchable
value={this.state.selectedValue}
onChange={this.handleChange}
/>
)
}
}
If you want to display a dropdown with search option I would recommend using react-select library. However your data should be in the form of an object like this {label:' ',value:' '}. This component takes an isSearchable prop that allows us to search the dropdown as well as select an option manually. Hope this helps!

Multi Level drop-down in ReactJS

I'm trying to implement multilevel nested drop-down. I have made use of "react-dropdown". A new dropdown that appears so be displayed just below. But I'm unable to implement nested dropdown.
what to achieve something like this
this is my output
import React from "react";
import Dropdown from "react-dropdown";
import 'react-dropdown/style.css';
const object = [
{value: 'course',
lable: "course" ,
submenu: [
{ value: "PCF8883US/7EA/1Y", lable: "PCF8883US/7EA/1Y"},
{ value: "AT42QT1050-UUR", lable: "AT42QT1050-UUR" },
{ value: "PCF8883", lable: "PCF8883"}
]
},
{value: "code",
lable:"code",
submenu: [
{ value: "MC3672", lable: "MC3672"},
{ value: "MXC400XXC", lable: "MXC400XXC"}
]
}
]
const course = [
{ value: "PCF8883US/7EA/1Y", lable: "PCF8883US/7EA/1Y"},
{ value: "AT42QT1050-UUR", lable: "AT42QT1050-UUR" },
{ value: "PCF8883", lable: "PCF8883"}
]
const code = [
{ value: "MC3672", lable: "MC3672"},
{ value: "MXC400XXC", lable: "MXC400XXC"}
]
export class WorkSpace extends React.Component {
render() {
return (
<div className="base_container">
<div className="left">
<h3>Select Component</h3>
<div>
<Dropdown options={object} placeholder="Name">
<Dropdown options={course} onChange={this._onSelect} placeholder="course" />
<Dropdown options={code} onChange={this._onSelect} placeholder="code"/>
</Dropdown>
</div>
</div>
</div>
);
}
}
You could try the library React Treebeard. It gives a UI almost exactly like your example.

Allow to type values that are not in options

Basically, I have not find a way to setup select component to allow values that are not in the option set. I know that select suggests that it must be a selection. But I am looking to make it act more like an autocomplete. Any knowledge on that?
Try This:
import react-select
$ yarn add react-select#next
# or, using npm:
$ npm install react-select#next
The dropdown is searchable.
import React from 'react';
import Select from 'react-select';
const tools = [
{ label: "Hammer", value: 1 },
{ label: "Hand Drill", value: 2 },
{ label: "Tape Rule", value: 3 },
{ label: "Saw", value: 4 },
{ label: "Ruler", value: 5 },
{ label: "Soldering Iron", value: 6 },
];
const App = () => (
<div className="app">
<div className="container">
<Select options={tools} />
</div>
</div>
);

Categories

Resources