简体   繁体   中英

React + Semantic-UI: Using Forms inside UI MODAL

In the plain old Semantic-UI WITHOUT React, I have been able to put a form inside a Modal without a problem at all.

With the Semantic-UI + React version, I am able to display the form inside the modal, but it doesn't work the way I would expect it to.

For example, after the modal shows and the form inside the modal also is displayed. If I start inputting in the input field, I would get this error displayed:

Error: Invariant Violation: findComponentRoot(..., .1.1.1.0.4.0.0.1): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a <tbody> when using tables, nesting tags like <form>, <p>, or <a>, or using non-SVG elements in an <svg> parent. Try inspecting the child nodes of the element with React ID ``.

And due to this error, the other react code that I use the input for do not work as expected.

This is the most simple version of the code that demonstrates the problem:

ConfirmEdit = React.createClass({

    render(){
        return (
            <div className="ui modal editform">
                <form className="ui form">
                    <div className="field">
                        <label>Name</label>
                        <input name="name" type="text" placeholder="Name">
                        </input>
                    </div>
                </form>
            </div>
        );
    }
});

Inside the component where i add the above the component I made sure to trigger it:

$('.ui.modal.editform').modal('show');

As mentioned above. It displays fine, but it doesn't work fine due to the Invariant Violation.

How do I work around this and make it work?

You want to initialize the modal in componentDidMount with the option detachable = false.

$('.ui.modal').modal({detachable: false});

This will prevent the modal being moved inside a global dimmer object, and the DOM will still be owned and managed by React. Other options are documented here .

I created an example JSFiddle for you to test with.

Ok...I wish I had thought of this earlier....

I decided to analyse the DOM and directly manipulate the DOM for the solution.

I had tried to look for other more 'graceful' less hack-y solution but things just weren't working out. I tried Material-UI's modal to integrate with Semantic-UI forms but found that it doesn't scroll if the content of the modal is long like a form etc......

I had also tried to rely on Semantic-UI's API (the available settings etc.) but they all have some kind of negative side effects.

So here is what I did to find the solution. I looked at the HTML produced when the MODAL displays and looked at its position in the DOM.

As it turns out, when a dimmer is active, Semantic-UI displays a div with this class for the dimmer

ui dimmer modals page transition visible active

I found this div to be a sibling and not a child of another div with a class of

ui fluid container pushable

which contains all my other contents.

So what I did was every time I trigger my modal, I immediately call the code to make the modal a child of that container for my other content... This way my modal does not get covered by the dimmer.

showModal: function() {
    $('.ui.modal.editform').modal('show');
    //$('.ui.dimmer.modals').dimmer('hide');
    //$('.ui.dimmer.modals').after('.pusher');
    // $('.ui.dimmer.modals').appendTo('#render-target');
    $('.ui.dimmer.modals').appendTo('.ui.fluid.container.pushable');
}

To summarize: 1.) With my experience of displaying a form inside a modal using Semantic-UI with React, if you don't set the detachable property of the UI MODAL of Semantic-UI, it errors with the Invariant Violation etc. The solution is to set detachable to false.

2.) After that, you might encounter the problem of the dimmer of the modal covering the modal and the form and therefore it not only looks bad, you also can't click into the input fields etc... The solution for that, atleast in my case, was to manipulate the dom with jQuery and fix whatever Semantic-UI forgot to do automatically.

I hope that helps someone in the future....have been stuck on this for 3 days now....

I don't know if this is the best solution....but it did work.... Let me know if you have any better solution......

Ok...I found an even better answer.

The first answer I gave above was to move the dimmer to the same parent as the modal when that modal can be in any container that is LOWER in the hierarchy.

By doing this, the modal and the form in the modal are no longer covered by the dimmer.

The problem now (atleast in my case) was that the dimmer was only covering a certain portion of the window and not the ENTIRE window which is what it should be doing. In this case, it didn't matter if you tried to set the css height to 100%...as it probably is already 100% but the parent container only goes up to that point and therefore the dimmer as well.

So this is the better solution I have found.

I have found that if you declare the modal higher in the hierarchy, in my case I declared it at the topmost container BEFORE the target container.

This is the target container:

<div id="render-target"></div>

And this is to tell react to render to that container:

React.render(<App />, document.getElementById("render-target"));

The topmost div container inside is where I declared the UI MODAL with the setting detachable:false ...

Now when I trigger the UI MODAL to display, I then use jQuery to move the modal to a even higher div container, which in this case is the target container:

$('.ui.modal.editform').appendTo('#render-target');

By doing this, the dimmer is behind the modal and form but it also covers the whole window entirely and in a dynamic way. Therefore if you have a long table with a lot of entries and the whole document is very long, the dimmer will still cover it in its entirety without you have to make any more manual adjustments.

Set detachable: false is not a good idea in my experience, because modal('show') usually also create a Himmer in your page, it will encounter z-index problem.

I make a react-semanticui-modal component to solve this problem, use this , make you use semantic modal in your react project freely.

Use context in modal settings. That worked for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM