-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added inject params and inject query params
- Loading branch information
Showing
15 changed files
with
403 additions
and
0 deletions.
There are no files selected for viewing
57 changes: 57 additions & 0 deletions
57
docs/src/content/docs/utilities/Injectors/inject-params.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,57 @@ | ||
--- | ||
title: injectParams | ||
description: ngxtension/inject-params | ||
--- | ||
|
||
`injectParams` is a helper function that allows us to inject params from the current route as a signal. | ||
|
||
Having params as a signal helps in a modern angular signals based architecture. | ||
|
||
```ts | ||
import { injectParams } from 'ngxtension/inject-params'; | ||
``` | ||
|
||
## Usage | ||
|
||
`injectParams` when is called, returns a signal with the current route params. | ||
|
||
```ts | ||
@Component({ | ||
standalone: true, | ||
template: '<div>{{params() | json}}</div>', | ||
}) | ||
class TestComponent { | ||
params = injectParams(); | ||
} | ||
``` | ||
|
||
If we want to get the value for a specific param, we can pass the name of the param to `injectParams`. | ||
|
||
```ts | ||
@Component({ | ||
template: ` | ||
@if (user()) { | ||
<div>{{ user.name }}</div> | ||
} @else { | ||
<div>No user!</div> | ||
} | ||
`, | ||
}) | ||
class TestComponent { | ||
userId = injectParams('id'); // returns a signal with the value of the id param | ||
|
||
user = computedFrom( | ||
[this.userId], | ||
switchMap((id) => this.userService.getUser(id).pipe(startWith(null))) | ||
); | ||
} | ||
``` | ||
|
||
Or, if we want to transform the params, we can pass a function to `injectParams`. | ||
|
||
```ts | ||
@Component() | ||
class TestComponent { | ||
paramsKeys = injectParams((params) => Object.keys(params)); // returns a signal with the keys of the params | ||
} | ||
``` |
64 changes: 64 additions & 0 deletions
64
docs/src/content/docs/utilities/Injectors/inject-query-params.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,64 @@ | ||
--- | ||
title: injectQueryParams | ||
description: ngxtension/inject-query-params | ||
--- | ||
|
||
`injectQueryParams` is a helper function that allows us to inject query params from the current route as a signal. | ||
|
||
Having query params as a signal helps in a modern angular signals based architecture. | ||
|
||
```ts | ||
import { injectQueryParams } from 'ngxtension/inject-query-params'; | ||
``` | ||
|
||
## Usage | ||
|
||
`injectQueryParams` when is called, returns a signal with the current query params. | ||
|
||
```ts | ||
@Component({ | ||
standalone: true, | ||
template: '<div>{{queryParams() | json}}</div>', | ||
}) | ||
class TestComponent { | ||
queryParams = injectQueryParams(); | ||
} | ||
``` | ||
|
||
If we want to get the value for a specific query param, we can pass the name of the query param to `injectQueryParams`. | ||
|
||
```ts | ||
@Component({ | ||
template: ` | ||
Search results for: {{ searchParam() }} | ||
@for (user of filteredUsers()) { | ||
<div>{{ user.name }}</div> | ||
} @empty { | ||
<div>No users!</div> | ||
} | ||
`, | ||
}) | ||
class TestComponent { | ||
searchParam = injectQueryParams('search'); // returns a signal with the value of the search query param | ||
|
||
filteredUsers = computedFrom( | ||
[this.searchParam], | ||
switchMap((searchQuery) => this.userService.getUsers(searchQuery).pipe(startWith([]))) | ||
); | ||
} | ||
``` | ||
|
||
Or, if we want to transform the query params, we can pass a function to `injectQueryParams`. | ||
|
||
```ts | ||
@Component() | ||
class TestComponent { | ||
queryParamsKeys = injectQueryParams((params) => Object.keys(params)); // returns a signal with the keys of the query params | ||
|
||
allQueryParamsArePassed = computed(() => { | ||
const keys = this.queryParamsKeys(); | ||
return ['search', 'sort', 'page'].every((x) => keys.includes(x)); | ||
}); | ||
} | ||
``` |
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/inject-params | ||
|
||
Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-params`. |
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/inject-params", | ||
"$schema": "../../../node_modules/nx/schemas/project-schema.json", | ||
"projectType": "library", | ||
"sourceRoot": "libs/ngxtension/inject-params/src", | ||
"targets": { | ||
"test": { | ||
"executor": "@nx/jest:jest", | ||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"], | ||
"options": { | ||
"jestConfig": "libs/ngxtension/jest.config.ts", | ||
"testPathPattern": ["inject-params"], | ||
"passWithNoTests": true | ||
}, | ||
"configurations": { | ||
"ci": { | ||
"ci": true, | ||
"codeCoverage": true | ||
} | ||
} | ||
}, | ||
"lint": { | ||
"executor": "@nx/eslint:lint", | ||
"outputs": ["{options.outputFile}"], | ||
"options": { | ||
"lintFilePatterns": [ | ||
"libs/ngxtension/inject-params/**/*.ts", | ||
"libs/ngxtension/inject-params/**/*.html" | ||
] | ||
} | ||
} | ||
} | ||
} |
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 './inject-params'; |
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,37 @@ | ||
import { Component } from '@angular/core'; | ||
import { TestBed } from '@angular/core/testing'; | ||
|
||
import { provideRouter } from '@angular/router'; | ||
import { RouterTestingHarness } from '@angular/router/testing'; | ||
import { injectParams } from './inject-params'; | ||
|
||
describe(injectParams.name, () => { | ||
it('returns a signal everytime the route params change based on the param passed to the fn', async () => { | ||
TestBed.configureTestingModule({ | ||
providers: [ | ||
provideRouter([{ path: 'user/:id', component: UserProfileComponent }]), | ||
], | ||
}); | ||
|
||
const harness = await RouterTestingHarness.create(); | ||
|
||
const instance = await harness.navigateByUrl( | ||
'/user/angular', | ||
UserProfileComponent | ||
); | ||
|
||
expect(instance.params()).toEqual({ id: 'angular' }); | ||
expect(instance.userId()).toEqual('angular'); | ||
expect(instance.paramKeysList()).toEqual(['id']); | ||
}); | ||
}); | ||
|
||
@Component({ | ||
standalone: true, | ||
template: ``, | ||
}) | ||
export class UserProfileComponent { | ||
params = injectParams(); | ||
userId = injectParams('id'); | ||
paramKeysList = injectParams((params) => Object.keys(params)); | ||
} |
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,55 @@ | ||
import { assertInInjectionContext, inject, type Signal } from '@angular/core'; | ||
import { toSignal } from '@angular/core/rxjs-interop'; | ||
import { ActivatedRoute, type Params } from '@angular/router'; | ||
import { map } from 'rxjs'; | ||
|
||
/** | ||
* Injects the params from the current route. | ||
*/ | ||
export function injectParams(): Signal<Params>; | ||
|
||
/** | ||
* Injects the params from the current route and returns the value of the provided key. | ||
* @param key | ||
*/ | ||
export function injectParams(key: string): Signal<string | null>; | ||
|
||
/** | ||
* Injects the params from the current route and returns the result of the provided transform function. | ||
* @param transform | ||
*/ | ||
export function injectParams<T>(transform: (params: Params) => T): Signal<T>; | ||
|
||
/** | ||
* Injects the params from the current route. | ||
* If a key is provided, it will return the value of that key. | ||
* If a transform function is provided, it will return the result of that function. | ||
* Otherwise, it will return the entire params object. | ||
* | ||
* @example | ||
* const userId = injectParams('id'); // returns the value of the 'id' param | ||
* const userId = injectParams(p => p['id'] as string); // same as above but can be used with a custom transform function | ||
* const params = injectParams(); // returns the entire params object | ||
* | ||
* @param keyOrTransform OPTIONAL The key of the param to return, or a transform function to apply to the params object | ||
*/ | ||
export function injectParams<T>( | ||
keyOrTransform?: string | ((params: Params) => T) | ||
): Signal<T | Params | string | null> { | ||
assertInInjectionContext(injectParams); | ||
const route = inject(ActivatedRoute); | ||
const params = route.snapshot.params || {}; | ||
|
||
if (typeof keyOrTransform === 'function') { | ||
return toSignal(route.params.pipe(map(keyOrTransform)), { | ||
initialValue: keyOrTransform(params), | ||
}); | ||
} | ||
|
||
const getParam = (params: Params) => | ||
keyOrTransform ? params?.[keyOrTransform] ?? null : params; | ||
|
||
return toSignal(route.params.pipe(map(getParam)), { | ||
initialValue: getParam(params), | ||
}); | ||
} |
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/inject-query-params | ||
|
||
Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-query-params`. |
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/inject-query-params", | ||
"$schema": "../../../node_modules/nx/schemas/project-schema.json", | ||
"projectType": "library", | ||
"sourceRoot": "libs/ngxtension/inject-query-params/src", | ||
"targets": { | ||
"test": { | ||
"executor": "@nx/jest:jest", | ||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"], | ||
"options": { | ||
"jestConfig": "libs/ngxtension/jest.config.ts", | ||
"testPathPattern": ["inject-query-params"], | ||
"passWithNoTests": true | ||
}, | ||
"configurations": { | ||
"ci": { | ||
"ci": true, | ||
"codeCoverage": true | ||
} | ||
} | ||
}, | ||
"lint": { | ||
"executor": "@nx/eslint:lint", | ||
"outputs": ["{options.outputFile}"], | ||
"options": { | ||
"lintFilePatterns": [ | ||
"libs/ngxtension/inject-query-params/**/*.ts", | ||
"libs/ngxtension/inject-query-params/**/*.html" | ||
] | ||
} | ||
} | ||
} | ||
} |
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 './inject-query-params'; |
43 changes: 43 additions & 0 deletions
43
libs/ngxtension/inject-query-params/src/inject-query-params.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,43 @@ | ||
import { Component } from '@angular/core'; | ||
import { TestBed } from '@angular/core/testing'; | ||
|
||
import { provideRouter } from '@angular/router'; | ||
import { RouterTestingHarness } from '@angular/router/testing'; | ||
import { injectQueryParams } from './inject-query-params'; | ||
|
||
describe(injectQueryParams.name, () => { | ||
it('returns a signal everytime the query params change based on the param passed to the fn', async () => { | ||
TestBed.configureTestingModule({ | ||
providers: [ | ||
provideRouter([{ path: 'search', component: SearchComponent }]), | ||
], | ||
}); | ||
|
||
const harness = await RouterTestingHarness.create(); | ||
|
||
const instance = await harness.navigateByUrl( | ||
'/search?query=Angular', | ||
SearchComponent | ||
); | ||
|
||
expect(instance.queryParams()).toEqual({ query: 'Angular' }); | ||
expect(instance.searchParam()).toEqual('Angular'); | ||
expect(instance.paramKeysList()).toEqual(['query']); | ||
|
||
await harness.navigateByUrl('/search?query=IsCool!&id=2'); | ||
|
||
expect(instance.queryParams()).toEqual({ query: 'IsCool!', id: '2' }); | ||
expect(instance.searchParam()).toEqual('IsCool!'); | ||
expect(instance.paramKeysList()).toEqual(['query', 'id']); | ||
}); | ||
}); | ||
|
||
@Component({ | ||
standalone: true, | ||
template: ``, | ||
}) | ||
export class SearchComponent { | ||
queryParams = injectQueryParams(); | ||
searchParam = injectQueryParams('query'); | ||
paramKeysList = injectQueryParams((params) => Object.keys(params)); | ||
} |
Oops, something went wrong.