Permalink
Browse files

emberscreencasts 194: angle-bracket-components

go to the /angle-bracket-components route and click through the examples linked in order

make sure to read the notes at the bottom of each template
  • Loading branch information...
jeffreybiles committed Jan 14, 2019
1 parent 16d94b6 commit 824ec2e0bd16da1c58261562ee94a3e222251407
Showing with 495 additions and 8 deletions.
  1. +2 −0 package.json
  2. +11 −1 src/router.js
  3. +26 −0 src/ui/components/cool-paragraph/component-test.js
  4. +5 −0 src/ui/components/cool-paragraph/component.js
  5. +1 −0 src/ui/components/cool-paragraph/template.hbs
  6. +26 −0 src/ui/components/paragraph/component-test.js
  7. +4 −0 src/ui/components/paragraph/component.js
  8. +1 −0 src/ui/components/paragraph/template.hbs
  9. +26 −0 src/ui/components/positional-arguments-paragraph/component-test.js
  10. +5 −0 src/ui/components/positional-arguments-paragraph/component.js
  11. +1 −0 src/ui/components/positional-arguments-paragraph/template.hbs
  12. +26 −0 src/ui/components/tagless-cool-paragraph/component-test.js
  13. +7 −0 src/ui/components/tagless-cool-paragraph/component.js
  14. +3 −0 src/ui/components/tagless-cool-paragraph/template.hbs
  15. +26 −0 src/ui/components/text-changer/component-test.js
  16. +4 −0 src/ui/components/text-changer/component.js
  17. +1 −0 src/ui/components/text-changer/template.hbs
  18. +11 −0 src/ui/routes/angle-bracket-components/basics/route-test.js
  19. +4 −0 src/ui/routes/angle-bracket-components/basics/route.js
  20. +9 −0 src/ui/routes/angle-bracket-components/basics/template.hbs
  21. +12 −0 src/ui/routes/angle-bracket-components/block-component/controller-test.js
  22. +12 −0 src/ui/routes/angle-bracket-components/block-component/controller.js
  23. +11 −0 src/ui/routes/angle-bracket-components/block-component/route-test.js
  24. +4 −0 src/ui/routes/angle-bracket-components/block-component/route.js
  25. +31 −0 src/ui/routes/angle-bracket-components/block-component/template.hbs
  26. +11 −0 src/ui/routes/angle-bracket-components/html-attributes/route-test.js
  27. +4 −0 src/ui/routes/angle-bracket-components/html-attributes/route.js
  28. +11 −0 src/ui/routes/angle-bracket-components/html-attributes/template.hbs
  29. +5 −0 src/ui/routes/angle-bracket-components/is-it-one-way/controller.js
  30. +11 −0 src/ui/routes/angle-bracket-components/is-it-one-way/route-test.js
  31. +4 −0 src/ui/routes/angle-bracket-components/is-it-one-way/route.js
  32. +13 −0 src/ui/routes/angle-bracket-components/is-it-one-way/template.hbs
  33. +11 −0 src/ui/routes/angle-bracket-components/one-word-component-names/route-test.js
  34. +4 −0 src/ui/routes/angle-bracket-components/one-word-component-names/route.js
  35. +9 −0 src/ui/routes/angle-bracket-components/one-word-component-names/template.hbs
  36. +11 −0 src/ui/routes/angle-bracket-components/positional-arguments/route-test.js
  37. +4 −0 src/ui/routes/angle-bracket-components/positional-arguments/route.js
  38. +13 −0 src/ui/routes/angle-bracket-components/positional-arguments/template.hbs
  39. +11 −0 src/ui/routes/angle-bracket-components/route-test.js
  40. +4 −0 src/ui/routes/angle-bracket-components/route.js
  41. +11 −0 src/ui/routes/angle-bracket-components/tagless-html-attributes/route-test.js
  42. +4 −0 src/ui/routes/angle-bracket-components/tagless-html-attributes/route.js
  43. +11 −0 src/ui/routes/angle-bracket-components/tagless-html-attributes/template.hbs
  44. +15 −0 src/ui/routes/angle-bracket-components/template.hbs
  45. +1 −3 src/ui/routes/application/template.hbs
  46. +3 −0 src/ui/styles/app.css
  47. +55 −4 yarn.lock
