Domanda

Ho una serie di immagini con popover che utilizzano il componente bootstrap popover ui nell'attributo/parametro del contenuto. Vorrei aggiungere il componente ReactJS MusicList ma non sono riuscito a capire la sintassi o se sia possibile o meno.

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

                );
    }
});
È stato utile?

Soluzione

Bootstrap non semplifica il rendering di un componente dinamico all'interno di un popover.Se il popover che vuoi presentare è statico, puoi semplicemente usare quello di React renderComponentToString che prende un componente e restituisce una stringa HTML tramite un callback:

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

Tuttavia, se il tuo componente ha interattività, quella strategia non funzionerà perché React non ha mai la possibilità di collegare gestori di eventi (o eseguire nessuno dei tuoi metodi personalizzati del ciclo di vita).In effetti, Bootstrap non fornisce gli hook adeguati per rendere dinamico il contenuto popover.


Detto questo, è possibile farlo funzionare applicando una patch a Bootstrap.Ho creato una demo live con contenuti popover dinamici:

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

Tieni presente che l'ora corrente viene visualizzata all'interno del popover da un componente React che si aggiorna ogni secondo.


Come è stato creato questo popover?

Ho patchato Popover di Bootstrap setContent metodo per prendere un componente React oltre a una stringa HTML o di testo.Invece di usare jQuery html O text metodi che utilizzo 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]);
    }
};

Ora è possibile per te scrivere

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

nel tuo componentDidMount metodo e renderlo correttamente.Se guardi nel JSFiddle collegato, vedrai un file general-scopo <BsPopover /> wrapper che ho creato che si occupa di tutte le chiamate Bootstrap per te, inclusa la corretta pulizia dei componenti popover una volta rimosso il componente wrapper dal DOM.

Altri suggerimenti

C'è una nuova biblioteca chiamata react-bootstrap che è in fase di sviluppo rapido.

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

Se si include questo modulo è possibile rendere la propria componente del proprio componente che è possibile salvare in una variabile e quindi utilizzare nella funzione di rendering.

Il loro esempio:

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.Render (positionerinstance, mountnode);

Il mio codice:

SHOWMOREDETAILS: funzione (OBJ, COLONNS) {

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

},
.

Dopo aver pubblicato questa risposta e avendo testato e ha funzionato un po 'con questo lavoro, mi rendo conto che non è ottimale.

Menu Dropdown Bootstrap si chiude non appena l'utente ha interagito con esso. Questo potrebbe non essere il comportamento desiderato (nel mio caso, sto inserendo un datepicker e l'utente non può cambiare mese senza dover riaprire il menu per scegliere la nuova data).


.

Ho avuto lo stesso problema e ho inventato una soluzione facile e alternativa.

Non volevo usare React-bootstrap (altre parti della mia app non sono reattificate e usano Bootstrap, quindi non voglio avere due librerie facendo la stessa cosa).

Il componente a discesa Fornito dalla scatola tramite Bootstrap offre quasi le stesse funzionalità del popolover, tranne che è molto più flessibile. Questo è il Dropdown standard 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>
.

Ecco il minimo che devi farlo funzionare senza romperlo e puoi includere qualsiasi elemento reagire all'interno di esso:

<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>
.

Tutto quello che devi tenere è (i) la classe "Dropdown" sul div wrapper, (ii) L'attributo di interruzione dati "Dropdown" sul trigger (è possibile modificare il trigger su qualsiasi elemento HTML che si desidera) e (iii) il menu a discesa Classe "sul menu a discesa (puoi anche cambiarlo su qualsiasi elemento HTML desiderato e non è necessario attaccare l'elemento" UL "proposto da Bootstrap).

Si perde alcune funzionalità rispetto al Popover (non è possibile definire le tue transizioni, non puoi visualizzarle in cima, sinistra o destra, ma solo sotto - è un ascensore) ma ottieni il controllo totale sul contenuto del tuo dropdown / aofover.

Un altro modo per risolvere questo per includere il componente React che si desidera essere il contenuto di Popoover nella funzione di rendering del componente contenente il popover (cioè "la pagina") ma metterlo all'interno di un div con stile "display: nessuno;"Quindi non viene visualizzato e prende spazio, anche dargli un ID, ad es.'PopoverContent'.Quindi, quando inizializza il contenuto del set di Popoover: Document.getElementByID ("POTOVERContent").In Bootstrap 4 almeno, ci vuole un elemento come contenuto.

Non è necessario modificare il codice bootstrap in questo modo, facilitare la manutenzione / aggiornamenti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top