Invoking a function in an Angular component through an event triggered by an external JS file

I'm in the process of converting a webpage that was originally designed using JS, HTML, and CSS into an Angular project. I have already included the JS file in index.html as shown below

index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Sample</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body class="">
<app-root></app-root>

<script type="text/javascript" src="assets/scripts/sample.js"></script>
</body>
</html>

sample.js

if (document.getElementById("fixedHeader")) {
    window.onscroll = function () { fixedHeader(); };
    var header = document.getElementById("fixedHeader");
    var fixed = header.offsetTop;
} 
function fixedHeader() {
    if (window.pageYOffset > fixed) {
        header.classList.add("fixed-active-lob");
        $('body').addClass("fixed-nav");
    } else {
        header.classList.remove("fixed-active-lob");
        $('body').removeClass("fixed-nav");
    }
}

current.component.html

<div class="gb-nav gn">
    <div id="fixedHeader" class="header">....
    </div>
</div>

sample.css File included in styles.css having

.gb-nav.gn .fixed-active-lob {
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 999999;
    -webkit-box-shadow: 0px 10px 15px -1px rgba(0,0,0,0.45);
    -moz-box-shadow: 0px 10px 15px -1px rgba(0,0,0,0.45);
    box-shadow: 0px 10px 15px -1px rgba(0,0,0,0.45);
}
body.fixed-nav{
    padding-top:56px
}

I encountered some issues trying to trigger the function from sample.js within the Angular component. However, I managed to achieve the desired result by redefining the same function in the

current.component.ts as:

@HostListener('window:scroll', ['$event'])
    scrollHandler(event: any) {
    console.log("Scroll event", event);
    this.fixedHeader();
    }
fixedHeader() {
    var header = document.getElementById("fixedHeader");
    var fixed: number = 0;
    if (header?.offsetTop != undefined) {
      fixed = header?.offsetTop;
    } else {
      fixed = 0;
    }
    if (window.pageYOffset > fixed) {
        header?.classList.add("fixed-active-lob");
        $('body').addClass("fixed-nav");
    } else {
        header?.classList.remove("fixed-active-lob");
        $('body').removeClass("fixed-nav");
    }
}

However, I would prefer to utilize the function from the JS file instead of duplicating it in the ts file, can anyone provide guidance on how to accomplish this?

Answer №1

Initially, update sample.js to export the function fixedHeader in the following manner:

if (document.getElementById("fixedHeader")) {
  window.onscroll = function () { fixedHeader(); };
  var header = document.getElementById("fixedHeader");
  var fixed = header.offsetTop;
}  

export function fixedHeader() {
  if (window.pageYOffset > fixed) {
    header.classList.add("fixed-active-lob");
    $('body').addClass("fixed-nav");
  } else {
    header.classList.remove("fixed-active-lob");
    $('body').removeClass("fixed-nav");
  }
} 

By making this adjustment, we have transformed sample.js into a module with a single export named fixedHeader, allowing other modules like current.component.ts to consume it more efficiently through JavaScript Modules.

Subsequently, add "allowJs": true to your project's tsconfig.json to signal TypeScript about the presence of both TypeScript and JavaScript source files within the project.

Afterward, directly import the fixedHeader function from sample.js into current.component.ts. Remove any redundant methods from the Angular component class and call the imported function as shown below:

 import {Component, HostListener} from '@angular/core';

 import {fixedHeader} from '../assets/scripts/sample.js';

 @Component({
   // Angular boilerplate and setup
 })
 export class CurrentComponent { // or the actual name
   @HostListener('window:scroll', ['$event'])
   scrollHandler(event: Event) {
     console.log("Scroll event", event);
  
     fixedHeader();
  }
}

Lastly, delete the script tag that initially loaded sample.js from index.html.

Note: Adjust the import path above according to the actual file locations relative to each other.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for continuously randomizing colors in p5.js

I recently began exploring p5.js and I have a query regarding color randomization. Currently, it seems that the color only changes randomly when I restart the code. Is there a way to trigger this randomization every time the mouse is clicked? Below is the ...

Transforming text into an image during an Ajax response

Currently, I am in the process of learning jQuery and experimenting with a list of hotels that have star ratings retrieved through an Ajax call. My goal is to transform these text-based ratings into images of stars, but I'm facing some difficulties in ...

The issue arises when TypeScript is unable to accurately infer the type as not being undefined following a type guard condition using

The following code snippet illustrates that in the else statement, it is evident that b cannot be undefined (a||b returns truthy and since a is falsy, b must be truthy). Why does Typescript show the error 'b' is possibly 'undefined', a ...

