Skip to content

Commit d19ca1a

Browse files
authored
Merge pull request #1832 from rx-angular/feat/provide-render-strategies
feat: added provideRxRenderStrategies provider function
2 parents d12d2db + 9b5d345 commit d19ca1a

35 files changed

+367
-513
lines changed

apps/docs/docs/cdk/render-strategies/render-strategies.mdx

Lines changed: 68 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ title: 'Render strategies'
55
hide_title: true
66
---
77

8+
import Tabs from '@theme/Tabs';
9+
import TabItem from '@theme/TabItem';
10+
811
# @rx-angular/cdk/render-strategies
912

1013
[![npm](https://img.shields.io/npm/v/%40rx-angular%2Fcdk.svg)](https://www.npmjs.com/package/%40rx-angular%2Fcdk)
@@ -41,9 +44,9 @@ yarn add @rx-angular/cdk
4144
## Documentation
4245

4346
- [Render Strategies](https://rx-angular.io/docs/cdk/render-strategies)
44-
- [Strategies](https://rx-angular.io/docs/cdk/render-strategies/strategies)
45-
- [Basic Strategies](https://rx-angular.io/docs/cdk/render-strategies/strategies/basic-strategies)
46-
- [Concurrent-strategies](https://rx-angular.io/docs/cdk/render-strategies/strategies/concurrent-strategies)
47+
- [Strategies](https://rx-angular.io/docs/cdk/render-strategies/strategies)
48+
- [Basic Strategies](https://rx-angular.io/docs/cdk/render-strategies/strategies/basic-strategies)
49+
- [Concurrent-strategies](https://rx-angular.io/docs/cdk/render-strategies/strategies/concurrent-strategies)
4750

4851
## Render strategies
4952

@@ -172,81 +175,79 @@ By default the following configurations are set:
172175
- primaryStrategy: `normal`
173176
- patchZone: `true`
174177

175-
### Global
176-
177-
1. Module Import
178+
<Tabs>
179+
<TabItem value="appConfig" label="Configure in appConfig">
178180

179181
```typescript
180-
...
181-
import {RxRenderStrategiesConfig, RX_RENDER_STRATEGIES_CONFIG} from '@rx-angular/cdk/render-strategies';
182-
183-
const CUSTOM_RX_ANGULAR_CONFIG: RxRenderStrategiesConfig<string> = {
184-
primaryStrategy: 'global',
185-
patchZone: false
186-
}
182+
import { provideRxRenderStrategies } from '@rx-angular/cdk/render-strategies';
187183

188-
@Module({
184+
const appConfig: ApplicationConfig = {
189185
providers: [
190-
{
191-
provide: RX_RENDER_STRATEGIES_CONFIG,
192-
useValue: CUSTOM_RX_ANGULAR_CONFIG
193-
}
194-
]
195-
})
196-
export class AnyModule {
197-
198-
}
186+
// ... other providers
187+
provideRxRenderStrategies({
188+
primaryStrategy: 'userBlocking',
189+
patchZone: false,
190+
}),
191+
],
192+
};
199193
```
200194

201-
### Feature Module
195+
</TabItem>
196+
<TabItem value="ngModule" label="Configure in NgModules">
202197

203-
```typescript
204-
...
205-
import {RxRenderStrategiesConfig, RX_RENDER_STRATEGIES_CONFIG} from '@rx-angular/cdk/render-strategies';
198+
This can be done in any NgModule, AppModule or any feature module.
206199

207-
const FEATURE_RX_ANGULAR_CONFIG: RxRenderStrategiesConfig<string> = {
208-
primaryStrategy: 'global',
209-
patchZone: false
210-
}
200+
```typescript
201+
import { provideRxRenderStrategies } from '@rx-angular/cdk/render-strategies';
211202

212-
@Module({
203+
@NgModule({
213204
providers: [
214-
{
215-
provide: RX_RENDER_STRATEGIES_CONFIG,
216-
useValue: FEATURE_RX_ANGULAR_CONFIG
217-
}
218-
]
205+
provideRxRenderStrategies({
206+
primaryStrategy: 'global',
207+
patchZone: false,
208+
}),
209+
],
219210
})
220-
export class AnyFeatureModule {
221-
222-
}
211+
export class AnyModule {}
223212
```
224213

225-
### Component
214+
</TabItem>
215+
216+
<TabItem value="route" label="Configure at route level">
226217

227218
```typescript
228-
...
229-
import {RxRenderStrategiesConfig, RX_RENDER_STRATEGIES_CONFIG} from '@rx-angular/cdk/render-strategies';
219+
import { provideRxRenderStrategies } from '@rx-angular/cdk/render-strategies';
220+
221+
export const routes: Routes = [
222+
{
223+
path: 'any-route',
224+
component: AnyComponent,
225+
providers: [provideRxRenderStrategies({ primaryStrategy: 'userBlocking' })],
226+
children: [
227+
// ... any child routes
228+
],
229+
},
230+
];
231+
```
230232

231-
const COMPONENT_RX_ANGULAR_CONFIG: RxRenderStrategiesConfig<string> = {
232-
primaryStrategy: 'global',
233-
patchZone: false
234-
}
233+
</TabItem>
234+
235+
<TabItem value="component" label="Configure at component level">
236+
237+
```typescript
238+
import { provideRxRenderStrategies } from '@rx-angular/cdk/render-strategies';
235239

236240
@Component({
237241
selector: 'any-component',
238-
providers: [
239-
{
240-
provide: RX_RENDER_STRATEGIES_CONFIG,
241-
useValue: COMPONENT_RX_ANGULAR_CONFIG
242-
}
243-
]
242+
providers: [provideRxRenderStrategies({ primaryStrategy: 'userBlocking', patchZone: false })],
244243
})
245-
export class AnyComponent {
246-
247-
}
244+
export class AnyComponent {}
248245
```
249246

247+
</TabItem>
248+
249+
</Tabs>
250+
250251
## Usage
251252

252253
Render strategies can be used with the `StrategyProvider` or `Directive` like `push`, `rxLet` or `rxFor`.
@@ -273,18 +274,18 @@ In this case, we span an overlay with the `immediate` strategy to get the best U
273274
The reason for the strategy choice is primarily because user interaction needs to give feedback instantly to align with the user's expectations.
274275

275276
```typescript
277+
import { RxStrategyProvider } from '@rx-angular/cdk/render-strategies';
278+
276279
@Component({
277280
selector: 'any-component',
278281
template: ` ... `,
279282
})
280283
export class AnyComponent {
281-
constructor(
282-
public strategyProvider: RxStrategyProvider,
283-
public changeDetectorRef: ChangeDetectorRef
284-
) {}
284+
private strategyProvider = inject(RxStrategyProvider);
285+
private cdr = inject(ChangeDetectorRef);
285286

286287
openDialog() {
287-
this.strategyProvider.scheduleCD(this.changeDetectorRef, {
288+
this.strategyProvider.scheduleCD(this.cdr, {
288289
strategy: 'immediate',
289290
});
290291
}
@@ -334,26 +335,18 @@ In this case, we can use a low priority.
334335
Again, `RxStrategyProvider` needs to get imported, and the scheduling APIs needs to be used.
335336

336337
```typescript
337-
@Injectable({
338-
providedIn: 'root',
339-
})
338+
import { RxStrategyProvider } from '@rx-angular/cdk/render-strategies';
339+
340+
@Injectable({ providedIn: 'root' })
340341
export class AnyService {
341-
constructor(
342-
public strategyProvider: RxStrategyProvider,
343-
private apiService: ApiService
344-
) {}
342+
private strategyProvider = inject(RxStrategyProvider);
343+
private apiService = inject(ApiService);
345344

346345
getData() {
347-
this.strategyProvider
348-
.schedule(() => this.apiService.sendRequest(), { strategy: 'low' })
349-
.subscribe();
346+
this.strategyProvider.schedule(() => this.apiService.sendRequest(), { strategy: 'low' }).subscribe();
350347
}
351348
}
352349
```
353350

354351
> **⚠ Notice:**
355352
> The component that introduces the change does not know where in the template it sits. The whole template needs to be re-evaluated.
356-
357-
## Testing
358-
359-
@TODO

apps/docs/docs/cdk/render-strategies/strategies/concurrent-strategies.md

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,12 @@ Tooltips should be displayed immediately on mouse over. Any delay will be very n
198198
```typescript
199199
@Component({
200200
selector: 'item-image',
201-
template: ` <img [src]="src" (mouseenter)="showTooltip()" (mouseleave)="hideTooltip()" /> `,
201+
template: ` <img [src]="src()" (mouseenter)="showTooltip()" (mouseleave)="hideTooltip()" /> `,
202202
})
203203
export class ItemsListComponent {
204-
@Input() src: string;
204+
private strategyProvider = inject(RxStrategyProvider);
205205

206-
constructor(private strategyProvider: RxStrategyProvider) {}
206+
readonly src = input.required<string>();
207207

208208
showTooltip() {
209209
this.strategyProvider
@@ -257,22 +257,24 @@ Dropdowns should be displayed right away on user interaction.
257257
selector: 'item-dropdown',
258258
template: `
259259
<div id="collapse" (mouseenter)="showDropdown()" (mouseleave)="hideDropdown()">
260-
{{ text }}
260+
{{ text() }}
261261
</div>
262262
`,
263263
})
264264
export class DropdownComponent {
265-
@Input() text: string;
265+
private strategyProvider = inject(RxStrategyProvider);
266266

267-
constructor(private strategyProvider: RxStrategyProvider) {}
267+
readonly text = input.required<string>();
268268

269269
showDropdown() {
270-
this.strategyProvider.schedule(
271-
() => {
272-
// create dropdown
273-
},
274-
{ strategy: 'userBlocking' },
275-
);
270+
this.strategyProvider
271+
.schedule(
272+
() => {
273+
// create dropdown
274+
},
275+
{ strategy: 'userBlocking' },
276+
)
277+
.subscribe();
276278
}
277279

278280
hideDropdown() {
@@ -318,16 +320,15 @@ It is often the case that rendering of big lists blocks user interactions. In co
318320
selector: 'items-list',
319321
template: `
320322
<div id="items-list">
321-
<div *rxFor="let item of items$; strategy: 'normal'>
323+
<div *rxFor="let item of state.items$; strategy: 'normal'>
322324
<item-image [src]="item.image"></item-image>
323325
<item-dropdown [text]="item.text"></item-dropdown>
324326
</div>
325327
</div>
326328
`,
327329
})
328330
export class ItemsListComponent {
329-
items$ = this.state.items$;
330-
constructor(private state: StateService) {}
331+
protected state = inject(StateService);
331332
}
332333
```
333334

@@ -354,7 +355,7 @@ Good use case for this strategy will be lazy loading of the components. For exam
354355
selector: 'items-list',
355356
template: `
356357
<div id="items-list">
357-
<div *rxFor="let item of items$; strategy: 'normal'>
358+
<div *rxFor="let item of state.items$; strategy: 'normal'>
358359
<item-image [src]="item.image"></item-image>
359360
<item-dropdown [text]="item.text"></item-dropdown>
360361
</div>
@@ -364,12 +365,8 @@ Good use case for this strategy will be lazy loading of the components. For exam
364365
`,
365366
})
366367
export class ItemsListComponent {
367-
items$ = this.state.items$;
368-
369-
constructor(
370-
private state: StateService,
371-
private strategyProvider: RxStrategyProvider,
372-
) {}
368+
protected state = inject(StateService);
369+
private strategyProvider = inject(RxStrategyProvider);
373370

374371
openCreateItemPopup() {
375372
this.strategyProvider
@@ -410,7 +407,7 @@ This strategy is especially useful for logic meant to run in the background. Goo
410407
selector: 'items-list',
411408
template: `
412409
<div id="items-list">
413-
<div *rxFor="let item of items$; strategy: 'normal'>
410+
<div *rxFor="let item of state.items$; strategy: 'normal'>
414411
{{item.name}}
415412
</div>
416413
</div>
@@ -421,14 +418,12 @@ This strategy is especially useful for logic meant to run in the background. Goo
421418
`,
422419
})
423420
export class ItemsListComponent {
424-
items$ = this.state.items$;
425-
426-
constructor(
427-
private state: StateService,
428-
private strategyProvider: RxStrategyProvider,
429-
private webSocket: WebSocketService,
430-
) {
431-
this.items$.pipe(this.strategyProvider.scheduleWith((items) => this.webSocket.syncItems(items), { strategy: 'idle' })).subscribe();
421+
private strategyProvider = inject(RxStrategyProvider);
422+
private webSocket = inject(WebSocketService);
423+
protected state = inject(StateService);
424+
425+
constructor() {
426+
this.state.items$.pipe(this.strategyProvider.scheduleWith((items) => this.webSocket.syncItems(items), { strategy: 'idle' })).subscribe();
432427
}
433428

434429
openCreateItemPopup() {

0 commit comments

Comments
 (0)