Skip to content

Commit

Permalink
docs: port code examples of template-imports readme
Browse files Browse the repository at this point in the history
  • Loading branch information
ignace committed Nov 21, 2023
1 parent e5e765b commit 528f4f6
Showing 1 changed file with 110 additions and 0 deletions.
110 changes: 110 additions & 0 deletions guides/release/components/template-tag-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,113 @@ import Hello from 'example-app/components/hello';
<Hello @name="world" />
</template>
```
You can also export the component explicitly:

```text {data-filename="components/hello.gjs"}
export default <template>
<span>Hello, {{@name}}!</span>
</template>;
```

Omitting the `export default` is just syntactic sugar. In addition, you can
define template-only components and assign them to variables, allowing you to
export components with named exports:

```text {data-filename="components/hello.gjs"}
export const First = <template>First</template>;
export const Second = <template>Second</template>;
export const Third = <template>Third</template>;
```

This also allows you to create components that are only used locally, in the
same file:

```text {data-filename="components/custom-select.gjs"}
const Option = <template>
<option selected={{@selected}} value={{@value}}>
{{or @title @value}}
</option>
</template>;
export const CustomSelect = <template>
<select>
{{#each @options as |opt|}}
<Option
@value={{opt.value}}
@selected={{eq opt @selectedOption}}
/>
{{/each}}
</select>
</template>;
```

Helpers and modifiers can also be defined in the same file as your components,
making them very flexible:

```text {data-filename="components/list.gjs"}
import { modifier } from 'ember-modifier';
const plusOne = (num) => num + 1;
const setScrollPosition = modifier((element, [position]) => {
element.scrollTop = position
});
<template>
<div class="scroll-container" {{setScrollPosition @scrollPos}}>
{{#each @items as |item index|}}
Item #{{plusOne index}}: {{item}}
{{/each}}
</div>
</template>
```

Finally, to associate a template with a class-based component, you can use the
template syntax directly in the class body:

```text {data-filename="components/hello.gjs"}
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { on } from '@ember/modifier';
export default class Hello extends Component {
@tracked count = 0;
increment = () => {
this.count += 1;
};
decrement = () => {
this.count -= 1;
};
<template>
<button {{on "click" this.increment}}>+</button>
Count: {{this.count}}
<button {{on "click" this.decrement}}>&minus;</button>
</template>
}
```

Template tag components can also be used for writing tests. In fact, this aligned syntax between app code and test code is one of the big advantages of the new authoring format.

Just like in app code, the template tag has access to the outer scope. This means you can reference variables directly in your tests:

```text {data-filename="tests/integration/components/hello-test.gjs"}
import Hello from 'example-app/components/hello';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
module('Integration | Component | hello', function (hooks) {
setupRenderingTest(hooks);
test('renders name argument', async function (assert) {
const name = 'world';
await render(<template><Hello @name={{name}} /></template>);
assert.dom('[data-test-id="some-selector"]').hasText(name);
});
});
```

0 comments on commit 528f4f6

Please sign in to comment.