skip to Main Content

I am currently working on an Angular website and having been attempting to run ng build. When I run ng serve it works just fine but on running ng build it produces the following error:
error message

I believe the error is something to do with Angular’s optimization. Is there anything I need to change about how I access my html elements? For reference, here are the two components with the HTML and TS files below.

<div #container class="container">
    <h1 class="title">Alan's Portfolio</h1>
</div>
import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
import { PianoService } from './../piano.service'
import { Subscription } from 'rxjs'

@Component({
    selector: 'app-header',
    templateUrl: './header.component.html',
    styleUrls: ['./header.component.css'],
    standalone: true
})
export class HeaderComponent implements AfterViewInit{
    loadEventSub!: Subscription;

    @ViewChild('container') containerRef!: ElementRef;

    constructor(private lidService: PianoService) {
        
    }

    ngAfterViewInit() {
        this.loadEventSub = this.lidService.getLoadEvent().subscribe(() => {
            this.containerRef.nativeElement.classList.add('rotate');

        })
    }

}
<div #container class="container">
    <div #spacer class="spacer"></div>
    <h1 #loading class="loading">Loading Site</h1>
    <div class="loadingContainer">
        <div class="dot"></div>
        <div class="dot"></div>
        <div class="dot"></div>
        <div class="dot"></div>
    </div>
</div>

import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
import { PianoService } from './../piano.service'
import { Subscription } from 'rxjs'
import { NgStyle } from '@angular/common';

@Component({
    selector: 'app-title',
    templateUrl: './title.component.html',
    styleUrls: ['./title.component.css'],
    standalone: true,
    imports: [NgStyle]
})
export class TitleComponent implements AfterViewInit{
    titleFilter!: string;
    enteranceCursor!: string;
    loadEventSub!: Subscription;


    @ViewChild('loading') titleRef!: ElementRef;
    @ViewChild('container') containerRef!: ElementRef;
    


    constructor(private lidService:PianoService) {
        
    }



    ngAfterViewInit() {
        this.loadEventSub = this.lidService.getLoadEvent().subscribe(() => {
            this.containerRef.nativeElement.classList.add('slide');
        })
    }

   
}

I feel like the issue may be in the previous two files but in case it is need, here is the file where I use threejs, I do have to access the canvas html element.

<canvas #canvas id="threeJS-canvas"></canvas>
import { Component, OnInit, AfterViewInit, Renderer2, ViewChild, ElementRef } from '@angular/core';
import { PianoService } from './../piano.service'

import { Subscription } from 'rxjs'

import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { EXRLoader } from 'three/examples/jsm/loaders/EXRLoader';
import { Mesh } from 'three';

@Component({
    selector: 'app-keyboard',
    templateUrl: './keyboard.component.html',
    styleUrls: ['./keyboard.component.css'],
    standalone: true
})




export class KeyboardComponent implements OnInit, AfterViewInit{
    scene: THREE.Scene;
    canvas: HTMLElement | null;
    scene_loaded: boolean;

  
    constructor(private pianoService: PianoService) {
        this.scene = new THREE.Scene();
        this.canvas = null;
        this.scene_loaded = false;
        
    }

    private LoadEventSub!: Subscription;
    private manager!: THREE.LoadingManager;

    private canvasSizes!: any;
    private pianoRenderer!: THREE.WebGLRenderer;
    private siteRenderer!: Renderer2;
    
    private clips!: any;
    private lid_clip!: any;
    private lid_mixer!: THREE.AnimationMixer;
    private clip_names: string[] = []; private mixer!: THREE.AnimationMixer;
    private clock: THREE.Clock = new THREE.Clock();
    private INTERSECTED_ARRAY: any[] = [];
    
    private raycaster: THREE.Raycaster = new THREE.Raycaster();
    private pointer: THREE.Vector2 = new THREE.Vector2();
    private camera!: THREE.PerspectiveCamera;

    
    @ViewChild('canvas') canvasRef!: ElementRef;
    

    ngOnInit(): void {
        window.addEventListener('pointermove', this.onPointerMove);

        this.initFunctions();
        
    }

