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
442 views
in Technique[技术] by (71.8m points)

jquery - Rendering a React component inside a Bootstrap popover

I have a set of images that have popovers using the bootstrap popover ui component in the content attribute/parameter i would like to add the ReactJS MusicList Component but I couldn't figure out the syntax or whether it's possible or not.

var MusicList = React.createClass({
    render : function(){
        return(<ul><li>Here</li></ul>);
    }
});

var PopoverImage = React.createClass({
    componentDidMount:function(){

        $("#"+this.getDOMNode().id).attr('data-component','<span>here</span>');
        $("#"+this.getDOMNode().id).popover({
            html:true,
            content: 
            });
    },

    render:function(){
        return(
            <img href="#" id={this.props.friend.uid+'_popover'} data-html={true} className="smallImage" src={this.props.friend.pic_small} rel="popover" data-original-title={this.props.friend.name} />

                );
    }
});
See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

Bootstrap doesn't make it easy to render a dynamic component within a popover. If the popover you want to present is static, you can simply use React's renderComponentToString which takes a component and returns a string of HTML through a callback:

var html = React.renderComponentToString(<MusicList />);
$(this.getDOMNode()).popover({
    html: true,
    content: html
});

However, if your component has any interactivity, that strategy won't work because React never has a chance to attach event handlers (or run any of your custom lifecycle methods). Indeed, Bootstrap doesn't provide the proper hooks to make your popover content dynamic.


That said, it's possible to make this work by patching Bootstrap. I've created a live demo that has dynamic popover content:

popover demo screenshot
http://jsfiddle.net/spicyj/q6hj7/

Note that the current time is rendered within the popover by a React component that updates every second.


How was this popover created?

I patched Bootstrap popover's setContent method to take a React component in addition to an HTML or text string. Instead of using jQuery's html or text methods, I use React.renderComponent:

// Patch Bootstrap popover to take a React component instead of a
// plain HTML string
$.extend($.fn.popover.Constructor.DEFAULTS, {react: false});
var oldSetContent = $.fn.popover.Constructor.prototype.setContent;
$.fn.popover.Constructor.prototype.setContent = function() {
    if (!this.options.react) {
        return oldSetContent.call(this);
    }

    var $tip = this.tip();
    var title = this.getTitle();
    var content = this.getContent();

    $tip.removeClass('fade top bottom left right in');

    // If we've already rendered, there's no need to render again
    if (!$tip.find('.popover-content').html()) {
        // Render title, if any
        var $title = $tip.find('.popover-title');
        if (title) {
            React.renderComponent(title, $title[0]);
        } else {
            $title.hide();
        }

        React.renderComponent(content,  $tip.find('.popover-content')[0]);
    }
};

Now it's possible for you to write

$(this.getDOMNode()).popover({
    react: true,
    content: <MusicList />
});

in your componentDidMount method and have it render properly. If you look in the linked JSFiddle, you'll see a general-purpose <BsPopover /> wrapper I made that takes care of all the Bootstrap calls for you, including properly cleaning up the popover components once the wrapper component is removed from the DOM.


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

...