Skip to content

Commit

Permalink
Merge pull request #12495 from mixonic/dot-path-lookup
Browse files Browse the repository at this point in the history
[FEATURE ember-contextual-components] dot-path
  • Loading branch information
rwjblue committed Oct 19, 2015
2 parents e2643a5 + a6f0487 commit c35e15c
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 9 deletions.
16 changes: 16 additions & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,19 @@ for a detailed explanation.
* `ember-metal-ember-assign`

Add `Ember.assign` that is polyfill for `Object.assign`.

* `ember-contextual-components`

Introduce a helper that creates closures over attrs and its own path, then
allow the closed over cell to be invoked via the `{{component` helper or
any reference with a dot in the path.

For example:

```js
{{#with (hash profile=(component "user-profile")) as |userComponents|}}
{{userComponents.profile}}
{{/with}}
```

Implements RFC [#64](https://github.com/emberjs/rfcs/blob/master/text/0064-contextual-component-lookup.md)
25 changes: 20 additions & 5 deletions packages/ember-htmlbars/lib/hooks/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@ import ComponentNodeManager from 'ember-htmlbars/node-managers/component-node-ma
import buildComponentTemplate, { buildHTMLTemplate } from 'ember-views/system/build-component-template';
import lookupComponent from 'ember-htmlbars/utils/lookup-component';
import Cache from 'ember-metal/cache';
import {
CONTAINS_DASH_CACHE,
CONTAINS_DOT_CACHE
} from 'ember-htmlbars/system/lookup-helper';
import {
COMPONENT_PATH,
COMPONENT_HASH,
isComponentCell,
mergeHash,
} from 'ember-htmlbars/keywords/closure-component';

var IS_ANGLE_CACHE = new Cache(1000, function(key) {
return key.match(/^(@?)<(.*)>$/);
});

var CONTAINS_DASH = new Cache(1000, function(key) {
return key.indexOf('-') !== -1;
});

export default function componentHook(renderNode, env, scope, _tagName, params, attrs, templates, visitor) {
var state = renderNode.getState();

Expand All @@ -22,6 +28,15 @@ export default function componentHook(renderNode, env, scope, _tagName, params,
}

let tagName = _tagName;
if (CONTAINS_DOT_CACHE.get(tagName)) {
let stream = env.hooks.get(env, scope, tagName);
let componentCell = stream.value();
if (isComponentCell(componentCell)) {
tagName = componentCell[COMPONENT_PATH];
attrs = mergeHash(componentCell[COMPONENT_HASH], attrs);
}
}

let isAngleBracket = false;
let isTopLevel = false;
let isDasherized = false;
Expand All @@ -34,7 +49,7 @@ export default function componentHook(renderNode, env, scope, _tagName, params,
isTopLevel = !!angles[1];
}

if (CONTAINS_DASH.get(tagName)) {
if (CONTAINS_DASH_CACHE.get(tagName)) {
isDasherized = true;
}

Expand Down
4 changes: 4 additions & 0 deletions packages/ember-htmlbars/lib/system/lookup-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export var CONTAINS_DASH_CACHE = new Cache(1000, function(key) {
return key.indexOf('-') !== -1;
});

export var CONTAINS_DOT_CACHE = new Cache(1000, function(key) {
return key.indexOf('.') !== -1;
});

export function validateLazyHelperName(helperName, container, keywords) {
return container && !(helperName in keywords);
}
Expand Down
24 changes: 20 additions & 4 deletions packages/ember-htmlbars/lib/utils/is-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
@submodule ember-htmlbars
*/

import { CONTAINS_DASH_CACHE } from 'ember-htmlbars/system/lookup-helper';
import {
CONTAINS_DASH_CACHE,
CONTAINS_DOT_CACHE
} from 'ember-htmlbars/system/lookup-helper';
import { isComponentCell } from 'ember-htmlbars/keywords/closure-component';
import { isStream } from 'ember-metal/streams/utils';

/*
Given a path name, returns whether or not a component with that
Expand All @@ -12,7 +17,18 @@ import { CONTAINS_DASH_CACHE } from 'ember-htmlbars/system/lookup-helper';
export default function isComponent(env, scope, path) {
var container = env.container;
if (!container) { return false; }
if (!CONTAINS_DASH_CACHE.get(path)) { return false; }
return container.registry.has('component:' + path) ||
container.registry.has('template:components/' + path);
if (typeof path === 'string') {
if (CONTAINS_DOT_CACHE.get(path)) {
let stream = env.hooks.get(env, scope, path);
if (isStream(stream)) {
let cell = stream.value();
if (isComponentCell(cell)) {
return true;
}
}
}
if (!CONTAINS_DASH_CACHE.get(path)) { return false; }
return container.registry.has('component:' + path) ||
container.registry.has('template:components/' + path);
}
}
46 changes: 46 additions & 0 deletions packages/ember-htmlbars/tests/helpers/closure_component_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,4 +339,50 @@ if (isEnabled('ember-contextual-components')) {
runAppend(component);
}, `The component helper cannot be used without a valid component name. You used "not-a-component" via (component compName)`);
});

QUnit.test('renders with dot path', function() {
let expectedText = 'Hodi';
registry.register(
'template:components/-looked-up',
compile(expectedText)
);

let template = compile('{{#with (hash lookedup=(component "-looked-up")) as |object|}}{{object.lookedup}}{{/with}}');
component = Component.extend({ container, template }).create();

runAppend(component);
equal(component.$().text(), expectedText, '-looked-up component rendered');
});

QUnit.test('renders with dot path and attr', function() {
let expectedText = 'Hodi';
registry.register(
'template:components/-looked-up',
compile('{{expectedText}}')
);

let template = compile('{{#with (hash lookedup=(component "-looked-up")) as |object|}}{{object.lookedup expectedText=expectedText}}{{/with}}');
component = Component.extend({ container, template }).create({
expectedText
});

runAppend(component);
equal(component.$().text(), expectedText, '-looked-up component rendered');
});

QUnit.test('renders with dot path curried over attr', function() {
let expectedText = 'Hodi';
registry.register(
'template:components/-looked-up',
compile('{{expectedText}}')
);

let template = compile('{{#with (hash lookedup=(component "-looked-up" expectedText=expectedText)) as |object|}}{{object.lookedup}}{{/with}}');
component = Component.extend({ container, template }).create({
expectedText
});

runAppend(component);
equal(component.$().text(), expectedText, '-looked-up component rendered');
});
}

0 comments on commit c35e15c

Please sign in to comment.