Appending/rendering Ember component with non-ember library


#1

We use FullCalendar, a non-Ember plugin for displaying a calendar with events on it (think of meeting on the Outlook calendar). The UI of these events can be customized using a callback which passes the event as a jQuery object.

Is it possible to inject an Ember component into these events?

Ideally I’d like to do something like this

$element.append(MyComponent.create(options).getHtml());

but unfortunately there doesn’t seem to be any way to get the HTML (or DOM) for a component that doesn’t already exist on the DOM.

I also tried this:

Ember.getOwner(this)
  .factoryFor('component:my-component')
  .create(options)
  .appendTo($element);

but that causes Ember to crash with Illegal Invocation: elMatches.call(el, selector), apparently because $element doesn’t exist on the DOM yet.

Another option I’ve seen online is to do something like

// Template
<div style="display: none">
  <div id='myComponent'>{{my-component}}</div>
</div>

//component.js
const myComponentDom = this.$('#myComponent').detach();
$element.append(myComponentDom);

But then there is no way to customize the component with the options, meaning I’d have to use jQuery to manually edit the component, at which point I might as well just hard-code the HTML in the JS file.

Does anyone know how to do this?


#2

There is an ember-fullcalendar addon that would allow you access to the fullcalendar as an Ember component.

All the callbacks can be handled as Ember actions and allow access to the view in the action so you might be able to send those actions to another Ember component or build a custom component that delegates to the ember-fullcalendar component.

I’ve never personally done that but it at least seems feasible. Let me know if you get it to work!


#3

ember-wormhole may also help with this.


#4

I looked into ember-wormhole, but it only seems useful when you have one specific div you want to replace. I didn’t see a way to use it to replace every instance of a plain-html div with an instance of a component.

I didn’t see ember-fullcalendar before, I’ll definitely look into that for my case. However, to be useful to future googlers (who might be using a library which doesn’t have an ember- version), my general question still stands: how can I replace multiple non-Ember divs with instances of a component?


#5

For that more general case you may want to look at ember-islands.

That addon is designed for adding “islands of richness” to a server rendered page, but if you can add data- attributes to your fullcalendar divs then you may be able to inject an ember component in the way you are desiring.

Depending upon how much you need the Ember infrastructure you could also consider a Glimmer component.

If you need more help please post a gist or twiddle for what you want to accomplish. Good luck!


#6

I’m trying to render events in a custom component, such that I can add a popup element in where we will able to manipulate the dates(if required) than by an action we will able to save that event, or else the event get removed. I’m doing as follows:

        let owner = Ember.getOwner(this);
        let ComponentFactory = owner.factoryFor('component:calendar/event-view');
        let component = ComponentFactory.create();
        const el = document.createElement('div');
        component.set('targetObject', this)
        component.appendTo(el)
        Ember.$(element[0]).append(el)

But the thing is, the component getting created, but the child elements are not there. Can any boby help me in this case.

Trying: To render in a predefined component