Рендеринг компонента React внутри всплывающего окна Bootstrap

StackOverflow https://stackoverflow.com//questions/20033522

Вопрос

У меня есть набор изображений, у которых есть всплывающие окна с использованием компонента bootstrap popover ui. в атрибуте / параметре content я хотел бы добавить компонент ReactJS MusicList, но я не смог понять синтаксис или возможно ли это или нет.

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

                );
    }
});
Это было полезно?

Решение

Bootstrap не позволяет легко отображать динамический компонент во всплывающем окне.Если всплывающее окно, которое вы хотите представить, является статическим, вы можете просто использовать React's renderComponentToString который принимает компонент и возвращает строку HTML через обратный вызов:

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

Однако, если ваш компонент обладает какой-либо интерактивностью, эта стратегия не сработает, потому что у React никогда не будет возможности подключить обработчики событий (или запустить любой из ваших пользовательских методов жизненного цикла).Действительно, Bootstrap не предоставляет надлежащих хуков, чтобы сделать ваш всплывающий контент динамичным.


Тем не менее, можно заставить это работать, исправив Bootstrap.Я создал живую демо-версию с динамическим всплывающим контентом:

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

Обратите внимание, что текущее время отображается во всплывающем окне компонентом React, который обновляется каждую секунду.


Как было создано это всплывающее окно?

Я залатал Загрузочный поповер setContent способ использовать компонент React в дополнение к HTML или текстовой строке.Вместо использования 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 /> оболочка, которую я создал, которая заботится обо всех вызовах начальной загрузки для вас, включая правильную очистку всплывающих компонентов после удаления компонента-оболочки из DOM.

Другие советы

Есть новая библиотека под названием React-bootstrap, которая претерпевает быстрое развитие.

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

Если вы включите этот модуль, у вас есть возможность сделать POSOVER свой собственный компонент, который вы можете сохранить в переменной, а затем использовать в вашей функции рендера.

Их пример:

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> );

ract.render (positionerianstance, mountnode);

Мой код:

ShowMOredetails: Функция (OBJ, столбцы) {

    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>
    );

},
.

После размещения этого ответа и проверив и проверил и немного работал с этой работой, я понимаю, что это не оптимально.

раскрывающиеся меню Bootstrap близко, как только пользователь взаимодействует с ним. Это может быть не желаемое поведение (в моем случае, я вставляю DatePicker, и пользователь не может изменить месяц без того чтобы открыть меню, чтобы выбрать новую дату).


У меня была такая же проблема, и я придумал простое и альтернативное решение.

Я не хотел использовать React-bootstrap (другие части моего приложения не реагируют и используют загрузочные данные, поэтому я не хочу иметь две библиотеки, которые делают то же самое).

Выпадающий компонент, предусмотренный из коробки с помощью 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>
.

Вот минимум, который вы должны сделать его работать, не нарушая его, и вы можете включить, какой элемент реагирования в него:

<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) Divgle атрибут атрибута «раскрывающийся» на триггере (вы можете изменить свой триггер на любой желаемый HTML-элемент) и (iii) Класс «DropDown-Menu» в раскрывающемся списке (вы также можете изменить его на любой желаемый HTML-элемент, и вам не нужно придерживаться элемента «ul», предлагаемого bootstrap).

Вы теряете несколько функций по сравнению с POPOVER (вы не можете определить свои собственные переходы, вы не можете отобразить их сверху, влево или вправо, но только ниже - это выпадает), но вы получаете полный контроль над контентом вашего выпадания / поповета.

Другой способ решить это, чтобы включить этот компонент React, который вы хотите быть содержанием поповета в функции рендеринга компонента, содержащего попуклад (т. Е. «Страница»), но поместите его внутри Div со стилем «Дисплей: нет;"Так что это не отображается и не занимает места, и дайте ему удостоверение личности, например'popovercontent'.Затем, когда вы инициализируете набор запасов: Document.GetElementByID («POPOVERContent»).В Bootstrap 4, по меньшей мере, он принимает элемент как контент.

Вам не нужно изменять код Bootstrap таким образом, что облегчает обслуживание / обновления.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top