Modal Dialog

General


Modal Dialog

Allows user to interact with it before they can go back to using the parent application.

Modal Dialog (Video)

Use the following HTML code to fire video.

Show Code
import React from "react";
import ModalDialog from 'funda-ui/ModalDialog';
 
export default () => {
 
    return (
        <>
 
            <h3>Modal Dialog</h3>
            <p>Allows user to interact with it before they can go back to using the parent application.</p>
            {/* ================================================================== */}
            <ModalDialog
                show={false}
                data="mydata"
                heading="Title Here"
                triggerClassName="d-inline w-auto"
                triggerContent={<>
                    <a href="#" tabIndex={-1} onClick={(e: React.MouseEvent) => {e.preventDefault()}}>Launch demo modal</a>
                </>}
                closeBtnClassName="btn btn-secondary"
                closeBtnLabel="Close"
                submitBtnClassName="btn btn-primary"
                submitBtnLabel={<><i className="fa fa-paper-plane"></i> Save</>}
                onOpen={(e, closewin) => {
                    if (e === null) return;
                    
                    console.log('open: ', e.target);
 
                    const myAppBtn = document.querySelector('#app-mybtn');
                    
                    myAppBtn?.addEventListener('pointerdown', (e) => {
                        e.preventDefault();
                        console.log('click event');
                        closewin();
                    });
 
 
 
                }}
                onClose={(e) => {
                    if (e === null) return;
 
                    console.log('close: ', e.target);
 
                    // Remove all Event Listeners
                    const myAppBtn = document.querySelector('#app-mybtn');
                    myAppBtn?.replaceWith(myAppBtn?.cloneNode(true));   
 
                }}
                onSubmit={(e, closewin, data) => {
                    if (e === null) return;
                    
                    console.log('submit: ', e.target, data);
                    e.target.disabled = true;
                    e.target.innerHTML = '<i class="fa fa-spinner fa-spin fa-fw"></i> Loading...'
 
                    setTimeout(() => {
                        closewin();
                        e.target.disabled = false;
                        e.target.innerHTML = '<i class="fa fa-paper-plane"></i> Save</>'
                    },1000);
                }}
                closeOnlyBtn
 
            >
                <h4>click the button below!!</h4>
                <p><button type="button" id="app-mybtn">this is an event</button></p>
            </ModalDialog>
 
 
            <h3>Modal Dialog (Video)</h3>
            <p>Use the following HTML code to fire video.</p>
            {/* ================================================================== */}
            <ModalDialog
                show={false}
                enableVideo={true}
                maxWidth="1200px"
                triggerClassName="d-inline w-auto"
                triggerContent={<>
                    <a href="#" tabIndex={-1} onClick={(e: React.MouseEvent) => {e.preventDefault()}}>Launch demo modal</a>
                </>}
            >
                <video playsInline controls poster="https://uiux.cc/uix-kit/assets/videos/480x270/demo.jpg" src="https://uiux.cc/uix-kit/assets/videos/480x270/demo.mp4"></video>
            </ModalDialog>
            
 
            <ModalDialog
                show={false}
                enableVideo={true}
                maxWidth="1200px"
                maskOpacity={0.2}
                triggerClassName="d-inline w-auto"
                triggerContent={<>
                    <a href="#" tabIndex={-1} onClick={(e: React.MouseEvent) => {e.preventDefault()}}>Launch demo modal</a>
                </>}
            >
                <iframe width="560" height="315" src="https://www.youtube.com/embed/VYdzttKU5H0?si=K7tXPlPgiuyJaoXp" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen></iframe>
            </ModalDialog>
 
        </>
    );
}

Display Number of CountDown & Automatically open&close the pop-up window


Show Code
import React, { useEffect, useState, useRef, useCallback  } from "react";
import ModalDialog from 'funda-ui/ModalDialog';
 
export default () => {
 
    const [autoCloseCount, setAutoCloseCount] = useState<number>(6);
    const intervalIdRef = useRef<any>(null);
    const startTimer = useCallback(() => {
        intervalIdRef.current = setInterval(() => {
 
        
            setAutoCloseCount((prevState: number) => {
                let _val = prevState;
                if ( _val > 0 ) {
                    _val = _val - 1;
                } else {
                    stopTimer();
                }
                console.log('***', _val)
 
                return _val;
            });
 
 
 
        }, 1000);
    }, []);
    
 
    const stopTimer = useCallback(() => {
        clearInterval(intervalIdRef.current);
        intervalIdRef.current = null;
    }, []);
 
 
    useEffect(() => {
 
        startTimer();
 
        return () => {
            stopTimer();
        }
 
    }, []);
    
 
 
    return (
        <>
 
 
            <ModalDialog
                show={true}
                autoClose={6000}
                triggerClassName="d-inline w-auto"
                triggerContent={<>
                    <a href="#" tabIndex={-1} onClick={(e: React.MouseEvent) => {e.preventDefault()}}>Launch demo modal</a>
                </>}
                maskDisabled
            >
                <h4>This window will automatically close after {autoCloseCount} seconds :)</h4>
                <p>You can click the button on the page to trigger the pop-up window.</p>
            </ModalDialog>
 
 
 
        </>
    );
}

