vijayst
vijayst

Reputation: 21846

Display selected option text within Dropdown of Materialize

I am using the Dropdown component in MaterializeCSS.

The following HTML works alright:

  <a class='dropdown-button btn' href='#' data-activates='dropdown1'>Drop Me!</a>
  <ul id='dropdown1' class='dropdown-content'>
    <li><a href="#!">one</a></li>
    <li><a href="#!">two</a></li>
    <li class="divider"></li>
    <li><a href="#!">three</a></li>
    <li><a href="#!"><i class="material-icons">view_module</i>four</a></li>
    <li><a href="#!"><i class="material-icons">cloud</i>five</a></li>
  </ul>

When the option is selected, it navigates to a link. But what I want to happen is, when the option is selected, the "Drop Me!" text is replaced by the text of the selected option. In this case, the text should be one, two, etc.

How do I do that? Thanks.

Upvotes: 0

Views: 1945

Answers (2)

vijayst
vijayst

Reputation: 21846

A custom Dropdown solution using pure React as requested by @Alex

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import DropdownArrow from '../icons/DropdownArrow';
import { Animate } from 'react-move';
import Animation from '../constants/Animation';
import { easeQuadInOut } from 'd3-ease';

export default class Dropdown extends Component {
    state = { isOpen: false };

    componentDidMount() {
        window.addEventListener('scroll', this.handleScroll);
        window.addEventListener('mousedown', this.handleClickOutside);
        window.addEventListener('keydown', this.handleKeyDown, true);
        this.scrollTop =
            window.pageYOffset || document.documentElement.scrollTop;
    }

    componentWillUnmount() {
        window.removeEventListener('scroll', this.handleScroll);
        window.removeEventListener('mousedown', this.handleClickOutside);
        window.removeEventListener('keydown', this.handleKeyDown);
    }

    componentDidUpdate(prevProps, prevState) {
        if (this.state.isOpen && !prevState.isOpen) {
            this.menuComp.scrollTop = this.menuScrollTop || 0;
        }
    }

    handleKeyDown = e => {
        if (e.keyCode == 27) {
            if (this.state.isOpen) {
                e.stopPropagation();
                this.setState({ isOpen: false });
            }
        }
    };

    handleClickOutside = e => {
        if (this.state.isOpen) {
            if (this.comp && !this.comp.contains(e.target)) {
                e.stopPropagation();
                this.setState({ isOpen: false });
            }
        }
    };

    handleScroll = () => {
        const scrollTop =
            window.pageYOffset || document.documentElement.scrollTop;
        if (Math.abs(scrollTop - this.scrollTop) > 2) {
            this.setState({ isOpen: false });
        }
        this.scrollTop = scrollTop;
    };

    handleClick() {
        if (this.props.disabled) return;
        let { isOpen } = this.state;
        isOpen = !isOpen;
        this.setState({ isOpen });
    }

    handleItemClick(value, e) {
        e.preventDefault();
        this.menuScrollTop = this.menuComp.scrollTop;
        this.props.onClick(value);
        this.setState({ isOpen: false });
    }

    getOptionValue(option) {
        return typeof option === 'undefined'
            ? ''
            : typeof option === 'string' ? option : option.value;
    }

    getOptionLabel(option) {
        return typeof option === 'undefined'
            ? this.props.placeholder
            : typeof option === 'string' ? option : option.label;
    }

    renderMenu() {
        const { isOpen } = this.state;
        const { options, selectedOption, height, marginLeft } = this.props;

        return (
            <Animate
                show={isOpen}
                start={() => ({
                    opacity: 0.01,
                    scale: 0.8
                })}
                enter={() => ({
                    opacity: [1],
                    scale: [1],
                    timing: {
                        duration: Animation.DropdownDuration,
                        ease: easeQuadInOut
                    }
                })}
                leave={{
                    opacity: [0.01],
                    scale: [0.8],
                    timing: {
                        duration: Animation.DropdownDuration,
                        ease: easeQuadInOut
                    }
                }}
            >
                {({ opacity, scale }) => {
                    return (
                        <div
                            className="menu-outer"
                            style={{
                                marginLeft,
                                opacity
                            }}
                        >
                            <div
                                className="menu"
                                style={{
                                    maxHeight: height || 368,
                                    overflowY: opacity == 1 ? 'auto' : 'hidden',
                                    opacity,
                                    transform: `scale(${scale})`
                                }}
                                ref={c => {
                                    this.menuComp = c;
                                }}
                            >
                                {options.map(option => (
                                    <div
                                        className={
                                            this.getOptionValue(option) ===
                                            this.getOptionValue(selectedOption)
                                                ? 'menu-item selected'
                                                : 'menu-item'
                                        }
                                        key={this.getOptionValue(option)}
                                    >
                                        <a
                                            href="#"
                                            onClick={this.handleItemClick.bind(
                                                this,
                                                this.getOptionValue(option)
                                            )}
                                            className={
                                                this.getOptionLabel(option)
                                                    .length === 1
                                                    ? 'circle'
                                                    : ''
                                            }
                                        >
                                            {this.getOptionLabel(option)}
                                        </a>
                                    </div>
                                ))}
                            </div>
                            <div className="cover-bar" />
                        </div>
                    );
                }}
            </Animate>
        );
    }

