-
-
Notifications
You must be signed in to change notification settings - Fork 72
Add deprecation guides for ComputedProperties #1412
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--- | ||
title: Deprecate import alias from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`alias` from `@ember/object/computed` is deprecated. | ||
|
||
It created a second property that reflected another property's value. | ||
|
||
## Migration | ||
Prefer direct access to the original tracked state, or use a simple getter and setter. | ||
|
||
Before: | ||
```js | ||
import { alias } from '@ember/object/computed'; | ||
import { tracked } from '@glimmer/tracking'; | ||
|
||
class Person { | ||
@tracked firstName = 'Tom'; | ||
@alias('firstName') name; | ||
} | ||
``` | ||
|
||
After: | ||
```js | ||
import { tracked } from '@glimmer/tracking'; | ||
class Person { | ||
@tracked firstName = 'Tom'; | ||
get name() { return this.firstName; } | ||
set name(value) { this.firstName = value; } | ||
} | ||
``` | ||
If all call sites can use `firstName` directly, remove the alias entirely. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
--- | ||
title: Deprecate import and from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`and` from `@ember/object/computed` is deprecated. It previously produced the logical AND of dependent keys. | ||
|
||
## Migration | ||
Use a getter with a standard JavaScript boolean expression. | ||
|
||
Before: | ||
```js | ||
import { and } from '@ember/object/computed'; | ||
class Cart { | ||
items = []; | ||
user = null; | ||
@and('items.length', 'user.isLoggedIn') canCheckout; | ||
} | ||
``` | ||
After: | ||
```js | ||
class Cart { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs reactivity |
||
items = []; | ||
user = null; | ||
get canCheckout() { | ||
return this.items.length > 0 && this.user?.isLoggedIn; | ||
} | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
title: Deprecate import bool from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`bool` from `@ember/object/computed` is deprecated. It coerced the value of another property to a boolean. | ||
|
||
## Migration | ||
Use a getter wrapping `Boolean(...)` or `!!`. | ||
|
||
Before: | ||
```js | ||
import { bool } from '@ember/object/computed'; | ||
class State { | ||
selectedItem = null; | ||
@bool('selectedItem') hasSelection; | ||
} | ||
``` | ||
|
||
After: | ||
```js | ||
class State { | ||
selectedItem = null; | ||
get hasSelection() { return Boolean(this.selectedItem); } | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
--- | ||
title: Deprecate import ComputedProperty from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`ComputedProperty` (the default export of `@ember/object/computed`) is deprecated. It was the internal class backing classic computed properties. | ||
|
||
## Migration | ||
Do not construct or refer to `ComputedProperty` directly. Use native getters with `@tracked` state instead. | ||
|
||
Before: | ||
```js | ||
import ComputedProperty from '@ember/object/computed'; | ||
// rarely used directly | ||
``` | ||
After: Remove the import; refactor any custom meta-programming to simple getters. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think custom ComputedProperties weren't rare. |
||
|
||
There is no public replacement for the class itself; the concept is removed. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
--- | ||
title: Deprecate import dependentKeyCompat from @ember/object/compat | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`dependentKeyCompat` is deprecated. It provided backwards compatibility so tracked getters could participate in classic CP dependency chains. | ||
|
||
## Migration | ||
Remove all ComputedProperties that depend on this getter, then remove `@dependentKeyCompat`. | ||
|
||
Before: | ||
```js | ||
import { tracked } from '@glimmer/tracking'; | ||
import { computed } from '@ember/object'; | ||
import { dependentKeyCompat } from '@ember/object/compat'; | ||
class Person { | ||
@tracked firstName = 'Tom'; | ||
@tracked lastName = 'Dale'; | ||
@dependentKeyCompat get givenName() { return this.firstName; } | ||
@computed('givenName','lastName') get fullName() { return `${this.givenName} ${this.lastName}`; } | ||
} | ||
``` | ||
After: | ||
```js | ||
import { tracked } from '@glimmer/tracking'; | ||
class Person { | ||
@tracked firstName = 'Tom'; | ||
@tracked lastName = 'Dale'; | ||
get givenName() { return this.firstName; } | ||
get fullName() { return `${this.givenName} ${this.lastName}`; } | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
--- | ||
title: Deprecate import deprecatingAlias from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`deprecatingAlias` from `@ember/object/computed` is deprecated. It created an alias that emitted a deprecation when accessed. | ||
|
||
## Migration | ||
Remove the indirection and update callers to reference the canonical property. If you still need a deprecation message temporarily, implement a manual getter that logs once. | ||
|
||
Before (framework provided deprecation): | ||
```js | ||
import { deprecatingAlias } from '@ember/object/computed'; | ||
class Person { | ||
firstName = 'Tom'; | ||
@deprecatingAlias('firstName', { id: 'app.old-name', until: '7.0.0' }) givenName; | ||
} | ||
``` | ||
After (direct access): | ||
```js | ||
class Person { | ||
firstName = 'Tom'; | ||
} | ||
``` | ||
Optional transitional getter: | ||
```js | ||
import { deprecate } from '@ember/debug'; | ||
class Person { | ||
firstName = 'Tom'; | ||
get givenName() { | ||
deprecate('Usage of `givenName` is deprecated, use `firstNAme` instead.'); | ||
return this.firstName; | ||
} | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--- | ||
title: Deprecate import empty from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`empty` from `@ember/object/computed` is deprecated. It returned true when the dependent value was `null`, `undefined`, an empty string, or had length 0. | ||
|
||
## Migration | ||
Implement the check in a getter. | ||
|
||
Before: | ||
```js | ||
import { empty } from '@ember/object/computed'; | ||
class ListState { | ||
items = []; | ||
@empty('items') isEmpty; | ||
} | ||
``` | ||
After: | ||
```js | ||
import { isEmpty } from '@ember/utils'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
class ListState { | ||
items = []; | ||
get isEmpty() { return isEmpty(this.items); } | ||
} | ||
``` | ||
Combine with `!` for `notEmpty` replacement. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
--- | ||
title: Deprecate import equal from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`equal` from `@ember/object/computed` is deprecated. It compared a dependent key's value to a constant. | ||
|
||
## Migration | ||
Use a getter with a strict equality expression. | ||
|
||
Before: | ||
```js | ||
import { equal } from '@ember/object/computed'; | ||
class Person { | ||
role = 'admin'; | ||
@equal('role', 'admin') isAdmin; | ||
} | ||
``` | ||
|
||
After: | ||
```js | ||
class Person { | ||
role = 'admin'; | ||
get isAdmin() { | ||
return this.role === 'admin'; | ||
} | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
--- | ||
title: Deprecate import expandProperties from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`expandProperties` is deprecated. It expanded bracket / brace notation in classic CP dependent key strings. | ||
|
||
## Migration | ||
This is largely unneeded and there is no direct replacement. | ||
|
||
Before: | ||
```js | ||
import { expandProperties } from '@ember/object/computed'; | ||
expandProperties('user.{first,last}Name', (prop) => {/* ... */}); | ||
``` | ||
|
||
After: List properties explicitly: `user.firstName`, `user.lastName`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
--- | ||
title: Deprecate import gt from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`gt` (greater than) from `@ember/object/computed` is deprecated. | ||
|
||
## Migration | ||
Use a comparison inside a getter. | ||
|
||
Before: | ||
```js | ||
import { gt } from '@ember/object/computed'; | ||
class Score { | ||
value = 42; | ||
@gt('value', 10) isHigh; | ||
} | ||
``` | ||
|
||
After: | ||
```js | ||
class Score { | ||
value = 42; | ||
get isHigh() { | ||
return this.value > 10; | ||
} | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
title: Deprecate import gte from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`gte` (greater than or equal) from `@ember/object/computed` is deprecated. | ||
|
||
Before: | ||
```js | ||
import { gte } from '@ember/object/computed'; | ||
class Score { | ||
value = 42; | ||
@gte('value', 10) meetsThreshold; | ||
} | ||
``` | ||
|
||
After: | ||
```js | ||
class Score { | ||
value = 42; | ||
get meetsThreshold() { | ||
return this.value >= 10; | ||
} | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
title: Deprecate import lt from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`lt` (less than) from `@ember/object/computed` is deprecated. | ||
|
||
Before: | ||
```js | ||
import { lt } from '@ember/object/computed'; | ||
class Score { | ||
value = 5; | ||
@lt('value', 10) isLow; | ||
} | ||
``` | ||
|
||
After: | ||
```js | ||
class Score { | ||
value = 5; | ||
get isLow() { | ||
return this.value < 10; | ||
} | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
title: Deprecate import lte from @ember/object/computed | ||
until: 7.0.0 | ||
since: 6.0.0 | ||
--- | ||
|
||
`lte` (less than or equal) from `@ember/object/computed` is deprecated. | ||
|
||
Before: | ||
```js | ||
import { lte } from '@ember/object/computed'; | ||
class Score { | ||
value = 5; | ||
@lte('value', 10) withinLimit; | ||
} | ||
``` | ||
|
||
After: | ||
```js | ||
class Score { | ||
value = 5; | ||
get withinLimit() { | ||
return this.value <= 10; | ||
} | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alias
could point to a computed property, a getter, or really anything so this may need to describe how make sure they work going forward.