web-dev-qa-db-ja.com

Reactコンポーネントをa Bootstrap popover内にレンダリングする

コンテンツ属性/パラメーターでbootstrap popover uiコンポーネントを使用してポップオーバーのある画像のセットがあります。ReactJSMusicListコンポーネントを追加したいのですが、構文やそれは可能かどうかです。

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} />

                );
    }
});
29

ブートストラップは、ポップオーバー内で動的コンポーネントをレンダリングすることを容易にしません。表示したいポップオーバーが静的である場合、コンポーネントを受け取り、コールバックを介してHTMLの文字列を返すReactのrenderComponentToStringを使用できます。

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

ただし、コンポーネントにインタラクティブ機能がある場合、Reactはイベントハンドラーをアタッチする(またはカスタムライフサイクルメソッドを実行する)ことができないため、この戦略は機能しません。)Bootstrapは、ポップオーバーコンテンツを動的にする適切なフックを提供しません。


そうは言っても、Bootstrapにパッチを当てることでこれを機能させることが可能です。動的なポップオーバーコンテンツを含むライブデモを作成しました。

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

現在時刻は、毎秒更新されるReactコンポーネントによってポップオーバー内にレンダリングされることに注意してください。


このポップオーバーはどのように作成されましたか?

私はパッチを当てました Bootstrap popoverのsetContentメソッド は、HTMLまたはテキスト文字列に加えてReactコンポーネントを受け取ります。jQueryのhtmlまたはtextメソッドを使用する代わりに、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]);
    }
};

今、あなたは書くことが可能です

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

componentDidMountメソッドで、適切にレンダリングします。リンクされたJSFiddleを見ると、私が作成した汎用の<BsPopover />ラッパーが表示され、すべてのBootstrap呼び出し(ポップオーバーの適切なクリーンアップを含む)を処理します)ラッパーコンポーネントがDOMから削除されると、コンポーネント。

39
Sophie Alpert

React-Bootstrapと呼ばれる新しいライブラリがあり、急速に開発が進んでいます。

https://react-bootstrap.github.io/components.html#popovers

このモジュールを含めると、変数に保存してレンダー関数で使用できる独自のコンポーネントをポップオーバーにすることができます。

彼らの例:

const positionerInstance = ( <ButtonToolbar> <OverlayTrigger trigger="click" placement="bottom" overlay={<Popover title="Popover bottom"><strong>Holy guacamole!</strong> Check this info.</Popover>}> <Button bsStyle="default">Click</Button> </OverlayTrigger> <OverlayTrigger trigger="hover" placement="bottom" overlay={<Popover title="Popover bottom"><strong>Holy guacamole!</strong> Check this info.</Popover>}> <Button bsStyle="default">Hover</Button> </OverlayTrigger> <OverlayTrigger trigger="focus" placement="bottom" overlay={<Popover title="Popover bottom"><strong>Holy guacamole!</strong> Check this info.</Popover>}> <Button bsStyle="default">Focus</Button> </OverlayTrigger> <OverlayTrigger trigger="click" rootClose placement="bottom" overlay={<Popover title="Popover bottom"><strong>Holy guacamole!</strong> Check this info.</Popover>}> <Button bsStyle="default">Click + rootClose</Button> </OverlayTrigger> </ButtonToolbar> );

React.render(positionerInstance、mountNode);

私のコード:

showMoreDetails:function(obj、columns){

    var popOver = (
        <Popover>
            <table>
                {
                    columns.map(col =>
                            <tr>
                                <td style={{textAlign:'right', padding:5}}>
                                    {col.label}:&nbsp;
                                </td>
                                <td style={{padding:5}}>
                                    {obj[col.key]}
                                </td>
                            </tr>
                    )
                }
            </table>
        </Popover>
    );

    return(
        <OverlayTrigger trigger='click' rootClose placement='left' overlay={popOver}>
            <div className="popover-more">more...</div>
        </OverlayTrigger>
    );

},
2
ml242

これを解決して、ポップオーバーを含むコンポーネント(つまり「ページ」)のレンダリング機能にポップオーバーコンテンツにしたい反応コンポーネントを含めるが、スタイル「display:none;」のdiv内に配置する別の方法これは表示されず、スペースも取りません。IDも指定してください。 「popOverContent」。次に、ポップオーバーセットのコンテンツを初期化するとき:document.getElementById( "popOverContent")。 bootstrap 4では少なくとも、要素をコンテンツとして受け取ります。

bootstrapコードをこのように変更する必要がないため、メンテナンス/更新が簡単になります。

0
Skill M2

この返信を投稿し、この回避策を少しテストして作業したところ、最適ではないことに気付きました。

ブートストラップドロップダウンメニューは、ユーザーが操作するとすぐに閉じます。これは望ましい動作ではない可能性があります(私の場合、日付ピッカーを挿入しており、ユーザーはメニューを再度開いて新しい日付を選択する必要がない限り、月を変更できません)。


私は同じ問題を抱えていて、簡単で代替の解決策を思いつきました。

私はreact-bootstrapを使用したくありませんでした(私のアプリの他の部分は反応しないため、ブートストラップを使用するため、2つのライブラリーで同じことをしたくありません)。

Bootstrapによってボックスから提供されるドロップダウンコンポーネントは、より柔軟であることを除いて、ポップオーバーとほぼ同じ機能を提供します。これは標準のBootstrapドロップダウンです。 :

<div class="dropdown">
  <button id="dLabel" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Dropdown trigger
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" aria-labelledby="dLabel">
    ...
  </ul>
</div>

以下は、それを壊さずに機能させるために必要な最低限のものであり、その中にReact要素を含めることができます。

<div className="dropdown">
  <button data-toggle="dropdown">
    Dropdown trigger
  </button>
  <div className="dropdown-menu">
    <myGreatReactIntervactiveComponent 
      value={this.props.value}
      onChange={this.handleChange}
      onClick={this.handleClick}
      children={this.greatChildrenForMyGreatREactInteractiveComponent}
    />
  </div>
</div>

保持する必要があるのは、(i)ラッパーdivの「ドロップダウン」クラス、(ii)トリガーのデータ切り替え属性「ドロップダウン」(トリガーを任意のHTML要素に変更できます)、および(iii)だけです。ドロップダウンの「ドロップダウンメニュー」クラス(任意のHTML要素に変更することもでき、Bootstrapによって提案された「ul」要素を貼り付ける必要はありません)。

ポップオーバーと比較していくつかの機能が失われます(独自のトランジションを定義することはできず、上、左、または右に表示することはできませんが、下にのみ-ドロップダウンです)が、ドロップダウンの内容を完全に制御できます/ popover。

0
Freddo