Custom content area without spacing and sticky


Show Code
import React from "react";
import ModalDialog from 'funda-ui/ModalDialog';
 
export default () => {
 
    const [closeModalFunc, setCloseModalFunc] = useState<Function | null>(null);
 
    return (
        <>
 
            <ModalDialog
                modalBodyClassName="p-0"
                show={false}
                maxWidth="850px"
                minHeight="175px"
                heading="Title Here"
                triggerClassName="d-inline w-auto"
                triggerContent={<>
                    <a href="#" tabIndex={-1} onClick={(e: React.MouseEvent) => {e.preventDefault()}}>Launch demo modal</a>
                </>}
                onOpen={(e, closewin) => {
                    setCloseModalFunc(() => closewin);
                }}
            >
 
                <div className="custom-content">
 
                    {/* NAV */}
                    <div className="position-sticky top-0 p-2 px-3 z-2 bg-body border-bottom">
                        <strong>Navigation</strong>
                    </div>
                    {/* /NAV */}
 
 
 
                    {/* CONTENT */}
                    <div className="p-3">
                        content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />content here...<br />
                    </div>
                    {/* /CONTENT */}
 
                
                    {/* TOOLBOX */}
                    <div className="border-top position-sticky bottom-0 px-3 z-2 bg-body pb-2">
 
                        <div className="text-start pt-2">
 
                            <div className="row g-3 align-items-center">
                                <div className="col-auto text-start">
                                    <button tabIndex={-1} type="button" className="btn btn-secondary my-1 btn-sm">Button 1</button>
                                    <button tabIndex={-1} type="button" className="btn mx-1 my-1 btn-sm ms-2 btn-outline-secondary"><small>Button 2</small></button>
                                    <button tabIndex={-1} type="button" className="btn mx-1 my-1 btn-sm ms-2 btn-outline-secondary"><small>Button 3</small></button>
                                </div>
                                <div className="col-auto gx-0">
                                    <input type="text" placeholder="Input" className="form-control form-control-sm" style={{ width: '100px' }} />
                                </div>
                                <div className="col text-end">
                                    <button tabIndex={-1} type="button" className="btn btn-outline-secondary btn-sm text-decoration-none" onClick={(e: React.MouseEvent) => {
                                        closeModalFunc?.();
                                    }}>Discard</button>
                                    <button tabIndex={-1} type="button" className="btn btn-primary btn-sm text-decoration-none ms-2" onClick={(e: React.MouseEvent) => {
                                        // do something...
 
                                        // close
                                        closeModalFunc?.();
                                    }}>Confirm</button>
                                </div>
                            </div>
                        </div>
                    </div>
                    {/* /TOOLBOX */}
 
                </div>
            </ModalDialog>
 
        </>
    );
}

Asynchronous Usage

Do not use trigger to bind Modal, and expose OPEN and CLOSE methods, which can be called in your code freely. It is usually used to process asynchronous data.


click here to open
Show Code
import React, { useState, useEffect, useRef } from "react";
import ModalDialog from 'funda-ui/ModalDialog';
 
