@harianus wrote:
In our codebase we use handlebars out of an API so people can change the content of the handlebars. We also use these handlebars to change the text of
meta
-tags, because the texts are depending on the user of the platform. For example we want to sayRobert Jackson's page with his 5 products
. The handlebars in the API will return something like{{user.name}}'s page with his {{products.length}} products
(simplified for now).How so solve this type of problem in Ember?
What I created now is a big helper function which worked in Ember.js 3.0.0 but does not anymore in Ember 3.1.3.
import { getOwner, setOwner } from '@ember/application'; import Component from '@ember/component'; import { inject as service } from '@ember/service'; import Helper from '@ember/component/helper'; import Ember from 'ember'; const { HTMLBars: { compile } } = Ember; // Here we store the keys with the corresponding content-element output const stored = {}; // In Ember you can only render templates in a real component, so we do that here export default Helper.extend({ store: service(), createDomElement(key, format, template, properties) { // The following logic create a real DOM element const owner = getOwner(this); const component = Component.create({ classNames: 'hide', layout: compile(template), renderer: owner.lookup('renderer:-dom') }); setOwner(component, owner); component.setProperties(properties); // We wait for the component to render and than grab the innerHTML from it component.on('didRender', () => { // We add the result in the global `stored` object const html = component.element.innerHTML; stored[key] = html.replace(/\s\s+/g, ' '); component.destroy(); // Ember helpers don't support Promises, so we recompute the helper which // will detect the element in the global `stored` object and returns that one. this.recompute(); }); // Here we append it to the body component.append(); }, // The compute function is the function Ember runs automatically compute(params, hash) { const key = hash.key; const format = hash.format; const offer = hash.offer; if (!offer) return; // We check if the key is already stored const storedKey = stored[key]; if (storedKey) { stored[key] = null return storedKey; } // Here we get our template (content-element) with a certain key const template = this.store.peekAll('content-element').filterBy('key', key).get('firstObject.value'); if (!template) return; this.createDomElement(key, format, template, { offer, product: offer.get('product'), project: offer.get('project') }); } });
We want to use this as a attribute of a link:
<a class="button" href={{social-url format=facebookUrl key='share_message.facebook' offer=offer}} {{action 'sendEvent' preventDefault=false}}>{{t 'share_facebook.open'}}</a>
And we want to use this in the body of our page:
{{{social-url key='meta.title' project=offer.product.project product=offer.product offer=offer}}}
And in our meta tags:
<meta name="twitter:description" content={{social-url key='meta.description' project=model.project product=model.offer.product offer=model.offer}}>
There error I get when running our current code in Ember.js 3.1.3:
Uncaught TypeError: Cannot read property 'fullName' of undefined at new RootComponentDefinition (vendor.js:44666) at InteractiveRenderer.appendTo (vendor.js:44883) at Class.exports.default._emberMetal.Mixin.create._Mixin$create.appendTo (vendor.js:70569) at Class.exports.default._emberMetal.Mixin.create._Mixin$create.append (vendor.js:70573) at Class.createDomElement (frontend.js:3976) at Class.compute (frontend.js:4023) at ClassBasedHelperReference.compute (vendor.js:40727) at ClassBasedHelperReference.value (vendor.js:40382) at Object.evaluate (vendor.js:29592) at AppendOpcodes.evaluate (vendor.js:28822) RootComponentDefinition @ vendor.js:44666 appendTo @ vendor.js:44883 exports.default._emberMetal.Mixin.create._Mixin$create.appendTo @ vendor.js:70569 exports.default._emberMetal.Mixin.create._Mixin$create.append @ vendor.js:70573 createDomElement @ frontend.js:3976 compute @ frontend.js:4023 compute @ vendor.js:40727 value @ vendor.js:40382 (anonymous) @ vendor.js:29592 ...
Posts: 1
Participants: 1