-
-
Notifications
You must be signed in to change notification settings - Fork 116
feat(utilities): add multiple injectors and documentation for enhance… #680
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,178 @@ | ||
| --- | ||
| title: injectElementBounding | ||
| description: ngxtension/inject-element-bounding | ||
| entryPoint: ngxtension/inject-element-bounding | ||
| badge: stable | ||
| contributors: ['enea-jahollari'] | ||
| --- | ||
|
|
||
| Reactive bounding box of an HTML element. This utility tracks the position and dimensions of an element, automatically updating when the element is resized, moved, or when the window is scrolled or resized. | ||
|
|
||
| ```ts | ||
| import { injectElementBounding } from 'ngxtension/inject-element-bounding'; | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| `injectElementBounding` accepts a signal that returns an `ElementRef` or `HTMLElement`, and optional configuration options. It returns an object containing reactive signals for all bounding box properties. | ||
|
|
||
| ```ts | ||
| import { Component, ElementRef, viewChild } from '@angular/core'; | ||
| import { injectElementBounding } from 'ngxtension/inject-element-bounding'; | ||
|
|
||
| @Component({ | ||
| selector: 'app-example', | ||
| standalone: true, | ||
| template: ` | ||
| <div #target class="box">Resize or scroll to see bounding box updates</div> | ||
| <div class="info"> | ||
| <p>Width: {{ bounding.width() }}px</p> | ||
| <p>Height: {{ bounding.height() }}px</p> | ||
| <p>Top: {{ bounding.top() }}px</p> | ||
| <p>Left: {{ bounding.left() }}px</p> | ||
| <p>Right: {{ bounding.right() }}px</p> | ||
| <p>Bottom: {{ bounding.bottom() }}px</p> | ||
| </div> | ||
| `, | ||
| }) | ||
| export class ExampleComponent { | ||
| target = viewChild<ElementRef<HTMLDivElement>>('target'); | ||
| bounding = injectElementBounding(this.target); | ||
| } | ||
| ``` | ||
|
|
||
| ### With Options | ||
|
|
||
| ```ts | ||
| @Component({ | ||
| selector: 'app-example', | ||
| standalone: true, | ||
| template: ` | ||
| <div #target>Content</div> | ||
| `, | ||
| }) | ||
| export class ExampleComponent { | ||
| target = viewChild<ElementRef<HTMLDivElement>>('target'); | ||
|
|
||
| bounding = injectElementBounding(this.target, { | ||
| reset: true, // Reset to 0 when element is removed | ||
| windowResize: true, // Listen to window resize events | ||
| windowScroll: true, // Listen to window scroll events | ||
| immediate: true, // Calculate immediately on mount | ||
| updateTiming: 'sync', // Update synchronously or on next frame | ||
| }); | ||
|
|
||
| constructor() { | ||
| effect(() => { | ||
| console.log('Element width:', this.bounding.width()); | ||
| console.log('Element position:', { | ||
| x: this.bounding.x(), | ||
| y: this.bounding.y(), | ||
| }); | ||
| }); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### With Raw HTMLElement | ||
|
|
||
| You can also use raw `HTMLElement` instead of `ElementRef`: | ||
|
|
||
| ```ts | ||
| @Component({ | ||
| selector: 'app-example', | ||
| standalone: true, | ||
| template: ` | ||
| <div #target>Content</div> | ||
| `, | ||
| }) | ||
| export class ExampleComponent { | ||
| target = viewChild<ElementRef<HTMLDivElement>>('target'); | ||
| elementSignal = signal<HTMLElement | null>(null); | ||
|
|
||
| bounding = injectElementBounding(this.elementSignal); | ||
|
|
||
| ngAfterViewInit() { | ||
| const el = this.target()?.nativeElement; | ||
| if (el) { | ||
| this.elementSignal.set(el); | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Manual Updates | ||
|
|
||
| The returned object includes an `update()` function for manual recalculation: | ||
|
|
||
| ```ts | ||
| @Component({ | ||
| selector: 'app-example', | ||
| standalone: true, | ||
| template: ` | ||
| <div #target>Content</div> | ||
| <button (click)="refresh()">Refresh Bounding Box</button> | ||
| `, | ||
| }) | ||
| export class ExampleComponent { | ||
| target = viewChild<ElementRef<HTMLDivElement>>('target'); | ||
| bounding = injectElementBounding(this.target); | ||
|
|
||
| refresh() { | ||
| this.bounding.update(); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## API | ||
|
|
||
| ```ts | ||
| function injectElementBounding( | ||
| target: Signal<ElementRef<HTMLElement> | HTMLElement | null | undefined>, | ||
| options?: InjectElementBoundingOptions, | ||
| ): InjectElementBoundingReturn; | ||
| ``` | ||
|
|
||
| ### Parameters | ||
|
|
||
| - `target`: A signal that returns an `ElementRef`, `HTMLElement`, or `null/undefined` | ||
| - `options` (optional): Configuration object with the following properties: | ||
| - `injector`: An `Injector` instance for dependency injection | ||
| - `reset`: Reset values to 0 when element is removed (default: `true`) | ||
| - `windowResize`: Listen to window resize events (default: `true`) | ||
| - `windowScroll`: Listen to window scroll events (default: `true`) | ||
| - `immediate`: Calculate bounding box immediately on mount (default: `true`) | ||
| - `updateTiming`: When to recalculate - `'sync'` for immediate or `'next-frame'` for next animation frame (default: `'sync'`) | ||
|
|
||
| ### Returns | ||
|
|
||
| An object with the following readonly signal properties: | ||
|
|
||
| - `height`: Signal containing the element's height in pixels | ||
| - `width`: Signal containing the element's width in pixels | ||
| - `top`: Signal containing the distance from the element's top edge to the viewport top | ||
| - `left`: Signal containing the distance from the element's left edge to the viewport left | ||
| - `right`: Signal containing the distance from the element's right edge to the viewport left | ||
| - `bottom`: Signal containing the distance from the element's bottom edge to the viewport top | ||
| - `x`: Signal containing the element's x coordinate (same as `left`) | ||
| - `y`: Signal containing the element's y coordinate (same as `top`) | ||
| - `update`: Function to manually trigger a recalculation of the bounding box | ||
|
|
||
| ## How it Works | ||
|
|
||
| `injectElementBounding` uses several browser APIs to track element bounds: | ||
|
|
||
| 1. **ResizeObserver**: Detects when the element's size changes | ||
| 2. **MutationObserver**: Watches for changes to the element's `style` and `class` attributes | ||
| 3. **Window Events**: Optionally listens to `scroll` and `resize` events on the window | ||
| 4. **getBoundingClientRect()**: Calculates the actual bounding box values | ||
|
|
||
| All observers and event listeners are automatically cleaned up when the component is destroyed. | ||
|
|
||
| ## Use Cases | ||
|
|
||
| - Creating tooltips or popovers that need to position relative to an element | ||
| - Implementing sticky headers or scroll-triggered animations | ||
| - Building responsive components that react to their own size changes | ||
| - Tracking element visibility and position for analytics | ||
| - Creating drag-and-drop interfaces with accurate collision detection | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,200 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: injectElementSize | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: ngxtension/inject-element-size | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| entryPoint: ngxtension/inject-element-size | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| badge: stable | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| contributors: ['enea-jahollari'] | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| Reactive size of an HTML element using ResizeObserver. This injector automatically tracks the width and height of an element and updates signals whenever the element is resized. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { injectElementSize } from 'ngxtension/inject-element-size'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Usage | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| `injectElementSize` accepts a target element reference (either an `ElementRef` or a `Signal<ElementRef>`) and optional configuration options. It returns an object containing readonly signals for `width` and `height` that automatically update when the element size changes. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Basic Example | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Component, ElementRef, viewChild } from '@angular/core'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { injectElementSize } from 'ngxtension/inject-element-size'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Component({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| selector: 'app-element-size', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| standalone: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| template: ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| #resizableElement | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| style="resize: both; overflow: auto; width: 200px; height: 150px; border: 1px solid;" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Resize me! | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p>Width: {{ size.width() }}px</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p>Height: {{ size.height() }}px</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| `, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class ElementSizeComponent { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| resizableElement = viewChild<ElementRef>('resizableElement'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| size = injectElementSize(this.resizableElement); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### With Initial Size | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| You can provide an initial size that will be used before the ResizeObserver initializes: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Component, ElementRef, viewChild } from '@angular/core'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { injectElementSize } from 'ngxtension/inject-element-size'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Component({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| selector: 'app-element-size', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| template: ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div #myElement>Content</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p>Width: {{ size.width() }}px</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p>Height: {{ size.height() }}px</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| `, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+53
to
+60
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. The
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class ElementSizeComponent { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| myElement = viewChild<ElementRef>('myElement'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| size = injectElementSize(this.myElement, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| initialSize: { width: 100, height: 100 }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Different Box Models | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| The `box` option allows you to specify which box model to use for measurements: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Component, ElementRef, viewChild } from '@angular/core'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { injectElementSize } from 'ngxtension/inject-element-size'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Component({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| selector: 'app-element-size', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| standalone: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| template: ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div #myElement style="padding: 20px; border: 5px solid;">Content</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p>Content Box - Width: {{ contentBoxSize.width() }}px</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p>Border Box - Width: {{ borderBoxSize.width() }}px</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| `, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class ElementSizeComponent { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| myElement = viewChild<ElementRef>('myElement'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Only measures the content area | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| contentBoxSize = injectElementSize(this.myElement, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| box: 'content-box', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Includes padding and border | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| borderBoxSize = injectElementSize(this.myElement, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| box: 'border-box', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Using with Dynamic Elements | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| When working with elements that may not be immediately available, you can pass a signal: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Component, ElementRef, signal } from '@angular/core'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { injectElementSize } from 'ngxtension/inject-element-size'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Component({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| selector: 'app-dynamic-element', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| standalone: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| template: ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| @if (showElement()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div #dynamicElement>Dynamic Content</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <button (click)="toggleElement()">Toggle Element</button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p>Width: {{ size.width() }}px</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p>Height: {{ size.height() }}px</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| `, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class DynamicElementComponent { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| showElement = signal(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| elementRef = signal<ElementRef | undefined>(undefined); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| size = injectElementSize(this.elementRef, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| initialSize: { width: 0, height: 0 }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| toggleElement() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.showElement.update((v) => !v); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+123
to
+134
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 example for dynamic elements is non-functional because the Also,
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### SVG Elements | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| The injector properly handles SVG elements by using `getBoundingClientRect()`: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Component, ElementRef, viewChild } from '@angular/core'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { injectElementSize } from 'ngxtension/inject-element-size'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Component({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| selector: 'app-svg-size', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| standalone: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| template: ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <svg #svgElement width="200" height="100"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <rect width="100%" height="100%" fill="blue" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| </svg> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p>SVG Width: {{ size.width() }}px</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p>SVG Height: {{ size.height() }}px</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| `, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class SVGSizeComponent { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| svgElement = viewChild<ElementRef>('svgElement'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| size = injectElementSize(this.svgElement); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## API | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```ts | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| function injectElementSize( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| target: ElementRef<HTMLElement> | Signal<ElementRef<HTMLElement> | undefined>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| options?: InjectElementSizeOptions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): Readonly<ElementSizeState>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Parameters | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `target`: The target element to observe. Can be: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `ElementRef<HTMLElement>`: A static element reference | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `Signal<ElementRef<HTMLElement> | undefined>`: A signal containing an element reference (useful for dynamic elements) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `options` (optional): An object that can have the following properties: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `initialSize`: The initial size of the element (default: `{ width: 0, height: 0 }`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `box`: The box model to use for ResizeObserver (default: `'content-box'`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `'content-box'`: Only the content area | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `'border-box'`: Content + padding + border | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `'device-pixel-content-box'`: Content in device pixels | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `window`: A custom `Window` instance, defaulting to the global `window` object | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `injector`: An `Injector` instance for Angular's dependency injection | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Returns | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| A readonly object with the following properties: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `width`: A readonly signal that emits the current width of the element in pixels | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `height`: A readonly signal that emits the current height of the element in pixels | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Notes | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - The injector uses the native `ResizeObserver` API, which is supported in all modern browsers | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - The signals are readonly to prevent external modifications | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - The ResizeObserver is automatically cleaned up when the component is destroyed | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - For SVG elements, the injector uses `getBoundingClientRect()` to get accurate dimensions | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - When the target element is not available (undefined), the signals will use the `initialSize` values | ||||||||||||||||||||||||||||||||||||||||||||||||||||
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.
This example uses
signaland thengAfterViewInitlifecycle hook, but the code snippet doesn't show the import forsignalor the class implementingAfterViewInit. For clarity and correctness, please update the example to include these.