class DataService {
 
 
    // "Date.now()" is used to detect mutable asynchronous data
    async getList() {
        return {
            code: 0,
            message: 'OK',
            data: [
                { item_name: 'foo' + Date.now(), item_code: 'bar' },
                { item_name: 'foo2' + Date.now(), item_code: 'bar2' },
                { item_name: 'foo3' + Date.now(), item_code: 'bar3' }
            ]
        };
    }
 
}
 
 
export default () => {
 
    const timer = useRef<any>(null); // we can save timer in useRef and pass it to child
    const [show, setShow] = useState<boolean>(false);
    const [data, setData] = useState<any[]>([]);
    const [fetchOk, setFetchOk] = useState<boolean>(false);
    
    
    function fetchData() {
        const service = new DataService();
        service.getList().then(function (response: any) {
            setData(response.data);
            setFetchOk(true);
            
        });
    }
 
    function handleClick(e: any) {
        e.preventDefault();
        
        fetchData();
        setShow(true);
 
        // auto close
        timer.current = setTimeout(() => {
            setShow(false);
        }, 3000);
 
    }
 
    useEffect(() => {
 
        if (!fetchOk) {
            fetchData();
        }
 
    }, []);
 
 
    return (
        <>
 
            <a href="#" onClick={handleClick}>click here to open</a>
            <ModalDialog
                show={show}
                heading="Choose a block"
                triggerClassName=""
                triggerContent=""
                onOpen={(e, closewin) => {
 
                    // Use "setTimeout()" to ensure asynchronous data exists
                    setTimeout(() => {
                        const btns = document.querySelectorAll('#app-mydata-list > a');
 
                        [].slice.call(btns).forEach((node: any) => {
 
                            // Prevent touch screen from starting to click option, DO NOT USE "pointerdown"
                            node?.addEventListener('click', (e: any) => {
                                e.preventDefault();
 
                                // do something
                                console.log(e.currentTarget.dataset.name);
                                closewin();
 
                            });
                        });
                    }, 0);
 
                }}
                onClose={(e) => {
 
                    clearTimeout(timer.current);
 
                    // Remove all Event Listeners
                    const btns = document.querySelectorAll('#app-mydata-list > a');
                    [].slice.call(btns).forEach((node: any) => {
                        node?.replaceWith(node?.cloneNode(true));
                    });
 
                    // Modifying React State can ensure that the window content is updated in real time
                    setTimeout(() => {
                        setData([]);
                        setShow(false);
                    }, 350);
 
 
                }}
            >
                {data.length > 0 ? <>
 
                    <div id="app-mydata-list">
                        {data ? data.map((item, i) => {
                            return <a href="#" tabIndex={-1} key={i} data-name={`${item.item_code}`} style={{display: 'block'}}>{item.item_name}</a>;
                        }) : null}
 
                    </div>
 
                </> : null}
 
            </ModalDialog>
 
        </>
    )
}

Using exposed OPEN and CLOSE methods

Lets you callback the handle exposed as attribute ref.


open modal  |  close modal
Show Code
import React, { useRef } from "react";
import ModalDialog from 'funda-ui/ModalDialog';
 
export default () => {
 
    const modalHandleRef = useRef<any>();
 
    function handleOpen(e: any) {
        if (typeof e !== 'undefined' && e !== null) e.preventDefault();
        if (modalHandleRef.current) modalHandleRef.current.open();
      
    }
 
    function handleClose(e: any) {
        if (typeof e !== 'undefined' && e !== null) e.preventDefault();
        if (modalHandleRef.current) modalHandleRef.current.close();
      
    }
 
    return (
        <>
 
            <a href="#" onClick={handleOpen}>open modal</a>
            &nbsp;&nbsp;|&nbsp;&nbsp;
            <a href="#" onClick={handleClose}>close modal</a>
            <ModalDialog
                ref={modalHandleRef}
                show={false}
                maskDisabled
            >
                <h4>This is a modal</h4>
            </ModalDialog>
 
 
        </>
    );
}

Using child component


Show Code
import React, { useRef } from "react";
import ModalDialog from 'funda-ui/ModalDialog';
 
 
// child component
const Child = ({id}) => {
    return <>ID: {id}</>;
}
 
export default () => {
 
    const formRef = useRef<any>(null);
 
    return (
        <>
 
            <ModalDialog
                show={false}
                data="mydata"
                heading="Title Here"
                triggerClassName="d-inline w-auto"
                triggerContent={<>
                    <a href="#" tabIndex={-1} onClick={(e: React.MouseEvent) => {e.preventDefault()}}>Launch demo modal</a>
                </>}
                closeBtnClassName="btn bg-secondary text-white"
                closeBtnLabel="Close"
            >
                <div ref={formRef}>
                    <Child id={Math.random()} key={Math.random()} /> {/* The child component in the Modal need to use [key] to ensure that they are updated at any time.*/}
                </div>
            </ModalDialog>
 
 
        </>
    );
}

Fullscreen


Show Code
import React from "react";
import ModalDialog from 'funda-ui/ModalDialog';
 
export default () => {
    return (
        <>
            <ModalDialog
                ...
                fullscreen
                ...
            >
                <h4>This is a modal</h4>
            </ModalDialog>
        </>
    );
}

Modal that cannot be closed


Show Code
import React from "react";
import ModalDialog from 'funda-ui/ModalDialog';
 
export default () => {
    return (
        <>
            <ModalDialog
                ...
                closeOnlyBtn
                closeDisabled
                ...
            >
                <h4>This is a modal</h4>
            </ModalDialog>
        </>
    );
}