@@ -23,6 +23,7 @@
"babel-eslint": "^8.0.0",
"broccoli-asset-rev": "^2.7.0",
"ember-ajax": "^3.1.0",
"ember-array-helper": "^5.0.0",
"ember-auto-import": "^1.2.19",
"ember-bind-helper": "^0.3.2",
"ember-cli": "github:ember-cli/ember-cli",
@@ -41,6 +42,7 @@
"ember-export-application-global": "^2.0.0",
"ember-load-initializers": "^1.1.0",
"ember-maybe-import-regenerator": "^0.1.6",
"ember-power-select": "^2.2.1",
"ember-qunit": "^3.4.1",
"ember-resolver": "^5.0.1",
"ember-source": "https://s3.amazonaws.com/builds.emberjs.com/canary/shas/3076110196bde48f9daf4c09ed31baace91df9b2.tgz",
@@ -6,6 +6,16 @@ const Router = EmberRouter.extend({
rootURL: config.rootURL
});

Router.map(function() {});
Router.map(function() {
this.route('angle-bracket-components', function() {
this.route('basics');
this.route('block-component');
this.route('is-it-one-way');
this.route('html-attributes');
this.route('tagless-html-attributes');
this.route('positional-arguments');
this.route('one-word-component-names');
});
});

export default Router;
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Component | cool-paragraph', function(hooks) {
setupRenderingTest(hooks);

test('it renders', async function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`{{cool-paragraph}}`);

assert.equal(this.element.textContent.trim(), '');

// Template block usage:
await render(hbs`
{{#cool-paragraph}}
template block text
{{/cool-paragraph}}
`);

assert.equal(this.element.textContent.trim(), 'template block text');
});
});
@@ -0,0 +1,5 @@
import Component from '@ember/component';

export default class CoolParagraphComponent extends Component {
// attributeBindings = ["data-test"]
}
@@ -0,0 +1 @@
<p>You know what's cool? {{this.coolThing}}</p>
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Component | paragraph', function(hooks) {
setupRenderingTest(hooks);

test('it renders', async function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`{{paragraph}}`);

assert.equal(this.element.textContent.trim(), '');

// Template block usage:
await render(hbs`
{{#paragraph}}
template block text
{{/paragraph}}
`);

assert.equal(this.element.textContent.trim(), 'template block text');
});
});
@@ -0,0 +1,4 @@
import Component from '@ember/component';

export default class ParagraphComponent extends Component {
}
@@ -0,0 +1 @@
<p>A component name that's a single word</p>
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Component | positional-arguments-paragraph', function(hooks) {
setupRenderingTest(hooks);

test('it renders', async function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`{{positional-arguments-paragraph}}`);

assert.equal(this.element.textContent.trim(), '');

// Template block usage:
await render(hbs`
{{#positional-arguments-paragraph}}
template block text
{{/positional-arguments-paragraph}}
`);

assert.equal(this.element.textContent.trim(), 'template block text');
});
});
@@ -0,0 +1,5 @@
import Component from '@ember/component';

export default class PositionalArgumentsParagraphComponent extends Component {
static positionalParams = ['coolThing']
}
@@ -0,0 +1 @@
<p>You know what's cool? {{this.coolThing}}</p>
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Component | tagless-cool-paragraph', function(hooks) {
setupRenderingTest(hooks);

test('it renders', async function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`{{tagless-cool-paragraph}}`);

assert.equal(this.element.textContent.trim(), '');

// Template block usage:
await render(hbs`
{{#tagless-cool-paragraph}}
template block text
{{/tagless-cool-paragraph}}
`);

assert.equal(this.element.textContent.trim(), 'template block text');
});
});
@@ -0,0 +1,7 @@
import Component from '@ember/component';

export default class TaglessCoolParagraphComponent extends Component {
tagName = ''
// attributeBindings = ['class', 'data-test']
// you're not allowed to use attributeBindings on a tagless component
}
@@ -0,0 +1,3 @@
<p ...attributes>You know what's cool? {{this.coolThing}}</p>

{{!-- <p class={{class}} data-test={{data-test}}>You know what's cool? {{coolThing}}</p> --}}
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Component | text-changer', function(hooks) {
setupRenderingTest(hooks);

test('it renders', async function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`{{text-changer}}`);

assert.equal(this.element.textContent.trim(), '');

// Template block usage:
await render(hbs`
{{#text-changer}}
template block text
{{/text-changer}}
`);

assert.equal(this.element.textContent.trim(), 'template block text');
});
});
@@ -0,0 +1,4 @@
import Component from '@ember/component';

export default class TextChangerComponent extends Component {
}
@@ -0,0 +1 @@
{{input value=this.textToChange}}
@@ -0,0 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

module('Unit | Route | angle-bracket-components/basic', function(hooks) {
setupTest(hooks);

test('it exists', function(assert) {
let route = this.owner.lookup('route:angle-bracket-components/basic');
assert.ok(route);
});
});
@@ -0,0 +1,4 @@
import Route from '@ember/routing/route';

export default class AngleBracketComponentsBasicRoute extends Route {
}
@@ -0,0 +1,9 @@
<h2>Basics</h2>

