|
3 | 3 | title: Ref
|
4 | 4 | sidebar_label: Ref
|
5 | 5 | ---
|
| 6 | + |
| 7 | +Ref is a concept borrowed from [React](https://beta.reactjs.org/learn/referencing-values-with-refs), but with a little twist. |
| 8 | +In THREE.js, it is common to mutate properties on an object rather than staying in the immutable lane that we're used to. |
| 9 | +And there are many sources that can mutate properties of the same object: THREE.js, Cannon.js (Physics engine), Animations (GSAP) etc... |
| 10 | + |
| 11 | +With that, NGT decides to implement the Ref concept. |
| 12 | + |
| 13 | +## `ViewChild` / `ContentChild` |
| 14 | + |
| 15 | +We can get a hold of an object on the template using the good ol' `ViewChild` or `ContentChild` |
| 16 | + |
| 17 | +```ts |
| 18 | +@Component({ |
| 19 | + template: `<ngt-mesh #mesh />`, |
| 20 | +}) |
| 21 | +export class SceneGraph { |
| 22 | + @ViewChild('mesh', { static: true }) mesh!: ElementRef<Mesh>; |
| 23 | +} |
| 24 | +``` |
| 25 | + |
| 26 | +We can also use `ViewChildren` / `ContentChildren` if we want to interact with the [QueryList API](https://angular.io/api/core/QueryList) |
| 27 | +instead. |
| 28 | + |
| 29 | +## `injectNgtRef()` |
| 30 | + |
| 31 | +More than often, we want to define an **external** Ref that we can pass around. To do so, we can use `injectNgtRef()` function |
| 32 | +to create a Ref. |
| 33 | + |
| 34 | +```ts |
| 35 | +@Component({ |
| 36 | + template: `<ngt-mesh />`, |
| 37 | +}) |
| 38 | +export class SceneGraph { |
| 39 | + // highlight-next-line |
| 40 | + readonly ref = injectNgtRef<Mesh>(); |
| 41 | +} |
| 42 | +``` |
| 43 | + |
| 44 | +Then, we pass our `ref` into the `[ref]` Input on the element. |
| 45 | + |
| 46 | +```ts |
| 47 | +@Component({ |
| 48 | + template: ` |
| 49 | + // highlight-next-line |
| 50 | + <ngt-mesh [ref]="ref" /> |
| 51 | + `, |
| 52 | +}) |
| 53 | +export class SceneGraph { |
| 54 | + readonly ref = injectNgtRef(); |
| 55 | +} |
| 56 | +``` |
| 57 | + |
| 58 | +The NGT Custom Renderer will assign the `Mesh` object to the `ref.nativeElement` when it is available. `injectNgtRef()` |
| 59 | +returns an `NgtInjectedRef<ObjectType>`. |
| 60 | + |
| 61 | +```ts |
| 62 | +type Subscribe<T> = (callback: (current: T, previous: T | null) => void) => Subscription; |
| 63 | + |
| 64 | +export type NgtInjectedRef<T> = ElementRef<T> & { |
| 65 | + /* a Subscribe fn that emits current and previous value. Useful for debug */ |
| 66 | + subscribe: Subscribe<T>; |
| 67 | + /* consumers should use this for listening to value of this ref. This filters out initial null value */ |
| 68 | + $: Observable<T>; |
| 69 | + /* consumers should use this for listenting to children changes on this ref */ |
| 70 | + children$: (type?: 'objects' | 'nonObjects' | 'both') => Observable<NgtInstanceNode[]>; |
| 71 | + /* notify this CD when ref value changes */ |
| 72 | + useCDR: (cdr: ChangeDetectorRef) => void; |
| 73 | +}; |
| 74 | +```title |
0 commit comments