Skip to content

Commit 2c27890

Browse files
committed
feat: try using ref directive
1 parent 81ddb3a commit 2c27890

File tree

6 files changed

+82
-34
lines changed

6 files changed

+82
-34
lines changed

libs/angular-three/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from './lib/di/catalogue';
44
export * from './lib/di/destroy';
55
export * from './lib/di/ref';
66
export * from './lib/directives/args';
7+
export * from './lib/directives/ref';
78
export * from './lib/directives/repeat';
89
export * from './lib/loader';
910
export * from './lib/loop';
Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
1-
import { Directive, EmbeddedViewRef, inject, Input, TemplateRef, ViewContainerRef } from '@angular/core';
1+
import { Directive, Input } from '@angular/core';
2+
import { NgtCommonDirective } from './common';
23

34
@Directive({ selector: '[args]', standalone: true })
4-
export class NgtArgs {
5-
private readonly vcr = inject(ViewContainerRef);
6-
private readonly template = inject(TemplateRef);
7-
8-
constructor() {
9-
const commentNode = this.vcr.element.nativeElement;
10-
if (commentNode['__ngt_renderer_add_comment__']) {
11-
commentNode['__ngt_renderer_add_comment__']();
12-
delete commentNode['__ngt_renderer_add_comment__'];
13-
}
14-
}
15-
5+
export class NgtArgs extends NgtCommonDirective {
166
private injectedArgs: any[] = [];
17-
private injected = false;
18-
private view?: EmbeddedViewRef<unknown>;
197

208
@Input() set args(args: any[] | null) {
219
if (args == null || !Array.isArray(args)) return;
@@ -36,12 +24,4 @@ export class NgtArgs {
3624
validate() {
3725
return !this.injected && !!this.injectedArgs.length;
3826
}
39-
40-
private createView() {
41-
if (this.view && !this.view.destroyed) {
42-
this.view.destroy();
43-
}
44-
this.view = this.vcr.createEmbeddedView(this.template);
45-
this.view.detectChanges();
46-
}
4727
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Directive, EmbeddedViewRef, inject, TemplateRef, ViewContainerRef } from '@angular/core';
2+
3+
@Directive()
4+
export abstract class NgtCommonDirective {
5+
protected readonly vcr = inject(ViewContainerRef);
6+
protected readonly template = inject(TemplateRef);
7+
8+
protected injected = false;
9+
protected shouldCreateView = true;
10+
private view?: EmbeddedViewRef<unknown>;
11+
12+
constructor() {
13+
const commentNode = this.vcr.element.nativeElement;
14+
if (commentNode['__ngt_renderer_add_comment__']) {
15+
commentNode['__ngt_renderer_add_comment__']();
16+
delete commentNode['__ngt_renderer_add_comment__'];
17+
}
18+
}
19+
20+
abstract validate(): boolean;
21+
22+
protected createView() {
23+
if (this.shouldCreateView) {
24+
if (this.view && !this.view.destroyed) {
25+
this.view.destroy();
26+
}
27+
this.view = this.vcr.createEmbeddedView(this.template);
28+
this.view.detectChanges();
29+
}
30+
}
31+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Directive, Input } from '@angular/core';
2+
import { NgtInjectedRef } from '../di/ref';
3+
import { NgtCommonDirective } from './common';
4+
5+
@Directive({ selector: '[ref]', standalone: true })
6+
export class NgtRef<T> extends NgtCommonDirective {
7+
private injectedRef?: NgtInjectedRef<T>;
8+
9+
@Input() set ref(ref: NgtInjectedRef<T> | null) {
10+
if (!ref || ref == null) return;
11+
this.injected = false;
12+
this.injectedRef = ref;
13+
this.createView();
14+
}
15+
16+
get ref(): NgtInjectedRef<T> | null {
17+
if (this.validate()) {
18+
this.injected = true;
19+
return this.injectedRef as NgtInjectedRef<T>;
20+
}
21+
return null;
22+
}
23+
24+
override validate(): boolean {
25+
return !this.injected && !!this.injectedRef && !this.injectedRef.nativeElement;
26+
}
27+
}

libs/angular-three/src/lib/renderer/renderer.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export class NgtRenderer implements Renderer2 {
105105
);
106106
}
107107

108-
const { injectedArgs, store } = this.store.getCreationState();
108+
const { injectedArgs, injectedRef, store } = this.store.getCreationState();
109109

110110
// handle primitive
111111
if (name === SPECIAL_DOM_TAG.NGT_PRIMITIVE) {
@@ -117,7 +117,9 @@ export class NgtRenderer implements Renderer2 {
117117
localState = getLocalState(object);
118118
}
119119
if (!localState.store) localState.store = store;
120-
return this.store.createNode('three', object);
120+
const primitiveNode = this.store.createNode('three', object);
121+
if (injectedRef) injectedRef.nativeElement = primitiveNode;
122+
return primitiveNode;
121123
}
122124

123125
const threeTag = name.startsWith('ngt') ? name.slice(4) : name;
@@ -134,6 +136,11 @@ export class NgtRenderer implements Renderer2 {
134136
localState.attach = ['material'];
135137
}
136138

139+
if (injectedRef) {
140+
injectedRef.nativeElement = node;
141+
node.__ngt_renderer__[NgtRendererClassId.ref] = injectedRef;
142+
}
143+
137144
return node;
138145
}
139146

libs/angular-three/src/lib/renderer/state.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { ChangeDetectorRef, getDebugNode, Injector, Type } from '@angular/core';
22
import { NgtArgs } from '../directives/args';
3+
import { NgtCommonDirective } from '../directives/common';
4+
import { NgtRef } from '../directives/ref';
35
import { NgtStore } from '../stores/store';
46
import type { NgtAnyRecord } from '../types';
57
import { applyProps } from '../utils/apply-props';
68
import { getLocalState } from '../utils/instance';
7-
import { is } from '../utils/is';
89
import { NgtCompoundClassId, NgtQueueOpClassId, NgtRendererClassId } from './enums';
910
import { attachThreeChild, removeThreeChild, SPECIAL_PROPERTIES } from './utils';
1011

@@ -210,11 +211,11 @@ export class NgtRendererStore {
210211
if (node.__ngt_renderer__[NgtRendererClassId.destroyed]) return;
211212
// setup [ref] here
212213
// ref should never change
213-
if (name === SPECIAL_PROPERTIES.REF && is.ref(value)) {
214-
node.__ngt_renderer__[NgtRendererClassId.ref] = value;
215-
value.nativeElement = node;
216-
return;
217-
}
214+
// if (name === SPECIAL_PROPERTIES.REF && is.ref(value)) {
215+
// node.__ngt_renderer__[NgtRendererClassId.ref] = value;
216+
// value.nativeElement = node;
217+
// return;
218+
// }
218219

219220
const parent = getLocalState(node).parent || node.__ngt_renderer__[NgtRendererClassId.parent];
220221

@@ -318,8 +319,9 @@ export class NgtRendererStore {
318319

319320
getCreationState() {
320321
const injectedArgs = this.firstNonInjectedDirective(NgtArgs)?.args || [];
322+
const injectedRef = this.firstNonInjectedDirective(NgtRef)?.ref || null;
321323
const store = this.tryGetPortalStore();
322-
return { injectedArgs, store };
324+
return { injectedArgs, injectedRef, store };
323325
}
324326

325327
destroy(node: NgtRendererNode, parent?: NgtRendererNode) {
@@ -405,8 +407,8 @@ export class NgtRendererStore {
405407
}
406408
}
407409

408-
private firstNonInjectedDirective(dir: Type<NgtArgs>) {
409-
let directive: NgtArgs | undefined;
410+
private firstNonInjectedDirective<T extends NgtCommonDirective>(dir: Type<T>) {
411+
let directive: T | undefined;
410412

411413
let i = this.comments.length - 1;
412414
while (i >= 0) {

0 commit comments

Comments
 (0)