Mastering JQuery: Techniques for Managing Events Across Numerous Elements

My view page utilizes Ajax and JQuery to retrieve data from Codeigniter's controller, then presents it in HTML format. Below is the code for the Ajax post: $(document).ready(function(){ var fileId = 0; var wrapper = $("#preference"); ...

Resolve the issue with automatically generating SCSS type definitions (style.d.ts) for Preact within a TypeScript webpack setup

Utilizing webpack with Preact 10.x (nearly identical to React) and TypeScript in the VSCode environment. Following an update from Node version 12 to version 14, there seems to be a problem where *.scss files no longer automatically generate their correspo ...

Can you explain the mechanics behind the functionalities of @angular and @type dependencies?

This inquiry may have been raised before, but I couldn't uncover all the solutions. If that's the case, my apologies. I have a good grasp on how package.json and dependencies / dev-dependencies function in Node applications. Currently delving i ...

Error: HTMLAnchorElement.linkAction is attempting to access an undefined property 'add', resulting in an uncaught TypeError

Displaying the following: Error: Cannot read property 'add' of undefined at HTMLAnchorElement.linkAction const navigationLinks = document.querySelectorAll('.nav__link') function handleLinkAction(){ // Activate link navLin ...

Would you like to learn how to dynamically alter a button's color upon clicking it and revert it back to its original color upon clicking it again?

My Upvote button starts off transparent, but when I click on it, the background color changes to green. What I need is for the button to become transparent again when clicked a second time. I've attempted using the following code snippet: function ...

Detect the 'mousewheel' event on a container with a concealed overflow

Is there a way to capture the "mousewheel" event on a body with a hidden overflow? I attempted to follow the solution provided here, but unfortunately, it did not work in my situation. ...

Identifying route changes and new view replacements in Angular: A comprehensive guide

I'm currently trying to detect when a route changes and a new view (HTML) is replaced. I attempted the code below but I'm unsure of how to proceed from here. this._routerSub = this.router.events .filter(event => event instanceof Navigation ...

Using the readline function in JavaScript, a sequence of user inputs can be collected. These inputs can be linked to

Within my array var questions=[], I have stored multiple questions. Currently, I am using forEach to iterate through the array and prompt the user for input on each question, displaying the responses in the terminal. However, I am facing an issue where onl ...

There seems to be a problem with the external JavaScript file not functioning

After dragging and dropping the .js file into my ASP.NET project, I am facing an issue where it remains unresponsive, even though the code works fine when used inline. This problem is occurring while using VS 2017. Here is a snippet of my code: <scrip ...

Ensuring the Textbox Does Not Allow Zero as the Initial Digit: A Guide

What is the best way to validate a textbox so that the entered text does not start with zero? Zero can be entered anywhere else in the textbox. function checkFirst() { var text = document.getElementById('<%=textbox.ClientID %>').value ...

Guide on applying CSS to option tag within a select element in VUE.js

I am attempting to design a dropdown menu that resembles the one shown in the image. However, I'm currently unable to include any CSS styling. Can anyone provide guidance on how to create a customizable select dropdown in Vue? https://i.stack.imgur.c ...

How can I create an input field that comes with a preset value but can be updated by the user with a different name?

I am in need of a solution that will enable a user to update text on a webpage dynamically. I have been unable to find any information on how to achieve this. Is there anyone aware of a method to implement this feature? Perhaps a library or utilizing Vue ...

Particles.js fails to persist as I scroll down the HTML page

After creating a website page, I incorporated Particles.js for the background. However, when I scroll down, the particles seem to be confined to the initial corner of the screen and do not continue downward. Here are my current particle settings: #particl ...

Sending HTML content to viewChild in Angular 5

I'm struggling to figure out how to pass HTML to a ViewChild in order for it to be added to its own component's HTML. I've been searching for a solution with no luck so far. As a newcomer to Angular, many of the explanations I find online ar ...

Combining two JSON objects in JavaScript by matching key values and index positions

After numerous attempts using various methods, I am still unable to achieve the desired outcome. Even implementing nested ng-repeats in Angular to filter down to specific properties proved to be too resource-intensive. My objective is to retrieve the valu ...

Implementing CSS styles on selected elements using jQuery

My current HTML layout looks like this.. <div class="container> <div class="panel"> <div> <div> <div> <img class="match" src="myimage.jpg"> &l ...

Guide to direct express.js requests straight to 404 page

I need guidance on how to direct a request to a specific route in express.js directly to a 404 error page if the user is not authenticated. Currently, my middleware includes the following code: exports.isAuthenticated = function (req, res, next) { if ( ...