Skip to content

Commit

Permalink
Make non-Ember-component <foo-bar> work
Browse files Browse the repository at this point in the history
As of the previous commit, any use of `<foo-bar>` was assumed to be an
Ember Glimmer Component. This breaks code that was using dasherized
names either to refer to web components or just to produce regular HTML
elements. We believe that both of these are done in practice.

This commit allows `<foo-bar>` to be treated the same as `<div>` in all
currently implemented contexts.
  • Loading branch information
Godhuda committed Aug 12, 2015
1 parent 715aa2b commit 974493f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 22 deletions.
31 changes: 26 additions & 5 deletions packages/ember-htmlbars/lib/hooks/component.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import ComponentNodeManager from 'ember-htmlbars/node-managers/component-node-manager';
import buildComponentTemplate, { buildHTMLTemplate } from 'ember-views/system/build-component-template';
import lookupComponent from 'ember-htmlbars/utils/lookup-component';
import Ember from 'ember-metal/core';

export default function componentHook(renderNode, env, scope, _tagName, params, attrs, templates, visitor) {
var state = renderNode.state;
Expand Down Expand Up @@ -40,9 +42,9 @@ export default function componentHook(renderNode, env, scope, _tagName, params,
// <div> are defined by the compiled template, and we need to emulate
// those semantics.

let component = env.view;
let isInvokedWithAngles = component && component._isAngleBracket;
let isInvokedWithCurlies = component && !component._isAngleBracket;
let currentComponent = env.view;
let isInvokedWithAngles = currentComponent && currentComponent._isAngleBracket;
let isInvokedWithCurlies = currentComponent && !currentComponent._isAngleBracket;

// <div> at the top level of a <foo-bar> invocation
let isComponentHTMLElement = isAngleBracket && !isDasherized && isInvokedWithAngles;
Expand All @@ -53,9 +55,25 @@ export default function componentHook(renderNode, env, scope, _tagName, params,
// <div> at the top level of a {{foo-bar}} invocation
let isNormalHTMLElement = isAngleBracket && !isDasherized && isInvokedWithCurlies;

let component, layout;
if (isDasherized || !isAngleBracket) {
let result = lookupComponent(env.container, tagName);
component = result.component;
layout = result.layout;

if (isAngleBracket && isDasherized && !component && !layout) {
isComponentHTMLElement = true;
} else {
Ember.assert(`HTMLBars error: Could not find component named "${tagName}" (no component or template with that name was found)`, !!(component || layout));
}
}

if (isComponentIdentityElement || isComponentHTMLElement) {
// Inside the layout for <foo-bar> invoked with angles, this is the top-level element
// for the component. It can either be `<foo-bar>` (the "identity element") or any
// normal HTML element (non-dasherized).
let templateOptions = {
component,
component: currentComponent,
tagName,
isAngleBracket: true,
isComponentElement: true,
Expand All @@ -71,7 +89,8 @@ export default function componentHook(renderNode, env, scope, _tagName, params,
let block = buildHTMLTemplate(tagName, attrs, { templates, scope });
block(env, [], undefined, renderNode, scope, visitor);
} else {
// "No special semantics" aka we are invoking a component
// Invoking a component from the outside (either via <foo-bar> angle brackets
// or {{foo-bar}} legacy curlies).

var manager = ComponentNodeManager.create(renderNode, env, {
tagName,
Expand All @@ -81,6 +100,8 @@ export default function componentHook(renderNode, env, scope, _tagName, params,
templates,
isAngleBracket,
isTopLevel,
component,
layout,
parentScope: scope
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Ember from 'ember-metal/core';
import assign from 'ember-metal/assign';
import buildComponentTemplate from 'ember-views/system/build-component-template';
import lookupComponent from 'ember-htmlbars/utils/lookup-component';
import getCellOrValue from 'ember-htmlbars/hooks/get-cell-or-value';
import { get } from 'ember-metal/property_get';
import { set } from 'ember-metal/property_set';
Expand Down Expand Up @@ -38,18 +37,12 @@ ComponentNodeManager.create = function(renderNode, env, options) {
parentView,
parentScope,
isAngleBracket,
component,
layout,
templates } = options;

attrs = attrs || {};

// Try to find the Component class and/or template for this component name in
// the container.
let { component, layout } = lookupComponent(env.container, tagName);

Ember.assert('HTMLBars error: Could not find component named "' + tagName + '" (no component or template with that name was found)', function() {
return component || layout;
});

component = component || (isAngleBracket ? GlimmerComponent : LegacyEmberComponent);

let createOptions = { parentView };
Expand Down
16 changes: 8 additions & 8 deletions packages/ember-htmlbars/tests/hooks/component_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { runAppend, runDestroy } from 'ember-runtime/tests/utils';
var view, registry, container;

if (isEnabled('ember-htmlbars-component-generation')) {
QUnit.module('ember-htmlbars: component hook', {
QUnit.module('ember-htmlbars: dasherized components that are not in the container ("web components")', {
setup() {
registry = new Registry();
container = registry.container();
Expand All @@ -24,8 +24,8 @@ if (isEnabled('ember-htmlbars-component-generation')) {
}
});

QUnit.test('component is looked up from the container', function() {
registry.register('template:components/foo-bar', compile('<foo-bar>yippie!</foo-bar>'));
QUnit.test('non-component dasherized elements can be used as top-level elements', function() {
registry.register('template:components/foo-bar', compile('<baz-bat>yippie!</baz-bat>'));

view = EmberView.create({
container: container,
Expand All @@ -34,17 +34,17 @@ if (isEnabled('ember-htmlbars-component-generation')) {

runAppend(view);

equal(view.$().text(), 'yippie!', 'component was looked up and rendered');
equal(view.$('baz-bat').length, 1, 'regular element fallback occurred');
});

QUnit.test('asserts if component is not found', function() {
QUnit.test('falls back to web component when invoked with angles', function() {
view = EmberView.create({
container: container,
template: compile('<foo-bar />')
});

expectAssertion(function() {
runAppend(view);
}, /Could not find component named "foo-bar" \(no component or template with that name was found\)/);
runAppend(view);

equal(view.$('foo-bar').length, 1, 'regular element fallback occurred');
});
}

0 comments on commit 974493f

Please sign in to comment.