Как совместить Nav с Callout? - PullRequest
0 голосов
/ 03 марта 2019

Я хочу, чтобы элемент навигации появлялся, когда пользователь нажимает кнопку.Итак, я решил совместить Nav и Callout из офисной ткани.

Однако вызов не изменяет свой размер, когда я добавляю / удаляю элементы меню или когда пользователь разворачивает / сворачивает элементы.

Для достижения необходимого результата я создал функцию 'updateSizeи я вызываю его для componentDidMount, componentDidUpdate, linkExpandClick.

Хотелось бы сделать это более элегантным способом.Есть ли один?

PageNav.tsx:

import * as React from 'react';
import { Nav, INavLink } from 'office-ui-fabric-react/lib/Nav';
import { createRef } from 'office-ui-fabric-react/lib/Utilities';

interface PageNavState{
    width: number,
    height: number,
}

export class PageNav extends React.Component<any, PageNavState> {
    static Navigation: INavLink[];

    private divRef = createRef();
    private navRef = createRef();

    constructor(props) {
        super(props);
        this.state = { width: 100, height: 200};
    }

    componentDidMount = () => {
        this.updateSize();
    }

    componentDidUpdate = () => {
        this.updateSize();
    }

    linkExpandClick = () => {
        this.setState({}, this.updateSize);
    }

    updateSize = () => {
        // Does anybody knows a better way to handle size change of the menu?
        var element : any = window.document.getElementsByClassName("nav")["0"];
        if (!element) return;
        element = element["childNodes"];
        if (!element) return;
        element = element["0"];
        if (!element) return;

        var h = element.clientHeight;
        var w = element.clientWidth;

        if (h != this.state.height || w != this.state.width)
        {
            this.setState({height: h, width: w});
        }
    }

    public render(): JSX.Element {

        return (
            <div ref={this.divRef} style= {{height: this.state.height + 54, width: this.state.width}}>
                <Nav className="nav" componentRef={this.navRef}
                    groups={[
                        {
                            links: PageNav.Navigation,
                        }
                    ]}

                    isOnTop={true}
                    expandedStateText={'expanded'}
                    collapsedStateText={'collapsed'}
                    selectedKey={PageNav.getCurrentSelection()}
                    expandButtonAriaLabel={'Expand or collapse'}
                    onLinkExpandClick={this.linkExpandClick}
                />
            </div>
        );
    }

    static getCurrentSelection(): string {
        return window.location.pathname;
    }
}

MenuButton.tsx:

import * as React from 'react';
import { Callout } from 'office-ui-fabric-react/lib/Callout';
import { PageNav } from './pageNav';
import Elements from '../design/elements';
import { Icon } from 'office-ui-fabric-react/lib/Icon';

interface IMenuButtonState {
    isMenuVisible?: boolean;
}

export default class MenuButton extends React.Component<{}, IMenuButtonState> {
    private _menuButtonElement = React.createRef<HTMLDivElement>();

    public constructor(props: {}) {
        super(props);

        this.state = {
            isMenuVisible: false
        };
    }

    public render(): JSX.Element {
        return (
            <div ref={this._menuButtonElement} 
                style={Elements.Menu}>
                <Icon 
                    onClick={this._onShowMenuClicked}
                    iconName="MoreVertical"
                    ariaLabel="Menu"
                />
                <Callout
                    target={this._menuButtonElement.current}
                    onDismiss={this._onCalloutDismiss}
                    setInitialFocus={true}
                    hidden={!this.state.isMenuVisible}
                    calloutMaxHeight={1000}
                    isBeakVisible={false}
                ><PageNav /></Callout>
            </div>
        );
    }

    private _onShowMenuClicked = (): void => {
        this.setState({
            isMenuVisible: !this.state.isMenuVisible
        });
    };

    private _onCalloutDismiss = (): void => {
        this.setState({
            isMenuVisible: false
        });
    };
}
...