furqanZafar / react-selectize

http://furqanzafar.github.io/react-selectize/
Apache License 2.0
704 stars 138 forks source link

tether feature NOT working along with Bootstrap #137

Open pgoldweic opened 7 years ago

pgoldweic commented 7 years ago

Given the following imports: import React, { PropTypes, Component } from 'react' import SimpleSelect from 'react-selectize' import '../../node_modules/react-selectize/themes/index.css'

and MyComponent render's method as follows:

return (
    <SimpleSelect placeholder="Select" onValueChange={this.change} >
        <option value="A">A</option>
        <option value="B">B</option>
    </SimpleSelect>

);

I am getting this error in my console: Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of MyComponent.

Have I missed anything regarding SimpleSelect? (I've just followed the readme instructions for using it)

pgoldweic commented 7 years ago

I've made some progress on getting it to show up without any errors (my import statement was apparently incorrect before). However, the dropdown is not displaying at all (that is, no dropdown items get displayed even though the options have been sent). The input element does accept a value and then apparently searches for matching items. However, it simply displays the matching item in the input field without ever displaying the dropdown :-(. What am I doing wrong? I am using it as follows:

    <SimpleSelect placeholder="Select" options={selectItems} tether
            onValueChange={function(option) {  
                if (option) onchange(student, option.value)}} />

Note: the component displays within a table cell. Is this use case not supported?

rafaelvanderlei commented 7 years ago

Hi, @pgoldweic . I've just started to use this component, and I guess I was facing the same issue as you are. I was missing to add the styles, as per install instructions, once I added it, the dropdown displayed correctly. Hope it works for you too.

pgoldweic commented 7 years ago

Thanks @rafaelvs for the tip, but unfortunately I have loaded the styles as explained in the instructions though :-(

rafaelvanderlei commented 7 years ago

Hmm... I see you have a import statement to the css file inside your .js file... well, I'm not loading the CSS this way. I actually downloaded the CSS file from here and then added this entry in my /public/index.html:

<link rel="stylesheet" href="%PUBLIC_URL%/css/react-selectize-2.1.0/index.min.css"/>

I did it because I intend to host the CSS file in my own server, but of course, you could also try to reference the CSS directly from the previous url, like this:

<link rel="stylesheet" href="https://npmcdn.com/react-selectize@2.1.0/dist/index.min.css"/>

If it doesn't work for you as well, then sorry.. it's the best I can do =(

pgoldweic commented 7 years ago

Thanks @rafaelvs. I'm pretty sure the problem is not that the css is not being loaded correctly for various reasons (1- my method works with create-react-app/webpack.etc. 2- my dropdown would not display at all if the css styles were not available. However what fails to display is the list of dropdownitems only). I am assuming that the problem relates to rendering within a table cell (see my first post), but it would be nice to have somebody else confirm this or offer other suggestions. Thanks!

rafaelvanderlei commented 7 years ago

If it helps confirm that the select can be displayed from inside a table cell, I've just created a new react app and got to display its items correctly.

Also, I ran the app with and without the css (please see the images below), just for you to see the issue I was facing when I wasn't loading the css correctly.

Without the css:

without the css

With the css:

with the css

pgoldweic commented 7 years ago

Once again, I guarantee the styles are loaded. Here's my picture to prove it:

image

The problem is that when I click on the components, the drop down does not show up at all.

rafaelvanderlei commented 7 years ago

Hmm, I see... have you tried to use the component outside of the table cell, in a free div, with as little css rules as possible, just to confirm the items render correctly? Maybe you have some fixed max height css rule that is not allowing the items do be displayed?

pgoldweic commented 7 years ago

Glad you asked the question: turns out that I've now created another simple app (using the same create-react-app build process) that simply displays a SimpleSelect, and again I didn't see any of the menu items in the dropdown. I had only two css import statements in my index.js file as follows:

import '../node_modules/bootstrap/dist/css/bootstrap.css'
import '../node_modules/react-selectize/themes/index.css'

Then I experimented with removing the first (that is, bootstrap!) and this time the dropdown items showed up. I'm afraid this suggests some kind of bootstrap incompatibility.... but I don't think I'd be able to leave bootstrap behind in order to use react-selectize :-(. I wonder whether any users of react-selectize are also Bootstrap users, and if so, how do they resolve this problem?

NOTE: I am using Bootstrap 4

rafaelvanderlei commented 7 years ago

Well, it just happens that I myself am using react-bootstrap@0.30.7 (with bootstrap v3.3.6 though), and I'm able to display dropdown items correctly, even inside a bootstrap table cell, as you can see in the image below:

bootstrap_table_cell_success

Anything changes if you import the css like this?

import 'bootstrap/dist/css/bootstrap.css';
import 'react-selectize/themes/index.css';

Notice that, compared to your import statements, I dropped '../node_modules/' prefix from the module path.

Edit: uploaded the image above.

pgoldweic commented 7 years ago

I tried it with the paths you suggested above, and I'm not seeing any difference at all. Note that I'm still testing on the simplest app.

rafaelvanderlei commented 7 years ago

Is it possible for you to upload your source code to a github repository? I'm not being able to reproduce your issue, as it's working ok for me, both in my current project and in a simple new app created with 'create-react-app'

pgoldweic commented 7 years ago

My test project it's actually a pretty minimal app created with create-react-app, so I can include all the source here (3 files total, including package.json). Here it goes:

File: App.js

import React, { Component } from 'react' import {SimpleSelect} from 'react-selectize'

class App extends Component {
    change = (option)=> {console.log("Selected option:" + option.value)}
    render() {
        const validValues = ["A","B","C"]
        const selectItems = validValues.map((x) => {return { value: x, label: x}} )
             return (
               <SimpleSelect placeholder="Select" options={selectItems} tether
                      onValueChange={function(option) {  
                           if (option) console.log("Selected option: " + option.value)} }
                />
      );
    }
 }
export default App;
---------------------------------
File: index.js
---------------------------------
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import 'bootstrap/dist/css/bootstrap.css'
import 'react-selectize/themes/index.css'

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
------------------------------------
File: package.json
------------------------------------

{ "name": "test-react-selectize", "version": "0.1.0", "private": true, "devDependencies": { "react-scripts": "0.8.5" }, "dependencies": { "bootstrap": "^3.3.7", "react": "^15.4.2", "react-addons-transition-group": "^15.0.0", "react-addons-shallow-compare":"^15.0.0", "react-bootstrap": "", "react-dom": "^15.4.2", "react-selectize": "", "tether":"*" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } }

rafaelvanderlei commented 7 years ago

First, just out of curiosity, I think you have a typo in your package.json: instead of react-addons-transition-group it should be react-addons-css-transition-group" but, that's not the real problem, though (and I think you have already fixed that, since otherwise it would lead to compile error).

As to what really matters... hey, I was able to reproduce your issue with the code you provided, and while experimenting, I noticed the problem is actually related to the use of the "tether" property in conflict with importing the bootstrap css. You could try this to confirm: if you remove 'tether' property (or set its value to false), the items are displayed, although not over the parent element as it would be expected to happen when using tether property. Still, if you try this code, but without importing bootstrap, it will also work (even with an absolutely positioned overlay, as expected).

It just seems like one (tether prop ) can't live with the other (bootstrap).

As to how to fix it, I can't help very much, as I don't know the internals of this component (if you remind, in my first post, I told you I've just started using this component). But at least, now react-selectize developers have more information to help understand what's really going on.

ps.: Even putting the script below, as described in install instructions, I could not get it working (I also tried, without success, loading the script that comes in '/node_modules/react-selectize/node_modules/tether/dist/jsnode_modules_tether/the tether.min.js' (to match the exact same script used in react-selectize, which I think is tether@1.4.0):

<!-- optional dependency (only required with using the tether prop) -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.1.1/js/tether.min.js" type="text/javascript" ></script>
pgoldweic commented 7 years ago

Wow! That's really a surprise and also a great find! Thanks so much for following up on this. Hopefully, as you say, it will provide enough information to the react-selectize developers that they'll be able to fix it (since, without the tether feature, I am not going to be able to use this component as this requirement is a must for my project).

rafaelvanderlei commented 7 years ago

No problem. Glad to help.

Also, maybe you should edit the title of this issue to give a better visibility of the actual problem by changing it to something like "Can't get tether feature working along with bootstrap"

howardjing commented 7 years ago

I ran into this issue as well. There are two incompatibilities that I found with bootstrap:

  1. tether property doesn't work with bootstrap3
  2. dropdown-direction: -1 property doesn't work with bootstrap 3

The issue is because DropdownMenu generates a div with className .dropdown-menu as seen here. This seems to clash with bootstrap styling which comes with styling for .dropdown-menu (see the dropdown component.

As a result, when dropdown-direction: -1 is specified, the menu doesn't actually open above the component. And when tether is specified, the dropdown menu isn't rendered at all.

To work around this, I renamed dropdown-menu to rs-dropdown-menu to see if that would fix things, and it worked. However, I don't think it's a great solution as it breaks backwards compatibility. See this commit for details.

Antho2407 commented 7 years ago

Any updates on this problem ?

belkosyak commented 7 years ago

Maybe will be useful for someone as "temporary" solution: When I wanted to use tether and dropdown-direction: -1 with the Bootstrap 3.3.6, I ended up with adding custom className (lets say custom-class) to my component:

.custom-class.dropdown-menu {
  top: initial;
  left: initial;
  display: initial;
  float: initial;
  padding: initial;
  margin: initial;
  font-size: initial;
  border-radius: initial;
  box-shadow: initial;
}

and everything started to work :)

Gribbs commented 7 years ago

Same problem when using Bootstrap 4. installing react-selectize-bs fixed the issue for me! Thanks

hwaterke commented 7 years ago

Any news on this? Could'nt we just merge the fix of @howardjing into master? I fear react-selectize-bs will quickly be outdated...

I think prefixing CSS classes with for example rs- is a good idea to avoid any other name clashes in the future.