-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added computedPrevious helper fn (#181)
- Loading branch information
Showing
8 changed files
with
168 additions
and
0 deletions.
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
docs/src/content/docs/utilities/Signals/computed-previous.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
--- | ||
title: computedPrevious | ||
description: ngxtension/computed-previous | ||
badge: stable | ||
contributor: enea-jahollari | ||
--- | ||
|
||
`computedPrevious` is a helper function that returns a `signal` that emits the previous value of the passed `signal`. It's useful when you want to keep track of the previous value of a signal. | ||
It will emit `null` as the previous value when the signal is first created. | ||
|
||
```ts | ||
import { computedPrevious } from 'ngxtension/computed-previous'; | ||
``` | ||
|
||
## Usage | ||
|
||
`computedPrevious` accepts a `Signal` and returns a `Signal` that emits the previous value of the passed `Signal`. | ||
|
||
```ts | ||
const a = signal(1); | ||
const b = computedPrevious(a); | ||
|
||
console.log(b()); // null | ||
|
||
a.set(2); | ||
console.log(b()); // 1 | ||
|
||
a.set(3); | ||
console.log(b()); // 2 | ||
``` | ||
|
||
## API | ||
|
||
```ts | ||
computedPrevious<T>(signal: Signal<T>): Signal<T | null> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# ngxtension/computed-previous | ||
|
||
Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/computed-previous`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"lib": { | ||
"entryFile": "src/index.ts" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"name": "ngxtension/computed-previous", | ||
"$schema": "../../../node_modules/nx/schemas/project-schema.json", | ||
"projectType": "library", | ||
"sourceRoot": "libs/ngxtension/computed-previous/src", | ||
"targets": { | ||
"test": { | ||
"executor": "@nx/jest:jest", | ||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"], | ||
"options": { | ||
"jestConfig": "libs/ngxtension/jest.config.ts", | ||
"testPathPattern": ["computed-previous"], | ||
"passWithNoTests": true | ||
}, | ||
"configurations": { | ||
"ci": { | ||
"ci": true, | ||
"codeCoverage": true | ||
} | ||
} | ||
}, | ||
"lint": { | ||
"executor": "@nx/eslint:lint", | ||
"outputs": ["{options.outputFile}"], | ||
"options": { | ||
"lintFilePatterns": [ | ||
"libs/ngxtension/computed-previous/**/*.ts", | ||
"libs/ngxtension/computed-previous/**/*.html" | ||
] | ||
} | ||
} | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
libs/ngxtension/computed-previous/src/computed-previous.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { Component, signal } from '@angular/core'; | ||
import { TestBed } from '@angular/core/testing'; | ||
import { computedPrevious } from './computed-previous'; | ||
|
||
describe(computedPrevious.name, () => { | ||
@Component({ standalone: true, template: '{{previous()}}' }) | ||
class Test { | ||
value = signal(0); | ||
previous = computedPrevious(this.value); | ||
} | ||
|
||
function setup() { | ||
const fixture = TestBed.createComponent(Test); | ||
fixture.detectChanges(); | ||
return fixture.componentInstance; | ||
} | ||
|
||
it('should work properly', () => { | ||
const cmp = setup(); | ||
|
||
expect(cmp.value()).toEqual(0); | ||
expect(cmp.previous()).toEqual(null); | ||
|
||
cmp.value.set(1); | ||
|
||
expect(cmp.value()).toEqual(1); | ||
expect(cmp.previous()).toEqual(0); | ||
|
||
cmp.value.set(2); | ||
|
||
expect(cmp.value()).toEqual(2); | ||
expect(cmp.previous()).toEqual(1); | ||
|
||
cmp.value.set(2); | ||
|
||
expect(cmp.value()).toEqual(2); | ||
expect(cmp.previous()).toEqual(1); | ||
|
||
cmp.value.set(3); | ||
|
||
expect(cmp.value()).toEqual(3); | ||
expect(cmp.previous()).toEqual(2); | ||
}); | ||
}); |
43 changes: 43 additions & 0 deletions
43
libs/ngxtension/computed-previous/src/computed-previous.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { computed, type Signal } from '@angular/core'; | ||
|
||
/** | ||
* Returns a signal that emits the previous value of the given signal. | ||
* The first time the signal is emitted, the previous value will be `null`. | ||
* | ||
* @example | ||
* ```ts | ||
* const value = signal(0); | ||
* const previous = computedPrevious(value); | ||
* | ||
* effect(() => { | ||
* console.log('Current value:', value()); | ||
* console.log('Previous value:', previous()); | ||
* }); | ||
* | ||
* Logs: | ||
* // Current value: 0 | ||
* // Previous value: null | ||
* | ||
* value.set(1); | ||
* | ||
* Logs: | ||
* // Current value: 1 | ||
* // Previous value: 0 | ||
*``` | ||
* @param s Signal to compute previous value for | ||
* @returns Signal that emits previous value of `s` | ||
*/ | ||
export function computedPrevious<T>(s: Signal<T>): Signal<T | null> { | ||
let current = null as T; | ||
let previous = null as T; | ||
|
||
return computed(() => { | ||
const value = s(); | ||
if (value !== current) { | ||
previous = current; | ||
current = value; | ||
} | ||
return previous; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './computed-previous'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters