ember-source 6.1.0-alpha.4 → 6.1.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build-metadata.json +3 -3
- package/dist/ember-template-compiler.js +2 -2
- package/dist/ember-testing.js +1 -1
- package/dist/ember.debug.js +2 -2
- package/dist/ember.prod.js +2 -2
- package/dist/packages/ember/version.js +1 -1
- package/docs/data.json +1 -24
- package/package.json +4 -4
- package/types/publish.mjs +12 -2
- package/types/stable/index.d.ts +0 -1
- package/types/stable/@ember/-internals/glimmer/lib/glimmer-component-docs.d.ts +0 -388
package/build-metadata.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "6.1.0-alpha.
|
|
2
|
+
"version": "6.1.0-alpha.5",
|
|
3
3
|
"buildType": "tag",
|
|
4
|
-
"SHA": "
|
|
5
|
-
"assetPath": "/tag/shas/
|
|
4
|
+
"SHA": "d228f82771b448d5b0359b731579d3ab083db135",
|
|
5
|
+
"assetPath": "/tag/shas/d228f82771b448d5b0359b731579d3ab083db135.tgz"
|
|
6
6
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
|
|
6
6
|
* @license Licensed under MIT license
|
|
7
7
|
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
|
|
8
|
-
* @version 6.1.0-alpha.
|
|
8
|
+
* @version 6.1.0-alpha.5
|
|
9
9
|
*/
|
|
10
10
|
/* eslint-disable no-var */
|
|
11
11
|
/* globals global globalThis self */
|
|
@@ -15651,7 +15651,7 @@ var define, require;
|
|
|
15651
15651
|
}, Symbol.toStringTag, { value: 'Module' });
|
|
15652
15652
|
|
|
15653
15653
|
// this file gets replaced with the real value during the build
|
|
15654
|
-
const version = '6.1.0-alpha.
|
|
15654
|
+
const version = '6.1.0-alpha.5';
|
|
15655
15655
|
|
|
15656
15656
|
const emberVersion = /*#__PURE__*/Object.defineProperty({
|
|
15657
15657
|
__proto__: null,
|
package/dist/ember-testing.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
|
|
6
6
|
* @license Licensed under MIT license
|
|
7
7
|
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
|
|
8
|
-
* @version 6.1.0-alpha.
|
|
8
|
+
* @version 6.1.0-alpha.5
|
|
9
9
|
*/
|
|
10
10
|
/* eslint-disable no-var */
|
|
11
11
|
/* globals global globalThis self */
|
package/dist/ember.debug.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
|
|
6
6
|
* @license Licensed under MIT license
|
|
7
7
|
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
|
|
8
|
-
* @version 6.1.0-alpha.
|
|
8
|
+
* @version 6.1.0-alpha.5
|
|
9
9
|
*/
|
|
10
10
|
/* eslint-disable no-var */
|
|
11
11
|
/* globals global globalThis self */
|
|
@@ -3379,7 +3379,7 @@ var define, require;
|
|
|
3379
3379
|
}, Symbol.toStringTag, { value: 'Module' });
|
|
3380
3380
|
|
|
3381
3381
|
// this file gets replaced with the real value during the build
|
|
3382
|
-
const Version = '6.1.0-alpha.
|
|
3382
|
+
const Version = '6.1.0-alpha.5';
|
|
3383
3383
|
|
|
3384
3384
|
const emberVersion = /*#__PURE__*/Object.defineProperty({
|
|
3385
3385
|
__proto__: null,
|
package/dist/ember.prod.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
|
|
6
6
|
* @license Licensed under MIT license
|
|
7
7
|
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
|
|
8
|
-
* @version 6.1.0-alpha.
|
|
8
|
+
* @version 6.1.0-alpha.5
|
|
9
9
|
*/
|
|
10
10
|
/* eslint-disable no-var */
|
|
11
11
|
/* globals global globalThis self */
|
|
@@ -2620,7 +2620,7 @@ var define, require;
|
|
|
2620
2620
|
}, Symbol.toStringTag, { value: 'Module' });
|
|
2621
2621
|
|
|
2622
2622
|
// this file gets replaced with the real value during the build
|
|
2623
|
-
const Version = '6.1.0-alpha.
|
|
2623
|
+
const Version = '6.1.0-alpha.5';
|
|
2624
2624
|
|
|
2625
2625
|
const emberVersion = /*#__PURE__*/Object.defineProperty({
|
|
2626
2626
|
__proto__: null,
|
package/docs/data.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "The Ember API",
|
|
4
4
|
"description": "The Ember API: a framework for building ambitious web applications",
|
|
5
5
|
"url": "https://emberjs.com/",
|
|
6
|
-
"version": "6.1.0-alpha.
|
|
6
|
+
"version": "6.1.0-alpha.5"
|
|
7
7
|
},
|
|
8
8
|
"files": {
|
|
9
9
|
"node_modules/rsvp/lib/rsvp/promise/all.js": {
|
|
@@ -520,15 +520,6 @@
|
|
|
520
520
|
"fors": {},
|
|
521
521
|
"namespaces": {}
|
|
522
522
|
},
|
|
523
|
-
"packages/@ember/-internals/glimmer/lib/glimmer-component-docs.ts": {
|
|
524
|
-
"name": "packages/@ember/-internals/glimmer/lib/glimmer-component-docs.ts",
|
|
525
|
-
"modules": {
|
|
526
|
-
"@glimmer/component": 1
|
|
527
|
-
},
|
|
528
|
-
"classes": {},
|
|
529
|
-
"fors": {},
|
|
530
|
-
"namespaces": {}
|
|
531
|
-
},
|
|
532
523
|
"packages/@ember/-internals/glimmer/lib/glimmer-tracking-docs.ts": {
|
|
533
524
|
"name": "packages/@ember/-internals/glimmer/lib/glimmer-tracking-docs.ts",
|
|
534
525
|
"modules": {
|
|
@@ -1904,20 +1895,6 @@
|
|
|
1904
1895
|
"file": "packages/@ember/-internals/glimmer/lib/utils/string.ts",
|
|
1905
1896
|
"line": 7
|
|
1906
1897
|
},
|
|
1907
|
-
"@glimmer/component": {
|
|
1908
|
-
"name": "@glimmer/component",
|
|
1909
|
-
"submodules": {},
|
|
1910
|
-
"elements": {},
|
|
1911
|
-
"classes": {},
|
|
1912
|
-
"fors": {},
|
|
1913
|
-
"namespaces": {},
|
|
1914
|
-
"tag": "module",
|
|
1915
|
-
"file": "packages/@ember/-internals/glimmer/lib/glimmer-component-docs.ts",
|
|
1916
|
-
"line": 1,
|
|
1917
|
-
"description": "A component is a reusable UI element that consists of a `.hbs` template and an\noptional JavaScript class that defines its behavior. For example, someone\nmight make a `button` in the template and handle the click behavior in the\nJavaScript file that shares the same name as the template.\n\nComponents are broken down into two categories:\n\n- Components _without_ JavaScript, that are based only on a template. These\n are called Template-only or TO components.\n- Components _with_ JavaScript, which consist of a template and a backing\n class.\n\nEmber ships with two types of JavaScript classes for components:\n\n1. Glimmer components, imported from `@glimmer/component`, which are the\n default components for Ember Octane (3.15) and more recent editions.\n2. Classic components, imported from `@ember/component`, which were the\n default for older editions of Ember (pre 3.15).\n\nBelow is the documentation for Template-only and Glimmer components. If you\nare looking for the API documentation for Classic components, it is\n[available here](/ember/release/classes/Component). The source code for\nGlimmer components can be found in [`@glimmer/component`](https://github.com/glimmerjs/glimmer.js/tree/master/packages/%40glimmer/component).\n\n## Defining a Template-only Component\n\nThe simplest way to create a component is to create a template file in\n`app/templates/components`. For example, if you name a template\n`app/templates/components/person-profile.hbs`:\n\n```app/templates/components/person-profile.hbs\n<h1>{{@person.name}}</h1>\n<img src={{@person.avatar}}>\n<p class='signature'>{{@person.signature}}</p>\n```\n\nYou will be able to use `<PersonProfile />` to invoke this component elsewhere\nin your application:\n\n```app/templates/application.hbs\n<PersonProfile @person={{this.currentUser}} />\n```\n\nNote that component names are capitalized here in order to distinguish them\nfrom regular HTML elements, but they are dasherized in the file system.\n\nWhile the angle bracket invocation form is generally preferred, it is also\npossible to invoke the same component with the `{{person-profile}}` syntax:\n\n```app/templates/application.hbs\n{{person-profile person=this.currentUser}}\n```\n\nNote that with this syntax, you use dashes in the component name and\narguments are passed without the `@` sign.\n\nIn both cases, Ember will render the content of the component template we\ncreated above. The end result will be something like this:\n\n```html\n<h1>Tomster</h1>\n<img src=\"https://emberjs.com/tomster.jpg\">\n<p class='signature'>Out of office this week</p>\n```\n\n## File System Nesting\n\nComponents can be nested inside sub-folders for logical groupping. For\nexample, if we placed our template in\n`app/templates/components/person/short-profile.hbs`, we can invoke it as\n`<Person::ShortProfile />`:\n\n```app/templates/application.hbs\n<Person::ShortProfile @person={{this.currentUser}} />\n```\n\nOr equivalently, `{{person/short-profile}}`:\n\n```app/templates/application.hbs\n{{person/short-profile person=this.currentUser}}\n```\n\n## Using Blocks\n\nYou can use `yield` inside a template to include the **contents** of any block\nattached to the component. For instance, if we added a `{{yield}}` to our\ncomponent like so:\n\n```app/templates/components/person-profile.hbs\n<h1>{{@person.name}}</h1>\n{{yield}}\n```\n\nWe could then invoke it like this:\n\n```handlebars\n<PersonProfile @person={{this.currentUser}}>\n <p>Admin mode</p>\n</PersonProfile>\n```\n\nor with curly syntax like this:\n\n```handlebars\n{{#person-profile person=this.currentUser}}\n <p>Admin mode</p>\n{{/person-profile}}\n```\n\nAnd the content passed in between the brackets of the component would be\nrendered in the same place as the `{{yield}}` within it, replacing it.\n\nBlocks are executed in their original context, meaning they have access to the\nscope and any in-scope variables where they were defined.\n\n### Passing parameters to blocks\n\nYou can also pass positional parameters to `{{yield}}`, which are then made\navailable in the block:\n\n```app/templates/components/person-profile.hbs\n<h1>{{@person.name}}</h1>\n{{yield @person.signature}}\n```\n\nWe can then use this value in the block like so:\n\n```handlebars\n<PersonProfile @person={{this.currentUser}} as |signature|>\n {{signature}}\n</PersonProfile>\n```\n\n### Passing multiple blocks\n\nYou can pass multiple blocks to a component by giving them names, and\nspecifying which block you are yielding to with `{{yield}}`. For instance, if\nwe wanted to add a way for users to customize the title of our\n`<PersonProfile>` component, we could add a named block inside of the header:\n\n```app/templates/components/person-profile.hbs\n<h1>{{yield to=\"title\"}}</h1>\n{{yield}}\n```\n\nThis component could then be invoked like so:\n\n```handlebars\n<PersonProfile @person={{this.currentUser}}>\n <:title>{{this.currentUser.name}}</:title>\n <:default>{{this.currentUser.signature}}</:default>\n</PersonProfile>\n```\n\nWhen passing named blocks, you must name every block, including the `default`\nblock, which is the block that is defined if you do not pass a `to` parameter\nto `{{yield}}`. Whenever you invoke a component without passing explicitly\nnamed blocks, the passed block is considered the `default` block.\n\n### Passing parameters to named blocks\n\nYou can also pass parameters to named blocks:\n\n```app/templates/components/person-profile.hbs\n<h1>{{yield @person.name to=\"title\"}}</h1>\n{{yield @person.signature}}\n```\n\nThese parameters can then be used like so:\n\n```handlebars\n<PersonProfile @person={{this.currentUser}}>\n <:title as |name|>{{name}}</:title>\n <:default as |signature|>{{signature}}</:default>\n</PersonProfile>\n```\n\n### Checking to see if a block exists\n\nYou can also check to see if a block exists using the `(has-block)` keyword,\nand conditionally use it, or provide a default template instead.\n\n```app/templates/components/person-profile.hbs\n<h1>\n {{#if (has-block \"title\")}}\n {{yield @person.name to=\"title\"}}\n {{else}}\n {{@person.name}}\n {{/if}}\n</h1>\n\n{{#if (has-block)}}\n {{yield @person.signature}}\n{{else}}\n {{@person.signature}}\n{{/if}}\n```\n\nWith this template, we can then optionally pass in one block, both blocks, or\nnone at all:\n\n```handlebars\n{{! passing both blocks }}\n<PersonProfile @person={{this.currentUser}}>\n <:title as |name|>{{name}}</:title>\n <:default as |signature|>{{signature}}</:default>\n</PersonProfile>\n\n{{! passing just the title block }}\n<PersonProfile @person={{this.currentUser}}>\n <:title as |name|>{{name}}</:title>\n</PersonProfile>\n\n{{! passing just the default block }}\n<PersonProfile @person={{this.currentUser}} as |signature|>\n {{signature}}\n</PersonProfile>\n\n{{! not passing any blocks }}\n<PersonProfile @person={{this.currentUser}}/>\n```\n\n### Checking to see if a block has parameters\n\nWe can also check if a block receives parameters using the `(has-block-params)`\nkeyword, and conditionally yield different values if so.\n\n```app/templates/components/person-profile.hbs\n{{#if (has-block-params)}}\n {{yield @person.signature}}\n{{else}}\n {{yield}}\n{{/if}}\n```\n\n## Customizing Components With JavaScript\n\nTo add JavaScript to a component, create a JavaScript file in the same\nlocation as the template file, with the same name, and export a subclass\nof `Component` as the default value. For example, to add Javascript to the\n`PersonProfile` component which we defined above, we would create\n`app/components/person-profile.js` and export our class as the default, like\nso:\n\n```app/components/person-profile.js\nimport Component from '@glimmer/component';\n\nexport default class PersonProfileComponent extends Component {\n get displayName() {\n let { title, firstName, lastName } = this.args.person;\n\n if (title) {\n return `${title} ${lastName}`;\n } else {\n return `${firstName} ${lastName}`;\n }\n })\n}\n```\n\nYou can add your own properties, methods, and lifecycle hooks to this\nsubclass to customize its behavior, and you can reference the instance of the\nclass in your template using `{{this}}`. For instance, we could access the\n`displayName` property of our `PersonProfile` component instance in the\ntemplate like this:\n\n```app/templates/components/person-profile.hbs\n<h1>{{this.displayName}}</h1>\n{{yield}}\n```\n\n## `constructor`\n\nparams: `owner` object and `args` object\n\nConstructs a new component and assigns itself the passed properties. The\nconstructor is run whenever a new instance of the component is created, and\ncan be used to setup the initial state of the component.\n\n```javascript\nimport Component from '@glimmer/component';\n\nexport default class SomeComponent extends Component {\n constructor(owner, args) {\n super(owner, args);\n\n if (this.args.displayMode === 'list') {\n this.items = [];\n }\n }\n}\n```\n\nService injections and arguments are available in the constructor.\n\n```javascript\nimport Component from '@glimmer/component';\nimport { service } from '@ember/service';\n\nexport default class SomeComponent extends Component {\n @service myAnimations;\n\n constructor(owner, args) {\n super(owner, args);\n\n if (this.args.fadeIn === true) {\n this.myAnimations.register(this, 'fade-in');\n }\n }\n}\n```\n\n## `willDestroy`\n\n`willDestroy` is called after the component has been removed from the DOM, but\nbefore the component is fully destroyed. This lifecycle hook can be used to\ncleanup the component and any related state.\n\n```javascript\nimport Component from '@glimmer/component';\nimport { service } from '@ember/service';\n\nexport default class SomeComponent extends Component {\n @service myAnimations;\n\n willDestroy() {\n super.willDestroy(...arguments);\n\n this.myAnimations.unregister(this);\n }\n}\n```\n\n## `args`\n\nThe `args` property of Glimmer components is an object that contains the\n_arguments_ that are passed to the component. For instance, the\nfollowing component usage:\n\n```handlebars\n<SomeComponent @fadeIn={{true}} />\n```\n\nWould result in the following `args` object to be passed to the component:\n\n```javascript\n{ fadeIn: true }\n```\n\n`args` can be accessed at any point in the component lifecycle, including\n`constructor` and `willDestroy`. They are also automatically marked as tracked\nproperties, and they can be depended on as computed property dependencies:\n\n```javascript\nimport Component from '@glimmer/component';\nimport { computed } from '@ember/object';\n\nexport default class SomeComponent extends Component {\n\n @computed('args.someValue')\n get computedGetter() {\n // updates whenever args.someValue updates\n return this.args.someValue;\n }\n\n get standardGetter() {\n // updates whenever args.anotherValue updates (Ember 3.13+)\n return this.args.anotherValue;\n }\n}\n```\n\n## `isDestroying`\n\nA boolean flag to tell if the component is in the process of destroying. This is set to\ntrue before `willDestroy` is called.\n\n## `isDestroyed`\nA boolean to tell if the component has been fully destroyed. This is set to true\nafter `willDestroy` is called.",
|
|
1918
|
-
"access": "public",
|
|
1919
|
-
"tagname": ""
|
|
1920
|
-
},
|
|
1921
1898
|
"@glimmer/tracking": {
|
|
1922
1899
|
"name": "@glimmer/tracking",
|
|
1923
1900
|
"submodules": {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember-source",
|
|
3
|
-
"version": "6.1.0-alpha.
|
|
3
|
+
"version": "6.1.0-alpha.5",
|
|
4
4
|
"description": "A JavaScript framework for creating ambitious web applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"@babel/preset-env": "^7.16.11",
|
|
112
112
|
"@babel/types": "^7.22.5",
|
|
113
113
|
"@embroider/shared-internals": "^2.5.0",
|
|
114
|
-
"@glimmer/component": "
|
|
114
|
+
"@glimmer/component": "workspace:^",
|
|
115
115
|
"@rollup/plugin-babel": "^6.0.4",
|
|
116
116
|
"@simple-dom/document": "^1.4.0",
|
|
117
117
|
"@swc-node/register": "^1.6.8",
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
}
|
|
174
174
|
},
|
|
175
175
|
"peerDependencies": {
|
|
176
|
-
"@glimmer/component": "
|
|
176
|
+
"@glimmer/component": ">= 1.1.2"
|
|
177
177
|
},
|
|
178
178
|
"engines": {
|
|
179
179
|
"node": ">= 18.*"
|
|
@@ -372,7 +372,7 @@
|
|
|
372
372
|
"node": "16.20.0",
|
|
373
373
|
"pnpm": "8.10.0"
|
|
374
374
|
},
|
|
375
|
-
"_originalVersion": "6.1.0-alpha.
|
|
375
|
+
"_originalVersion": "6.1.0-alpha.5",
|
|
376
376
|
"_versionPreviouslyCalculated": true,
|
|
377
377
|
"publishConfig": {
|
|
378
378
|
"tag": "alpha"
|
package/types/publish.mjs
CHANGED
|
@@ -116,8 +116,7 @@ async function main() {
|
|
|
116
116
|
|
|
117
117
|
// The majority of those items should be excluded entirely, but in some cases
|
|
118
118
|
// we still need to post-process them.
|
|
119
|
-
let excludes = remappedLocationExcludes
|
|
120
|
-
.concat(sideEffectExcludes);
|
|
119
|
+
let excludes = remappedLocationExcludes.concat(sideEffectExcludes);
|
|
121
120
|
|
|
122
121
|
// This is rooted in the `TYPES_DIR` so that the result is just the names of
|
|
123
122
|
// the modules, as generated directly from the tsconfig above. These must
|
|
@@ -147,6 +146,17 @@ async function main() {
|
|
|
147
146
|
// Make the generated types easier to read!
|
|
148
147
|
spawnSync('prettier', ['--write', 'types/stable/**/*.ts']);
|
|
149
148
|
|
|
149
|
+
// @glimmer/component publishes as a separate package. We need to build its
|
|
150
|
+
// types after building the ember-source types.
|
|
151
|
+
doOrDie(() => {
|
|
152
|
+
let result = spawnSync('pnpm', ['tsc'], { cwd: 'packages/@glimmer/component' });
|
|
153
|
+
if (result.status !== 0) {
|
|
154
|
+
console.log(`@glimmer/component types build failed:`);
|
|
155
|
+
console.error(result.output.toString());
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
150
160
|
process.exit(status === 'success' ? 0 : 1);
|
|
151
161
|
}
|
|
152
162
|
|
package/types/stable/index.d.ts
CHANGED
|
@@ -66,7 +66,6 @@
|
|
|
66
66
|
/// <reference path="./@ember/-internals/glimmer/lib/components/textarea.d.ts" />
|
|
67
67
|
/// <reference path="./@ember/-internals/glimmer/lib/dom.d.ts" />
|
|
68
68
|
/// <reference path="./@ember/-internals/glimmer/lib/environment.d.ts" />
|
|
69
|
-
/// <reference path="./@ember/-internals/glimmer/lib/glimmer-component-docs.d.ts" />
|
|
70
69
|
/// <reference path="./@ember/-internals/glimmer/lib/glimmer-tracking-docs.d.ts" />
|
|
71
70
|
/// <reference path="./@ember/-internals/glimmer/lib/helper.d.ts" />
|
|
72
71
|
/// <reference path="./@ember/-internals/glimmer/lib/helpers/-disallow-dynamic-resolution.d.ts" />
|
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
declare module '@ember/-internals/glimmer/lib/glimmer-component-docs' {
|
|
2
|
-
/**
|
|
3
|
-
A component is a reusable UI element that consists of a `.hbs` template and an
|
|
4
|
-
optional JavaScript class that defines its behavior. For example, someone
|
|
5
|
-
might make a `button` in the template and handle the click behavior in the
|
|
6
|
-
JavaScript file that shares the same name as the template.
|
|
7
|
-
|
|
8
|
-
Components are broken down into two categories:
|
|
9
|
-
|
|
10
|
-
- Components _without_ JavaScript, that are based only on a template. These
|
|
11
|
-
are called Template-only or TO components.
|
|
12
|
-
- Components _with_ JavaScript, which consist of a template and a backing
|
|
13
|
-
class.
|
|
14
|
-
|
|
15
|
-
Ember ships with two types of JavaScript classes for components:
|
|
16
|
-
|
|
17
|
-
1. Glimmer components, imported from `@glimmer/component`, which are the
|
|
18
|
-
default components for Ember Octane (3.15) and more recent editions.
|
|
19
|
-
2. Classic components, imported from `@ember/component`, which were the
|
|
20
|
-
default for older editions of Ember (pre 3.15).
|
|
21
|
-
|
|
22
|
-
Below is the documentation for Template-only and Glimmer components. If you
|
|
23
|
-
are looking for the API documentation for Classic components, it is
|
|
24
|
-
[available here](/ember/release/classes/Component). The source code for
|
|
25
|
-
Glimmer components can be found in [`@glimmer/component`](https://github.com/glimmerjs/glimmer.js/tree/master/packages/%40glimmer/component).
|
|
26
|
-
|
|
27
|
-
## Defining a Template-only Component
|
|
28
|
-
|
|
29
|
-
The simplest way to create a component is to create a template file in
|
|
30
|
-
`app/templates/components`. For example, if you name a template
|
|
31
|
-
`app/templates/components/person-profile.hbs`:
|
|
32
|
-
|
|
33
|
-
```app/templates/components/person-profile.hbs
|
|
34
|
-
<h1>{{@person.name}}</h1>
|
|
35
|
-
<img src={{@person.avatar}}>
|
|
36
|
-
<p class='signature'>{{@person.signature}}</p>
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
You will be able to use `<PersonProfile />` to invoke this component elsewhere
|
|
40
|
-
in your application:
|
|
41
|
-
|
|
42
|
-
```app/templates/application.hbs
|
|
43
|
-
<PersonProfile @person={{this.currentUser}} />
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Note that component names are capitalized here in order to distinguish them
|
|
47
|
-
from regular HTML elements, but they are dasherized in the file system.
|
|
48
|
-
|
|
49
|
-
While the angle bracket invocation form is generally preferred, it is also
|
|
50
|
-
possible to invoke the same component with the `{{person-profile}}` syntax:
|
|
51
|
-
|
|
52
|
-
```app/templates/application.hbs
|
|
53
|
-
{{person-profile person=this.currentUser}}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Note that with this syntax, you use dashes in the component name and
|
|
57
|
-
arguments are passed without the `@` sign.
|
|
58
|
-
|
|
59
|
-
In both cases, Ember will render the content of the component template we
|
|
60
|
-
created above. The end result will be something like this:
|
|
61
|
-
|
|
62
|
-
```html
|
|
63
|
-
<h1>Tomster</h1>
|
|
64
|
-
<img src="https://emberjs.com/tomster.jpg">
|
|
65
|
-
<p class='signature'>Out of office this week</p>
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## File System Nesting
|
|
69
|
-
|
|
70
|
-
Components can be nested inside sub-folders for logical groupping. For
|
|
71
|
-
example, if we placed our template in
|
|
72
|
-
`app/templates/components/person/short-profile.hbs`, we can invoke it as
|
|
73
|
-
`<Person::ShortProfile />`:
|
|
74
|
-
|
|
75
|
-
```app/templates/application.hbs
|
|
76
|
-
<Person::ShortProfile @person={{this.currentUser}} />
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Or equivalently, `{{person/short-profile}}`:
|
|
80
|
-
|
|
81
|
-
```app/templates/application.hbs
|
|
82
|
-
{{person/short-profile person=this.currentUser}}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
## Using Blocks
|
|
86
|
-
|
|
87
|
-
You can use `yield` inside a template to include the **contents** of any block
|
|
88
|
-
attached to the component. For instance, if we added a `{{yield}}` to our
|
|
89
|
-
component like so:
|
|
90
|
-
|
|
91
|
-
```app/templates/components/person-profile.hbs
|
|
92
|
-
<h1>{{@person.name}}</h1>
|
|
93
|
-
{{yield}}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
We could then invoke it like this:
|
|
97
|
-
|
|
98
|
-
```handlebars
|
|
99
|
-
<PersonProfile @person={{this.currentUser}}>
|
|
100
|
-
<p>Admin mode</p>
|
|
101
|
-
</PersonProfile>
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
or with curly syntax like this:
|
|
105
|
-
|
|
106
|
-
```handlebars
|
|
107
|
-
{{#person-profile person=this.currentUser}}
|
|
108
|
-
<p>Admin mode</p>
|
|
109
|
-
{{/person-profile}}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
And the content passed in between the brackets of the component would be
|
|
113
|
-
rendered in the same place as the `{{yield}}` within it, replacing it.
|
|
114
|
-
|
|
115
|
-
Blocks are executed in their original context, meaning they have access to the
|
|
116
|
-
scope and any in-scope variables where they were defined.
|
|
117
|
-
|
|
118
|
-
### Passing parameters to blocks
|
|
119
|
-
|
|
120
|
-
You can also pass positional parameters to `{{yield}}`, which are then made
|
|
121
|
-
available in the block:
|
|
122
|
-
|
|
123
|
-
```app/templates/components/person-profile.hbs
|
|
124
|
-
<h1>{{@person.name}}</h1>
|
|
125
|
-
{{yield @person.signature}}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
We can then use this value in the block like so:
|
|
129
|
-
|
|
130
|
-
```handlebars
|
|
131
|
-
<PersonProfile @person={{this.currentUser}} as |signature|>
|
|
132
|
-
{{signature}}
|
|
133
|
-
</PersonProfile>
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Passing multiple blocks
|
|
137
|
-
|
|
138
|
-
You can pass multiple blocks to a component by giving them names, and
|
|
139
|
-
specifying which block you are yielding to with `{{yield}}`. For instance, if
|
|
140
|
-
we wanted to add a way for users to customize the title of our
|
|
141
|
-
`<PersonProfile>` component, we could add a named block inside of the header:
|
|
142
|
-
|
|
143
|
-
```app/templates/components/person-profile.hbs
|
|
144
|
-
<h1>{{yield to="title"}}</h1>
|
|
145
|
-
{{yield}}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
This component could then be invoked like so:
|
|
149
|
-
|
|
150
|
-
```handlebars
|
|
151
|
-
<PersonProfile @person={{this.currentUser}}>
|
|
152
|
-
<:title>{{this.currentUser.name}}</:title>
|
|
153
|
-
<:default>{{this.currentUser.signature}}</:default>
|
|
154
|
-
</PersonProfile>
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
When passing named blocks, you must name every block, including the `default`
|
|
158
|
-
block, which is the block that is defined if you do not pass a `to` parameter
|
|
159
|
-
to `{{yield}}`. Whenever you invoke a component without passing explicitly
|
|
160
|
-
named blocks, the passed block is considered the `default` block.
|
|
161
|
-
|
|
162
|
-
### Passing parameters to named blocks
|
|
163
|
-
|
|
164
|
-
You can also pass parameters to named blocks:
|
|
165
|
-
|
|
166
|
-
```app/templates/components/person-profile.hbs
|
|
167
|
-
<h1>{{yield @person.name to="title"}}</h1>
|
|
168
|
-
{{yield @person.signature}}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
These parameters can then be used like so:
|
|
172
|
-
|
|
173
|
-
```handlebars
|
|
174
|
-
<PersonProfile @person={{this.currentUser}}>
|
|
175
|
-
<:title as |name|>{{name}}</:title>
|
|
176
|
-
<:default as |signature|>{{signature}}</:default>
|
|
177
|
-
</PersonProfile>
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Checking to see if a block exists
|
|
181
|
-
|
|
182
|
-
You can also check to see if a block exists using the `(has-block)` keyword,
|
|
183
|
-
and conditionally use it, or provide a default template instead.
|
|
184
|
-
|
|
185
|
-
```app/templates/components/person-profile.hbs
|
|
186
|
-
<h1>
|
|
187
|
-
{{#if (has-block "title")}}
|
|
188
|
-
{{yield @person.name to="title"}}
|
|
189
|
-
{{else}}
|
|
190
|
-
{{@person.name}}
|
|
191
|
-
{{/if}}
|
|
192
|
-
</h1>
|
|
193
|
-
|
|
194
|
-
{{#if (has-block)}}
|
|
195
|
-
{{yield @person.signature}}
|
|
196
|
-
{{else}}
|
|
197
|
-
{{@person.signature}}
|
|
198
|
-
{{/if}}
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
With this template, we can then optionally pass in one block, both blocks, or
|
|
202
|
-
none at all:
|
|
203
|
-
|
|
204
|
-
```handlebars
|
|
205
|
-
{{! passing both blocks }}
|
|
206
|
-
<PersonProfile @person={{this.currentUser}}>
|
|
207
|
-
<:title as |name|>{{name}}</:title>
|
|
208
|
-
<:default as |signature|>{{signature}}</:default>
|
|
209
|
-
</PersonProfile>
|
|
210
|
-
|
|
211
|
-
{{! passing just the title block }}
|
|
212
|
-
<PersonProfile @person={{this.currentUser}}>
|
|
213
|
-
<:title as |name|>{{name}}</:title>
|
|
214
|
-
</PersonProfile>
|
|
215
|
-
|
|
216
|
-
{{! passing just the default block }}
|
|
217
|
-
<PersonProfile @person={{this.currentUser}} as |signature|>
|
|
218
|
-
{{signature}}
|
|
219
|
-
</PersonProfile>
|
|
220
|
-
|
|
221
|
-
{{! not passing any blocks }}
|
|
222
|
-
<PersonProfile @person={{this.currentUser}}/>
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### Checking to see if a block has parameters
|
|
226
|
-
|
|
227
|
-
We can also check if a block receives parameters using the `(has-block-params)`
|
|
228
|
-
keyword, and conditionally yield different values if so.
|
|
229
|
-
|
|
230
|
-
```app/templates/components/person-profile.hbs
|
|
231
|
-
{{#if (has-block-params)}}
|
|
232
|
-
{{yield @person.signature}}
|
|
233
|
-
{{else}}
|
|
234
|
-
{{yield}}
|
|
235
|
-
{{/if}}
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
## Customizing Components With JavaScript
|
|
239
|
-
|
|
240
|
-
To add JavaScript to a component, create a JavaScript file in the same
|
|
241
|
-
location as the template file, with the same name, and export a subclass
|
|
242
|
-
of `Component` as the default value. For example, to add Javascript to the
|
|
243
|
-
`PersonProfile` component which we defined above, we would create
|
|
244
|
-
`app/components/person-profile.js` and export our class as the default, like
|
|
245
|
-
so:
|
|
246
|
-
|
|
247
|
-
```app/components/person-profile.js
|
|
248
|
-
import Component from '@glimmer/component';
|
|
249
|
-
|
|
250
|
-
export default class PersonProfileComponent extends Component {
|
|
251
|
-
get displayName() {
|
|
252
|
-
let { title, firstName, lastName } = this.args.person;
|
|
253
|
-
|
|
254
|
-
if (title) {
|
|
255
|
-
return `${title} ${lastName}`;
|
|
256
|
-
} else {
|
|
257
|
-
return `${firstName} ${lastName}`;
|
|
258
|
-
}
|
|
259
|
-
})
|
|
260
|
-
}
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
You can add your own properties, methods, and lifecycle hooks to this
|
|
264
|
-
subclass to customize its behavior, and you can reference the instance of the
|
|
265
|
-
class in your template using `{{this}}`. For instance, we could access the
|
|
266
|
-
`displayName` property of our `PersonProfile` component instance in the
|
|
267
|
-
template like this:
|
|
268
|
-
|
|
269
|
-
```app/templates/components/person-profile.hbs
|
|
270
|
-
<h1>{{this.displayName}}</h1>
|
|
271
|
-
{{yield}}
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
## `constructor`
|
|
275
|
-
|
|
276
|
-
params: `owner` object and `args` object
|
|
277
|
-
|
|
278
|
-
Constructs a new component and assigns itself the passed properties. The
|
|
279
|
-
constructor is run whenever a new instance of the component is created, and
|
|
280
|
-
can be used to setup the initial state of the component.
|
|
281
|
-
|
|
282
|
-
```javascript
|
|
283
|
-
import Component from '@glimmer/component';
|
|
284
|
-
|
|
285
|
-
export default class SomeComponent extends Component {
|
|
286
|
-
constructor(owner, args) {
|
|
287
|
-
super(owner, args);
|
|
288
|
-
|
|
289
|
-
if (this.args.displayMode === 'list') {
|
|
290
|
-
this.items = [];
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
Service injections and arguments are available in the constructor.
|
|
297
|
-
|
|
298
|
-
```javascript
|
|
299
|
-
import Component from '@glimmer/component';
|
|
300
|
-
import { service } from '@ember/service';
|
|
301
|
-
|
|
302
|
-
export default class SomeComponent extends Component {
|
|
303
|
-
@service myAnimations;
|
|
304
|
-
|
|
305
|
-
constructor(owner, args) {
|
|
306
|
-
super(owner, args);
|
|
307
|
-
|
|
308
|
-
if (this.args.fadeIn === true) {
|
|
309
|
-
this.myAnimations.register(this, 'fade-in');
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
## `willDestroy`
|
|
316
|
-
|
|
317
|
-
`willDestroy` is called after the component has been removed from the DOM, but
|
|
318
|
-
before the component is fully destroyed. This lifecycle hook can be used to
|
|
319
|
-
cleanup the component and any related state.
|
|
320
|
-
|
|
321
|
-
```javascript
|
|
322
|
-
import Component from '@glimmer/component';
|
|
323
|
-
import { service } from '@ember/service';
|
|
324
|
-
|
|
325
|
-
export default class SomeComponent extends Component {
|
|
326
|
-
@service myAnimations;
|
|
327
|
-
|
|
328
|
-
willDestroy() {
|
|
329
|
-
super.willDestroy(...arguments);
|
|
330
|
-
|
|
331
|
-
this.myAnimations.unregister(this);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
## `args`
|
|
337
|
-
|
|
338
|
-
The `args` property of Glimmer components is an object that contains the
|
|
339
|
-
_arguments_ that are passed to the component. For instance, the
|
|
340
|
-
following component usage:
|
|
341
|
-
|
|
342
|
-
```handlebars
|
|
343
|
-
<SomeComponent @fadeIn={{true}} />
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
Would result in the following `args` object to be passed to the component:
|
|
347
|
-
|
|
348
|
-
```javascript
|
|
349
|
-
{ fadeIn: true }
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
`args` can be accessed at any point in the component lifecycle, including
|
|
353
|
-
`constructor` and `willDestroy`. They are also automatically marked as tracked
|
|
354
|
-
properties, and they can be depended on as computed property dependencies:
|
|
355
|
-
|
|
356
|
-
```javascript
|
|
357
|
-
import Component from '@glimmer/component';
|
|
358
|
-
import { computed } from '@ember/object';
|
|
359
|
-
|
|
360
|
-
export default class SomeComponent extends Component {
|
|
361
|
-
|
|
362
|
-
@computed('args.someValue')
|
|
363
|
-
get computedGetter() {
|
|
364
|
-
// updates whenever args.someValue updates
|
|
365
|
-
return this.args.someValue;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
get standardGetter() {
|
|
369
|
-
// updates whenever args.anotherValue updates (Ember 3.13+)
|
|
370
|
-
return this.args.anotherValue;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
## `isDestroying`
|
|
376
|
-
|
|
377
|
-
A boolean flag to tell if the component is in the process of destroying. This is set to
|
|
378
|
-
true before `willDestroy` is called.
|
|
379
|
-
|
|
380
|
-
## `isDestroyed`
|
|
381
|
-
A boolean to tell if the component has been fully destroyed. This is set to true
|
|
382
|
-
after `willDestroy` is called.
|
|
383
|
-
|
|
384
|
-
@module @glimmer/component
|
|
385
|
-
@public
|
|
386
|
-
*/
|
|
387
|
-
export {};
|
|
388
|
-
}
|