Ref
Ref is a concept borrowed from React, but with a little twist. In THREE.js, it is common to mutate properties on an object rather than staying in the immutable lane that we're used to. And there are many sources that can mutate properties of the same object: THREE.js, Cannon.js (Physics engine), Animations (GSAP) etc...
With that, NGT decides to implement the Ref concept.
ViewChild
/ ContentChild
We can get a hold of an object on the template using the good ol' ViewChild
or ContentChild
@Component({
template: `<ngt-mesh #mesh />`,
})
export class SceneGraph {
@ViewChild('mesh', { static: true }) mesh!: ElementRef<Mesh>;
}
We can also use ViewChildren
/ ContentChildren
if we want to interact with the QueryList API
instead.
injectNgtRef()
More than often, we want to define an external Ref that we can pass around. To do so, we can use injectNgtRef()
function
to create a Ref.
@Component({
template: `<ngt-mesh />`,
})
export class SceneGraph {
readonly ref = injectNgtRef<Mesh>();
}
Then, we pass our ref
into the [ref]
Input on the element.
@Component({
template: `
<ngt-mesh [ref]="ref" />
`,
})
export class SceneGraph {
readonly ref = injectNgtRef();
}
The NGT Custom Renderer will assign the Mesh
object to the ref.nativeElement
when it is available. injectNgtRef()
returns an NgtInjectedRef<ObjectType>
.
type Subscribe<T> = (callback: (current: T, previous: T | null) => void) => Subscription;
export type NgtInjectedRef<T> = ElementRef<T> & {
/* a Subscribe fn that emits current and previous value. Useful for debug */
subscribe: Subscribe<T>;
/* consumers should use this for listening to value of this ref. This filters out initial null value */
$: Observable<T>;
/* consumers should use this for listenting to children changes on this ref */
children$: (type?: 'objects' | 'nonObjects' | 'both') => Observable<NgtInstanceNode[]>;
/* notify this CD when ref value changes */
useCDR: (cdr: ChangeDetectorRef) => void;
};