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)
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.
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.
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');
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With