    render() {
        const { options, selectedOption, disabled } = this.props;
        return options.length ? (
            <div
                className={disabled ? 'dropdown disabled' : 'dropdown'}
                ref={c => {
                    this.comp = c;
                }}
            >
                <div className="label" onClick={this.handleClick.bind(this)}>
                    <span>{this.getOptionLabel(selectedOption)}</span>
                    <DropdownArrow width={18} height={18} />
                </div>
                {this.renderMenu()}
            </div>
        ) : null;
    }
}

Dropdown.propTypes = {
    placeholder: PropTypes.string,
    options: PropTypes.array,
    selectedOption: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
    onClick: PropTypes.func,
    height: PropTypes.number,
    marginLeft: PropTypes.number,
    disabled: PropTypes.bool
};

Dropdown.defaultProps = {
    marginLeft: 0
};

And the style for it is:

.dropdown {
    position: relative;
    &.disabled .label {
        color: $color-grey-56;
        cursor: not-allowed;
    }
    .label {
        display: inline-flex;
        align-items: center;
        color: $color-black;
        cursor: pointer;
        &>span {
            font-family: Axiforma;
            font-size: 12px;
            line-height: 16px;
            padding-top: 2px;
        }
    }

    .menu-outer {
        position: absolute;
        z-index: 1500;
        width: 24rem;
        margin-top: 0.8rem;
        border-radius: $border-radius;
        box-shadow: 0 1rem 3rem $color-grey-32;
        transform-origin: 20% 20%;

        .cover-bar {
            width: 20px;
        }

        &:hover .cover-bar {
            opacity: 0;
            transition: opacity 100ms;
        }
    }

    .menu {
        padding: 0.8rem 0;
        background-color: $color-white;

        .menu-item {
            height: 4rem;
            display: flex;
            align-items: center;
            padding-left: 2.4rem;
            a {
                font-family: Axiforma;
                color: $color-grey-56;
                margin-left: -0.8rem;
                padding: 0.8rem;
                border-radius: 1.8rem;
                line-height: 1;
                &.circle {
                    border-radius: 50%;
                    padding: 0;
                    display: inline-flex;
                    width: 30px;
                    height: 30px;
                    justify-content: center;
                    align-items: center;
                }
                &:hover {
                    background-color: $color-yellow-hover;
                }
                &:active {
                    background-color: $color-yellow-active;
                }
            }
            &.selected {
                a {
                    font-family: 'Axiforma SemiBold';
                    color: $color-black;
                    background-color: $color-yellow;
                }
            }
        }
    }
}

Upvotes: 1

Rupal
Rupal

Reputation: 1109

You can do this through jquery on click event trigger. Just find the value of li and set text of drop me to the value of clicked li. Below is the code snippet. I hope this helps..

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

  <!-- Compiled and minified CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">

  <!-- Compiled and minified JavaScript -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
</head>
<body>
<!-- Dropdown Trigger -->
  <a class='dropdown-button btn dropdownBtn' href='#' data-activates='dropdown1'>Drop Me!</a>

  <!-- Dropdown Structure -->
  <ul id='dropdown1' class='dropdown-content'>
    <li><a href="#!">one</a></li>
    <li><a href="#!">two</a></li>
    <li class="divider"></li>
    <li><a href="#!">three</a></li>
    <li><a href="#!"><i class="material-icons">view_module</i>four</a></li>
    <li><a href="#!"><i class="material-icons">cloud</i>five</a></li>
  </ul>
<script type="text/javascript">
    $(document).ready(function(){
        $('.dropdown-button').dropdown('open');
    })
        $('#dropdown1 li').click(function(){

            a = $(this).text()
            $('.dropdownBtn').text(a)
        })
</script>
</body>
</html>

Upvotes: 1

Related Questions