    ngAfterViewInit() {
        this.createCanvas();
        this.createPiano();
        console.log(this.scene);
        this.animate();
    }

    initFunctions( pianoService = this.pianoService ): void {
        this.LoadEventSub = this.pianoService.getLoadEvent().subscribe(() => {
            this.lidup();
        })

        this.manager = new THREE.LoadingManager();
        
        this.manager.onLoad = function ()  {
            setTimeout(() => {
                pianoService.sendLoadEvent();

            }, 2000); // Delay of 2000 milliseconds (2 seconds)
        }
    }

    createPiano(): void {
        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 1000);
        this.scene.add(this.camera);


        new EXRLoader( this.manager )
            .setPath('../../assets/')
            .load('dancing_hall_1k.exr', (texture) => {
            texture.mapping = THREE.EquirectangularReflectionMapping;
            this.scene.environment = texture;
        });


        this.createBase();
        this.createKeyboard();

        const light = new THREE.AmbientLight(0xfffada, 1);
        this.scene.add(light);

    }

    private createCanvas = () => {
        this.canvas = this.canvasRef.nativeElement;

        if (!this.canvas) { return };

        this.pianoRenderer = new THREE.WebGLRenderer({ antialias: true, canvas: this.canvas });

        this.pianoRenderer.setClearColor(0x000000, 1);
        const pmremGenerator = new THREE.PMREMGenerator(this.pianoRenderer);
        pmremGenerator.compileEquirectangularShader();

        this.pianoRenderer.toneMapping = THREE.ACESFilmicToneMapping;
        this.pianoRenderer.toneMappingExposure = 1;
        this.pianoRenderer.outputEncoding = THREE.sRGBEncoding;
    }

    private resizeCanvasToDisplaySize() {
        const canvas = this.pianoRenderer.domElement;

        const width = canvas.clientWidth;
        const height = canvas.clientHeight;
        if (canvas.width !== width || canvas.height !== height) {
            this.pianoRenderer.setSize(width, height, false);
            this.camera.aspect = width / height;
            this.camera.updateProjectionMatrix();
        }
    }


    private onPointerMove = (event: any) => {
        const rect = this.pianoRenderer.domElement.getBoundingClientRect();

        this.pointer.x = ((event.clientX - rect.left) / (rect.right - rect.left)) * 2 - 1;
        this.pointer.y = - ((event.clientY - rect.top) / (rect.bottom - rect.top)) * 2 + 1;
    }

    private animate = () => {
        this.resizeCanvasToDisplaySize();

        var delta = this.clock.getDelta();
        if (this.mixer) { this.mixer.update(delta) };
        if (this.lid_mixer) {
            this.lid_mixer.update(delta)
        };
        this.render();

        requestAnimationFrame(this.animate);


    }

    createBase(): void {
        new GLTFLoader()
            .setPath('../../assets/')
            .load('Piano.glb', (gltf) => {
                console.log("base")
                console.log(gltf)

                const object = gltf.scene
                const base = object.children[2]

                object.traverse((subObject) => {
                    if (subObject instanceof Mesh) {
                         subObject.material.envMapIntensity = 0;
                    }
                });

                console.log(base);

                this.lid_clip = gltf.animations[1];
                this.lid_mixer = new THREE.AnimationMixer(object);

                this.camera.position.x = base.position.x;
                this.camera.position.y = base.position.y + 184; 
                this.camera.position.z = base.position.z + 150; //160
                this.camera.lookAt(new THREE.Vector3(156, 0, -74));
                console.log(this.camera);
        
                this.scene.add(object);
            });
    }


    createKeyboard(): void {
        new GLTFLoader()
            .setPath('../../assets/')
            .load('Keyboard.glb', (gltf) => {
                console.log(gltf)

                this.clips = gltf.animations;
                this.clips.forEach((clip: { name: string; }) => {
                    this.clip_names.push(clip.name)
                });

                this.mixer = new THREE.AnimationMixer(gltf.scene);
                this.scene.add(gltf.scene);
                this.scene_loaded = true;

            },  (xhr) => {
                console.log((xhr.loaded / xhr.total * 100) + "% loaded")
                
               
            }, function (error) {
                console.error(error);
            });

        console.log(this.scene);
        console.log(this.camera);

        console.log(this.scene.children);
        console.log(this.clip_names)
    }


    

    private keydown(animation_name: string) {
        const clip_num = this.clip_names.indexOf(animation_name)
        const action = this.mixer.clipAction(this.clips[clip_num]);

        action.setLoop(THREE.LoopOnce, 1);
        action.paused = false;
        action.clampWhenFinished = true;
        action.timeScale = 1;

        action.play();
    }

    private keyup(animation_name: string) {
        const clip_num = this.clip_names.indexOf(animation_name)
        const action = this.mixer.clipAction(this.clips[clip_num]);

        action.setLoop(THREE.LoopOnce, 1);
        action.paused = false;
        action.clampWhenFinished = true;
        action.timeScale = -1;

        action.play();
    }

    private lidup(): void {
        const action = this.lid_mixer.clipAction(this.lid_clip);
        action.setLoop(THREE.LoopOnce, 1);
        action.clampWhenFinished = true;
        action.timeScale = 0.8;
        action.play();
    }
    

    private render = () => {
        this.pianoRenderer.render(this.scene, this.camera);


        if (this.scene_loaded) {
            this.intersectionCheck();
        }
    }


    // add checks for menu keys (tooltip??)

    private intersectionCheck() {
        var clip_num = 0;
        var intersected_name: string;

        this.raycaster.setFromCamera(this.pointer, this.camera);

        const intersected = this.raycaster.intersectObjects(this.scene.children)[0];

        try {
            // no  idea why this is needed. blender issue??
            // it works tho lol
            if (intersected.object.name == "A000") {
                intersected_name = "A000";
            }
            else if (intersected.object.name == "C001") {
                intersected_name = "C001"
            }

            else {
                intersected_name = intersected.object.parent?.name + "";

            }
        }
        catch {
            intersected_name = "Scene";
        }

        if (intersected_name.includes('#0')) {
            intersected_name = intersected_name.slice(0, 2) + "." + intersected_name.slice(2) + "Action"
        }
        else if (intersected_name.includes('0')) {
            intersected_name = intersected_name.slice(0, 1) + "." + intersected_name.slice(1) + "Action"
        }
        else {
            intersected_name += "Action"
        }

        if (this.INTERSECTED_ARRAY.length < 2) { this.INTERSECTED_ARRAY.push(intersected_name) }
        else {
            const prev_intersected = this.INTERSECTED_ARRAY[1]
            this.INTERSECTED_ARRAY = [prev_intersected, intersected_name];
        }

        if (this.INTERSECTED_ARRAY[0] != this.INTERSECTED_ARRAY[1]) {
            this.INTERSECTED_ARRAY.forEach((intersected) => {
                clip_num = this.clip_names.indexOf(intersected);
                if (clip_num != -1) {
                    if (this.INTERSECTED_ARRAY.indexOf(intersected) == 0) { this.keyup(intersected) }
                    else { this.keydown(intersected) }
                }
            });
        }
    }

}

Sorry for the long post, but I have looked for hours and have not found any solutions

2

Answers


  1. Chosen as BEST ANSWER

    Turns out it was an issue with update from Angular 15 to Angular 16. Moving the code to a new Angular 16 project solved the problem.


  2. First, make sure to check your terminal or console for any error messages. Angular typically provides informative error messages that can help pinpoint the problem.

    1. Clear Cache: Sometimes, cached files may interfere with the build process. Try running npm run clean or deleting the node_modules folder and then reinstalling dependencies.

    2. Disable AOT (Ahead-of-Time) Compilation: Temporarily disabling AOT compilation during the build process might help identify the problem. Use ng build --aot=false to test this.

    3. Try a Fresh Build: If none of the above steps work, create a new Angular project using the Angular CLI and see if the index.html generation works in the new project. This will help determine if the issue is specific to your project or a global problem.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search