{{cool-paragraph coolThing="Curly Components"}}

<hr>

<CoolParagraph @coolThing="Angle Bracket Components" />

{{!-- The only change so far is in how they're invoked --}}
@@ -0,0 +1,12 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

module('Unit | Controller | angle-bracket-components/block-component', function(hooks) {
setupTest(hooks);

// Replace this with your real tests.
test('it exists', function(assert) {
let controller = this.owner.lookup('controller:angle-bracket-components/block-component');
assert.ok(controller);
});
});
@@ -0,0 +1,12 @@
import Controller from '@ember/controller';

export default class AngleBracketComponentsBlockComponentController extends Controller {
topicIdeas = [
"ES6 Class Syntax",
"New app organization",
"ember-cli-create",
"CRUD 2019",
"LiquidFire",
"Building something complex step by step"
]
}
@@ -0,0 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

module('Unit | Route | angle-bracket-component/block-component', function(hooks) {
setupTest(hooks);

test('it exists', function(assert) {
let route = this.owner.lookup('route:angle-bracket-component/block-component');
assert.ok(route);
});
});
@@ -0,0 +1,4 @@
import Route from '@ember/routing/route';

export default class AngleBracketComponentBlockComponentRoute extends Route {
}
@@ -0,0 +1,31 @@
<h2>Block Components</h2>
<p>(Using ember-power-component)</p>

<p>Select the next topic:</p>
{{#power-select
selected=nextTopic
options=this.topicIdeas
onchange=(action (mut nextTopic))
as |name|
}}
{{name}}
{{/power-select}}

<CoolParagraph @coolThing={{nextTopic}} />

<hr>

<p>Select the next topic2:</p>
<PowerSelect
@selected={{nextTopic2}}
@options={{this.topicIdeas}}
@onchange={{action (mut nextTopic2)}}
as |name|
>
{{name}}
</PowerSelect>

<CoolParagraph @coolThing={{nextTopic2}} />

{{!-- The differences here are pretty self-explanatory. --}}
{{!-- We're using the ember-power-select addon: https://ember-power-select.com/docs --}}
@@ -0,0 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

module('Unit | Route | angle-bracket-components/html-attributes', function(hooks) {
setupTest(hooks);

test('it exists', function(assert) {
let route = this.owner.lookup('route:angle-bracket-components/html-attributes');
assert.ok(route);
});
});
@@ -0,0 +1,4 @@
import Route from '@ember/routing/route';

export default class AngleBracketComponentsHtmlAttributesRoute extends Route {
}
@@ -0,0 +1,11 @@
<h2>Html Attributes</h2>

{{cool-paragraph data-test="hello" class="blue" coolThing="using html attributes"}}

<hr>

<CoolParagraph data-test="hello" class="blue" @coolThing="using html attributes" />

{{!-- Two advantages of angle-bracket invocation --}}
{{!-- 1. It's easy to tell the difference between html attributes and named arguments in curly bracket invocation --}}
{{!-- 2. data-test and many other html attributes don't bind on the curly-bracket invocation unless we add `attributeBindings = ['data-test']` --}}
@@ -0,0 +1,5 @@
import Controller from '@ember/controller';

export default class IsItOneWayController extends Controller {
coolThing = "Angle Bracket Components"
}
@@ -0,0 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

module('Unit | Route | angle-bracket-components/is-it-one-way', function(hooks) {
setupTest(hooks);

test('it exists', function(assert) {
let route = this.owner.lookup('route:angle-bracket-components/is-it-one-way');
assert.ok(route);
});
});
@@ -0,0 +1,4 @@
import Route from '@ember/routing/route';

export default class AngleBracketComponentsIsItOneWayRoute extends Route {
}
@@ -0,0 +1,13 @@
<h2>Is it one way?</h2>

{{cool-paragraph coolThing=coolThing}}

<p>Is curly brackets one-way data bound by default?</p>
{{text-changer textToChange=coolThing}}

<hr>

<p>Is angle brackets one-way data bound by default?</p>
<TextChanger @textToChange={{coolThing}} />

{{!-- No, they are not bound by default. This was something that was in the original spec, but was dropped --}}
@@ -0,0 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

module('Unit | Route | angle-bracket-components/one-word-component-names', function(hooks) {
setupTest(hooks);

test('it exists', function(assert) {
let route = this.owner.lookup('route:angle-bracket-components/one-word-component-names');
assert.ok(route);
});
});
@@ -0,0 +1,4 @@
import Route from '@ember/routing/route';

export default class AngleBracketComponentsOneWordComponentNamesRoute extends Route {
}
Oops, something went wrong.

0 comments on commit 824ec2e

Please sign in to comment.