简体   繁体   中英

Dynamically compile a HTMLBars template at runtime in Ember

I want to dynamically compile (and then render) a HTMLBars template at runtime, on the client in Ember. How can I do this?

This answer is now out of date. Please see @poohoka's answer which I've accepted above.


Building off of Kingpin2K's answer to Compile template client side in ember using HTMLbars :

For some background, it might be useful to refer back to Compiling Templates with Ember 1.10 . We'll still need to load ember-template-compiler.js . Add

  app.import('bower_components/ember/ember-template-compiler.js');

to your ember-cli-build.js .

Then you can write a Component like this:

import Ember from 'ember';

export default Ember.Component.extend({

  layout: Ember.computed(function() {
    return Ember.HTMLBars.compile(
      '{{foo-bar}} <span>' + 'hello' + '</span>'
    );
  }),

});

This solution will likely break in future relases of Ember, depending on how the Ember Template compilation process changes with the advent of Glimmer 2 .

Since Ember 2.10 is now using Glimmer, things might be a bit tricky here. In order to compile a template, you need to include ember-template-compiler.js to your application. I'd recommend using ember-browserify and ember-source .

In your controller, import the compiler as the following.

import Ember from 'ember';
import Compiler from 'npm:ember-source/dist/ember-template-compiler';

export default Ember.Controller.extend({
  compileContent() {
    const template = Compiler.compile(this.get('dynamicContent'));
    Ember.TEMPLATES[`YOUR_TEMPLATE_NAME`] = template;
  },
  // we observe content changes here
  contentDidUpdate: Ember.observer('dynamicContent', function() {
    this.compileContent();
  }),
});

As tested, your content can contain anything from Ember helpers to your custom components, even your action bindings.

eg

<ul>
  <li>{{#link-to 'index'}}Home{{/link-to}}</li>
</ul>
<div {{action 'yourCustomAction'}}>
  {{your-custom-component params=yourCustomParams model=model flag=true}}
</div>

Now, let's do the magic in your template by using {{partial}} helper.

...

{{partial 'YOUR_TEMPLATE_NAME'}}

...

This method works in Ember 2.13 without deprecation warnings, it should work in future updates. Please note that Ember.TEMPLATES is global variable and the engine seems to cache it somehow, so do not reassign new values to the existing one.

Since Ember 2.13+ (without bower by default) you need to add in your ember-cli-build.js:

app.import('vendor/ember/ember-template-compiler.js');

For Ember version prior to 2.10 you need to include it via bower (also on ember-cli-build.js)

app.import('bower_components/ember/ember-template-compiler.js');

And on the code you need to:

Ember.TEMPLATES['mycompiledcode'] = Ember.HTMLBars.compile('{{foo-bar}} <span>' + 'hello' + '</span>');

In the hbs file call:

{{partial 'mycompiledcode'}}

Or you can make a component like this:

import Ember from 'ember';

export default Ember.Component.extend({

  layout: Ember.computed(function() {
    return Ember.HTMLBars.compile(
      '{{foo-bar}} <span>' + 'hello' + '</span>'
    );
  }),

});

Based on solution of another answer https://stackoverflow.com/a/37345099/6505594

I'm currently on Ember-2.9.x and I brought in the latest handlebars with my bower.json :

"handlebars": "^4.0.0"

And then added it via my ember-cli-build.js file:

app.import('bower_components/handlebars/handlebars.js');

This has worked for my typeahead component and I don't see any reason why this won't work when upgrading to Ember-2.10 with Glimmer2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM