Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
630 views
in Technique[技术] by (71.8m points)

javascript - How do I initialize the Bootstrap 4 popover in a React application?

I can't figure out how to make popovers work, as per: https://getbootstrap.com/docs/4.0/components/popovers/.

The documentation talks about the popover support being a plugin and requiring the tooltip plugin as well, so I've modified my webpack.config.js to add those two, now it looks like this:

...
new webpack.ProvidePlugin({
  $: 'jquery',
  jQuery: 'jquery',
  'window.jQuery': 'jquery',
  Popper: ['popper.js', 'default'],
  Popover: 'exports-loader?Popover!bootstrap/js/dist/popover',
  Tooltip: "exports-loader?Tooltip!bootstrap/js/dist/tooltip",
}),
...

I haven't found any documentation about the Bootstrap plugin concept, so the above two lines for Popover and Tooltip came from a search, not sure if they're correct.

The documentation states:

Popovers are opt-in for performance reasons, so you must initialize them yourself.

But I don't understand how to do that.

The documentation shows the following code for initializing the popover:

$(function () {
  $('.example-popover').popover({
    container: 'body'
  })
})

But I don't understand what that's supposed to be doing - there's no popover() function on my element to invoke - how does this work?

Here's an example of my code that's trying to use a popover:

render(){

  ...

  <span>
    Summary info
    <button 
      type="button" className="btn btn-sm" 
      data-toggle="popover" title="Popover title" 
      data-content="The popover Content"
    >
      Show popover
    </button>        
  </span>

  ...
}

How do I make the Bootstrap V4 popover functionality work in the context of a React application? Specifically - how do I "initialize" the popover?


I'm using Typescript 2.3, React 16, Bootstrap 4 (no react-bootstrap style libraries).

Note that react-bootstrap supports only Bootstrap V3, and reactstrap is too unstable and I don't want to use it.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I had (still have, undoubtedly) a lot of missing contextual understanding when I was initially trying to get Bootstrap popovers working.

First thing is: the Bootstrap "Popover" plugin is really a JQuery plugin. I assume that's how all the Bootstrap plugins work, but I couldn't find any Bootstrap introductory documentation about this. So that explains the popover() method and where it comes from.

Below, I've outlined what is needed to make the popovers work in the context of a React / Typescript / Webpack stack.

In the following, I'm assuming you've configured Webpack as per the Bootstrap doco.

You don't need the "Popover" and "Tooltip" lines from the original question, assuming you're webpack.config.js is as per the Bootstrap doco and you have import 'bootstrap'; somewhere in your codebase.


You need to add the JQuery typings, if not already present, so that you can import $ and have the right types:

"devDependencies": {
   "@types/jquery": "3.2.15",
   ...
}

"dependencies": {
  "bootstrap": "4.0.0-beta",
  "jquery": "3.2.1",
  "popper.js": "1.11.0",
  ...
}

You have to extend the type definition of JQuery so that it knows about the Popover plugin, as per this blog article by Netanel Basal. In typings.d.ts (or wherever makes sense in your project), add the following:

// support for JQuery popover plugin from Bootstrap 4
interface JQuery {
  popover() : any;
}

Note that definition is the bare minimum you need to get popovers working from your code in a statically typed way. It needs to be extended to support passing parameters so that you can customise the popover behaviour. Or you could use the data attributes to pass these parameters, as per the Live example in the doco.

In the React component itself, the JSX to declare the popover from the question seems to work fine.

To "initialize" the popover, as per the question, you need to import the JQuery identifier and then call the popover method:

...
const $ = require('jquery'); 
...
componentDidMount(): void{
  $('[data-toggle="popover"]').popover();
}
...

The "import form" didn't work for me, so I had to require() it.

That code searches the entire HTML page for elements with data-toggle="popover", and returns a JQuery object that has the popover() method you can call (that's the whole JQuery plugin part).

Once popover() has been called on the element with the popover attributes, popovers will be automatically displayed when the element is clicked (there's no need to manage popover-specific React state).


EDIT

It's not a good idea to search the entire HTML page for all popovers as shown above. In a complicated page with multiple popovers in multiple React components, each component would end up overwriting each other's popover() options.

Here's my current solution for a re-usable React bootstrap Popover component.

Extend the Typescript typings to understand more popover options:

// support for JQuery popover plugin from Bootstrap 4
interface JQuery {
  popover(options?: PopoverOptions) : any;
}

interface PopoverOptions {
  container?: string | Element | boolean;
  content?: string | Element | Function;
  placement?: "auto" | "top" | "bottom" | "left" | "right" | Function;
  title?: string | Element | Function;
  ...
}

Create Popover.tsx like:

export interface PopoverProps {
  popoverTitle: string | Element | Function;
  popoverContent: string | Element | Function;
}

export class Popover
extends PureComponent<PopoverProps, object> {

  selfRef: HTMLSpanElement;

  componentDidMount(): void{
    $(this.selfRef).popover({
      container: this.selfRef,
      placement: "auto",
      title: this.props.popoverTitle,
      content: this.props.popoverContent,
    });
  }

  render(){
    return <span
      ref={(ref)=>{if(ref) this.selfRef = ref}} 
      data-toggle="popover"
    >
      {this.props.children}
    </span>;

  }
}

Then use the popover like:

<Popover 
  popoverTitle="The popover title"
  popoverContent="The popover content"
>
  <span>
    Click this to show popover.
  </span>
</Popover>

Beware issues related to Popover positioning with dynamic content: Bootstrap 4 - how does automatic Popover re-positioning work?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...