@@ -238,7 +240,7 @@ module('Acceptance | super rentals', function (hooks) {
assert.strictEqual(
tweetURL.searchParams.get('url'),
- `${window.location.origin}/rentals/grand-old-mansion`
+ `${window.location.origin}/rentals/grand-old-mansion`,
);
});
@@ -322,7 +324,7 @@ import Component from '@glimmer/component';
const TWEET_INTENT = 'https://twitter.com/intent/tweet';
-export default class ShareButtonComponent extends Component {
+export default class ShareButton extends Component {
@service router;
get currentURL() {
@@ -393,7 +395,7 @@ module('Integration | Component | share-button', function (hooks) {
setupRenderingTest(hooks);
const MOCK_URL = new URL(
'/foo/bar?baz=true#some-section',
- window.location.origin
+ window.location.origin,
);
test('it renders', async function (assert) {
@@ -409,7 +411,7 @@ class MockRouterService extends Service {
module('Integration | Component | share-button', function (hooks) {
setupRenderingTest(hooks);
- assert.dom(this.element).hasText('');
+ assert.dom().hasText('');
hooks.beforeEach(function () {
this.owner.register('service:router', MockRouterService);
});
@@ -423,7 +425,7 @@ module('Integration | Component | share-button', function (hooks) {
test('basic usage', async function (assert) {
await render(hbs`
Tweet this!`);
- assert.dom(this.element).hasText('template block text');
+ assert.dom().hasText('template block text');
assert
.dom('a')
.hasAttribute('target', '_blank')
@@ -457,7 +459,7 @@ import { hbs } from 'ember-cli-htmlbars';
const MOCK_URL = new URL(
'/foo/bar?baz=true#some-section',
- window.location.origin
+ window.location.origin,
);
class MockRouterService extends Service {
@@ -500,7 +502,7 @@ module('Integration | Component | share-button', function (hooks) {
test('it supports passing @text', async function (assert) {
await render(
- hbs`
Tweet this!`
+ hbs`
Tweet this!`,
);
assert.strictEqual(this.tweetParam('text'), 'Hello Twitter!');
@@ -508,7 +510,7 @@ module('Integration | Component | share-button', function (hooks) {
test('it supports passing @hashtags', async function (assert) {
await render(
- hbs`
Tweet this!`
+ hbs`
Tweet this!`,
);
assert.strictEqual(this.tweetParam('hashtags'), 'foo,bar,baz');
@@ -521,7 +523,7 @@ module('Integration | Component | share-button', function (hooks) {
test('it supports adding extra classes', async function (assert) {
await render(
- hbs``
+ hbs``,
);
assert
@@ -534,7 +536,7 @@ module('Integration | Component | share-button', function (hooks) {
test('the target, rel and href attributes cannot be overridden', async function (assert) {
await render(
- hbs`
Not a Tweet!`
+ hbs`
Not a Tweet!`,
);
assert
diff --git a/guides/typescript/core-concepts/ember-data.md b/guides/typescript/core-concepts/ember-data.md
index 4290b52ee..b4e742f8c 100644
--- a/guides/typescript/core-concepts/ember-data.md
+++ b/guides/typescript/core-concepts/ember-data.md
@@ -2,6 +2,23 @@ In this section, we cover how to use TypeScript effectively with specific EmberD
We do _not_ cover general usage of EmberData; instead, we assume that as background knowledge. Please see the [EmberData Guides][ED-guides] and [API docs][ED-api-docs]!
+
+
+
+
+
+
+
## Models
EmberData models are normal TypeScript classes, but with properties decorated to define how the model represents an API resource and relationships to other resources. The decorators the library supplies "just work" with TypeScript at runtime, but require type annotations to be useful with TypeScript. Additionally, you must register each model with the [`ModelRegistry`][ED-registry] as shown in the examples below.
diff --git a/guides/typescript/getting-started.md b/guides/typescript/getting-started.md
index 88f045e84..560b96d01 100644
--- a/guides/typescript/getting-started.md
+++ b/guides/typescript/getting-started.md
@@ -33,7 +33,12 @@ The `typescript` package provides tooling to support TypeScript type checking an
Zoey says...
- Ember also publishes its own native types compiled directly from its source code, as described
in this blog post. For now, we continue to use the
@types
packages by default for the sake of compatibility with EmberData, because EmberData is not yet compatible with Ember's native official types. However, if you do not use EmberData, we
highly recommend following the instructions in that blog post to switch to the native types, which are guaranteed to always be 100% correct and 100% up to date!
+
+ Ember also publishes its own native types compiled directly from its source code. For now, we continue to use the @types
packages in these guides for the sake of compatibility with EmberData, because the EmberData @types
packages are not compatible with Ember's native official types.
+
+
+ If you do not use EmberData, or if you use EmberData's alpha native types, we highly recommend following the instructions in this blog post to switch to the native types, which are guaranteed to always be 100% correct and 100% up to date!
+
diff --git a/guides/upgrading/current-edition/tracked-properties.md b/guides/upgrading/current-edition/tracked-properties.md
index e01386029..17a1be264 100644
--- a/guides/upgrading/current-edition/tracked-properties.md
+++ b/guides/upgrading/current-edition/tracked-properties.md
@@ -71,11 +71,8 @@ Tracked properties have subtler benefits as well:
to anything external to your class.
Most computed properties should be fairly straightforward to convert to tracked
-properties. It's important to note that in these new components, arguments are
-automatically tracked, but in classic components they are _not_. This is because
-arguments are put on the `args` hash, which is tracked
-property. Since they are assigned to arbitrary properties on classic components,
-they can't be instrumented ahead of time, so you must decorate them manually.
+properties. It's important to note that on `@glimmer/component`, arguments are
+automatically tracked, but in classic `@ember/component` they are not.
#### Plain Old JavaScript Objects (POJOs)
@@ -130,53 +127,50 @@ class Person {
}
```
-In some cases, if your usage of properties on POJOs is too dynamic, you may not
-be able to enumerate every single property that could be tracked. There could be
-a prohibitive number of possible properties, or there could be no way to know
-them in advance. In this case, it's recommended that you _reset_ the value
-wherever it is updated:
+Generally, you should try to create classes with their tracked properties
+enumerated and decorated with `@tracked`, instead of relying on dynamically
+created POJOs. In some cases however, if your usage of properties on POJOs is
+too dynamic, you may not be able to enumerate every single property that could
+be tracked. In this case, you can use `TrackedObject` from `tracked-built-ins`:
```js
-class SimpleCache {
- @tracked _cache = {};
+import { TrackedObject } from 'tracked-built-ins';
- set(key, value) {
- this._cache[key] = value;
+let obj = new TrackedObject({
+ a: 1,
+ b: 2,
+})
- // trigger an update
- this._cache = this._cache;
- }
-
- get(key) {
- return this._cache[key];
- }
-}
+// This change is tracked
+obj.c = 3;
```
-Triggering an update like this will cause any getters that used the `_cache` to
-recalculate. Note that we can use the `get` method to access the cache, and it
-will still push the `_cache` tracked property.
+All property reading and writing on this object is automatically tracked.
+`TrackedObject` is "shallowly" tracked. `obj.c = 4` would be tracked, but
+`obj.c.somethingDeeper = 5` would not be tracked unless you've also made sure
+that the contents of `obj.c` is itself another `TrackedObject`.
+
#### Arrays
-Arrays are another example of a type of object where you can't enumerate every
-possible value - after all, there are an infinite number of integers (though you
-_may_ run out of bits in your computer at some point!). Instead, you can
-continue to use `EmberArray`, which will continue to work with tracking and will
-cause any dependencies that use it to invalidate correctly.
+When you want to track the contents of an Array, you can use `TrackedArray` from
+`tracked-built-ins`:
```js
-import { A } from '@ember/array';
+import { TrackedArray } from 'tracked-built-ins';
class ShoppingList {
- items = A([]);
+ items = new TrackedArray([]);
addItem(item) {
- this.items.pushObject(item);
+ this.items.push(item);
}
}
```
+`TrackedArray` supports all the normal native `Array` methods, ensuring that
+their reads and writes are tracked.
+
### Backwards Compatibility
Tracked properties are fully backwards compatible with computed properties and