Draggable


Show Code
import React from "react";
import ModalDialog from 'funda-ui/ModalDialog';
 
export default () => {
    return (
        <>
            <ModalDialog
                ...
                draggable
                draggedPreventOutsideScreen={{
                    xAxis: true,
                    yAxis: true
                }}
                ...
            >
                <h4>This is a modal</h4>
            </ModalDialog>
        </>
    );
}

Adjust depth and matte visibility

import React from "react";
import ModalDialog from 'funda-ui/ModalDialog';
 
export default () => {
    return (
        <>
            <ModalDialog
                ...
                maskOpacity={0.001} // optional opacity
                depth={1040}
                ...
            >
                <h4>This is a modal</h4>
            </ModalDialog>
        </>
    );
}

API

Modal Dialog

import ModalDialog from 'funda-ui/ModalDialog';
PropertyTypeDefaultDescriptionRequired
refReact.ForwardedRef-It exposes the following methods of the component:
  1. ref.current.open()
  2. ref.current.close()
-
modalContentClassNamestring-The extended class name of content wrapper-
modalHeaderClassNamestring-The extended class name of header-
modalTitleClassNamestring-The extended class name of title-
modalBodyClassNamestring-The extended class name of content area-
modalFooterClassNamestring-The extended class name of footer area-
modalFooterExpandedContentClassNamestring-The extended class name of footer content area-
lockBodyScrollbooleanfalseEnables body scroll locking (for iOS Mobile and Tablet, Android, desktop Safari/Chrome/Firefox) without breaking scrolling of a target element.-
draggablebooleanfalsePop-ups that can be dragged-
draggedPreventOutsideScreenJSON Object-Prevent dragged item to be dragged outside of screen. You can set the vertical or horizontal direction. such as {xAxis: true, yAxis: true}
It is valid when draggable is "true"
-
depthnumber1055Set the depth value of the control to control the display of the pop-up layer appear above. Please set it when multiple controls are used at the same time.-
showbooleanfalseWhether the modal dialog is visible or not, you can use it with the autoClose property at the same time
autoClosenumber | booleanfalseSpecify auto-close time. This function is not enabled when this value is false. If the value is 2000, it will automatically close after 2 seconds.-
headingReactNode-Set a window title-
footerExpandedContentReactNode-Set footer content expanded-
maskDisabledbooleanfalseDisable mask-
maskOpacitystring | number-The mask opacity. The value is in the range 0.0 to 1.0. Do not want the user to see but also do not want to disable, use 0.001-
maxWidthnumber | string | functionfalseCustom modal max-width whick need a unit string. Such as: 500px or () => window.innerWidth >= 768 ? window.innerWidth - 100 + 'px' : undefined-
minHeightnumber | string | functionfalseCustom modal max-height whick need a unit string. Such as: auto or () => window.innerHeight - 150 + 'px'-
closeOnlyBtnbooleanfalseDisable mask to close the window-
closeDisabledbooleanfalseDisable the close button & mask.-
triggerClassNamestring-Specify a class for your trigger-
triggerContentReactNode-Set a piece of text or HTML code for the trigger-
closeBtnClassNamestring-Specify a class for close button-
closeBtnLabelstring | ReactNode-Set a piece of text or HTML code for the close button-
submitBtnClassNamestring-Specify a class for submit button-
submitBtnLabelstring | ReactNode-Set a piece of text or HTML code for the submit button-
fullscreenbooleanfalseEnable fullscreen modal.-
enableVideobooleanfalseAdapt the video to the window. For example, the content of the component can be written as: <iframe width="560" height="315" src="https://www.xxx.com"></iframe>
or
<video playsInline controls poster="/assets/videos/480x270/demo.jpg" src="/assets/videos/480x270/demo.mp4"></video>
-
data
You could use key (opens in a new tab) instead of it
any-Incoming data, you can set the third parameter of onSubmit.
Changes in the data value will cause the component to re-render. It will be used when the value or content does not change when switching routes and needs to re-render the component or get the request.
-
onLoadfunction-Call a function when the modal is rendered. It returns two callback values.
  1. The first is the function of open(Function)
  2. The second is the function of close (Function)
.
-
onOpenfunction-Call a function when the modal is opened. It returns two callback values, one is the trigger object and the other is the closing event (Function).-
onClosefunction-Call a function when the modal is closed. It returns a callback value which is the trigger object.-
onSubmitfunction-Call a function when the modal is submitted. It returns three callback values.
  1. The first is the trigger object
  2. The second is the closing event (Function)
  3. The third is a string passed by the data attribute
-