Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootstrap Popovers with ember.js template

I'm trying to use Bootstrap Popover with EmberJS, so that the content of the popover will be a ember/handlebars template (with binding etc). How can this be done? (Ember 1.0.0-rc2)

like image 649
Ori Shavit Avatar asked Apr 14 '13 23:04

Ori Shavit


4 Answers

Here is a working example for an ember bootstrap popover (see http://jsfiddle.net/72fSd/):

App.Popover = Ember.View.extend({
        parentSelector: '',
        contentSelector: '',
        didInsertElement: function () {
            var self = this;
            $(self.parentSelector).popover({
                html: true,
                content: function() {
                    var $content = $(self.contentSelector);
                    return $content.html();
                }
            });
        }

Instantiate the view:

{{view App.Popover templateName="my-popover-content" parentSelector=".popoverButton" contentSelector="#popovercontent"}}

Here, parentSelector might e.g. select a button. Make sure you have a div container with id #popovercontent in your my-popover-content template in order for the contentSelector to work. Of course you need to load the template prior to initialization of the view.

Two-way binding should work with that solution.

like image 163
Robert Avatar answered Oct 22 '22 17:10

Robert


I took Terry's answer a bit further and think I've come up with a simple, general solution to this problem.

I created a bootstrap-popover component like so:

App.BootstrapPopoverComponent = Ember.Component.extend({
  tagName: 'div',      //whatever default you want... div is default anyway here
  classNames: '',      //whatever default you want
  placement: 'bottom', //whatever default you want
  didInsertElement: function () {
    var component = this,
        contents = this.$('.popoverJs');
    component.$().popover({
      animation: false,
      placement: component.get('placement'),
      html: true,
      content: contents
    }).on('show.bs.popover', function () {
      contents.removeClass('hide');
    });
  },
  willDestroyElement: function () {
    this.$().popover('destroy');
  }
});

Here is the associated template:

<script type="text/x-handlebars" id="components/bootstrap-popover">
  {{title}}
  <div class="popoverJs hide">
    {{yield}}
  </div>
</script>

Note the use of the "hide" class to hide the yielded contents initially. This class is simply "display: none". Without this, things won't work quite how you'd hope.

Once you have that, you can do simply do something like this whenever you want a popover:

  {{#bootstrap-popover title="My Fancy Popover" tagName="button"}}
    <ul>
      <li>my</li>
      <li>awesome</li>
      <li>popover</li>
      <li>contents</li>
      <li>example</li>
    </ul>
  {{/bootstrap-popover}}

The contents should be able to be whatever you want -- any arbitrary HTML, rendering a component or partial, etc.. Naturally, you can specify other tagNames, classNames, title, placement, etc. as you see fit.

I hope this solution helps.

like image 42
eeggers Avatar answered Oct 22 '22 17:10

eeggers


ex if you want to popup a image do something like this in you view

imgTag: '<img src="smiley.gif" alt="Smiley face" height="42" width="42">',

didInsertElement: function () {
    var self = this;
    Ember.run.schedule('actions', this, function () {
        self.$().popover({
            title: 'Smile!!!',
            html: true,
            content: self.get('imgTag'),
            placement: 'bottom',
            trigger: 'hover'
        });
    });
},

willDestroyElement: function () {
    this.$().popover('destroy');
}
like image 45
pjlammertyn Avatar answered Oct 22 '22 17:10

pjlammertyn


I ran into this problem as well and had the same problem Robert mentioned above where the acceptable solution simply doesn't scale well to more complicated scenarios.

I ran into a very elegant fix, but I'm not sure how future-friendly it is. I'm taking advantage of the function renderToBuffer - see below:

//make your popover view to be created later
App.PopoverView = Ember.View.extend({
  templateName : 'name-of-your-template-with-content'
});

//then you make your link that will trigger the popover
App.PopoverLinkView = Ember.View.extend({

  tagName : 'a',

  didInsertElement : function(){

  var that = this;

  this.$().popover({
    'html' : true,
    'content' : function(el){
    var detailView = App.PopoverView.create();
    var html = detailView.renderToBuffer().buffer;
    return html;
    }
  });

  }

});

The advantage here is that you can pass in a model and make things dynamic. Haven't tested it thoroughly, but wanted to get this out there to potentially help others.

like image 37
gcoladarci Avatar answered Oct 22 '22 19:10

gcoladarci