Skip to content

Commit

Permalink
Expose custom element node via customElement arg
Browse files Browse the repository at this point in the history
  • Loading branch information
Ravenstine committed Jun 12, 2020
1 parent 31f61cc commit 2dbc982
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 6 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Ember Web Components Changelog
==============================

## v0.4.0

- Expose the custom element node via the `customElement` component arg.
- Fix misfiring log warning

## v0.3.0

- Add global default options inside `config/environment.js` under `ENV.emberCustomElements.defaultOptions`.
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The most flexible way to render parts of your Ember application using custom ele
* [Outlet Element](#outlet-element)
* [Applications](#applications)
* [Options](#options)
* [Accessing a Custom Element](#accessing-a-custom-element)
* [Notes](#notes)
* [Elements](#elements)
* [Runloop](#runloop)
Expand Down Expand Up @@ -298,6 +299,16 @@ module.exports = function(environment) {
```



### Accessing a Custom Element

The custom element node that's invoking a component is passed to that component as an argument.

For Ember components, this is an attribute called `customElement`, which becomes available once `didReceiveAttrs` is fired.

With Glimmer components, it is accessible as `this.args.customElement`.


## Notes


Expand Down
6 changes: 3 additions & 3 deletions addon/instance-initializers/ember-custom-elements.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ export function initialize(instance) {
if (!shouldEvalModule) continue;
const componentClass = instance.resolveRegistration(entityName);
const customElements = getCustomElements(componentClass);
const noCustomElements = !customElements.length;
const hasCustomElements = customElements.length;
warn(
`ember-custom-elements: Custom element expected for \`${entityName}\` but none found.`,
noCustomElements,
hasCustomElements,
{ id: 'no-custom-elements' }
);
if (noCustomElements) continue;
if (!hasCustomElements) continue;
setupCustomElementFor(instance, entityName);
}
}
Expand Down
1 change: 1 addition & 0 deletions addon/lib/custom-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export default class EmberCustomElement extends HTMLElement {
attrs,
blockContent: null
});
this.view.customElement = this;
// Track block content presence and push a DocumentFragment when content
// is no longer in the DOM due to logic in the component
blockContent.onTracked = fragment => {
Expand Down
11 changes: 9 additions & 2 deletions addon/lib/template-compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,27 @@ export function compileTemplate(componentName, attributeNames=[]) {
const baseValue = argumentIdentifiers[0];
argumentIdentifiers.length = 0;
// https://github.com/glimmerjs/glimmer-vm/blob/319f3e391c547544129e4dab0746b059b665880e/packages/%40glimmer/compiler/lib/allocate-symbols.ts#L113
for (const name of attributeNames) {
function pushArg(name, identifier) {
argumentNames.push(`@${name}`);
// https://github.com/glimmerjs/glimmer-vm/blob/319f3e391c547544129e4dab0746b059b665880e/packages/%40glimmer/compiler/lib/allocate-symbols.ts#L130
const value = JSON.parse(JSON.stringify(baseValue));
crawl(value, ({ object }) => {
if (object === 'valueName') return `attrs.${name}`;
if (object === 'valueName') return identifier;
});
argumentIdentifiers.push(value);
}
// Set args
for (const name of attributeNames)
pushArg(name, `attrs.${name}`);
// Set customElement arg
pushArg('customElement', 'customElement');
template.id = componentName;
template.block = JSON.stringify(block);
return createTemplateFactory(template);
}



/**
* Given an object and a callback, will crawl the object
* until the callback returns a truthy value, in which case
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ember-custom-elements",
"version": "0.3.0",
"version": "0.4.0",
"description": "Easily use custom elements to invoke your Ember components, routes, and applications.",
"keywords": [
"ember-addon",
Expand Down
23 changes: 23 additions & 0 deletions tests/integration/ember-custom-elements-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,29 @@ module('Integration | Component | ember-custom-elements', function(hooks) {
const bar = find('bar-component');
assert.equal(bar.shadowRoot.textContent.trim(), 'foo bar');
});

test('it can access the custom element', async function(assert) {
assert.expect(1);

@customElement('web-component', { useShadowRoot: false })
class EmberCustomElement extends klass {
constructor() {
super(...arguments);
if (!this.args) return;
const element = this.args.customElement;
assert.equal(element.tagName, 'WEB-COMPONENT', 'found the custom element');
}
didReceiveAttrs() {
const element = this.customElement;
assert.equal(element.tagName, 'WEB-COMPONENT', 'found the custom element');
}å
}

setupComponentForTest(this.owner, EmberCustomElement, hbs``, 'web-component');

await render(hbs`<web-component></web-component>`);
await settled();
});
});
}

Expand Down

0 comments on commit 2dbc982

Please sign in to comment.