How to smoothly transition between different components in Angular 2 with scroll actions

I am looking to dynamically change components based on user scrolling. Here is the behavior I want to achieve:

  • When the user reaches the end of a component, the next component should load
  • When the user reaches the top of a component, the previous component should load
  • Each component should have its own router link/path

For example, if there are two components (ComponentA and ComponentB) with paths "/a" and "/b" respectively, they should be loaded inside a parent/wrapper component

I am currently working on detecting these changes in the parent component

import { Component, HostListener, ElementRef, Output, EventEmitter, OnInit } from '@angular/core';
import { Router } from "@angular/router"


@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit  {


  @Output() mouseWheelUp = new EventEmitter();
  @Output() mouseWheelDown = new EventEmitter();

  @HostListener('mousewheel', ['$event']) onMouseWheelChrome(event: any) {
    this.mouseWheelFunc(event);
  }
  @HostListener('DOMMouseScroll', ['$event']) onMouseWheelFirefox(event: any) {
    this.mouseWheelFunc(event);
  }
  @HostListener('onmousewheel', ['$event']) onMouseWheelIE(event: any) {
    this.mouseWheelFunc(event);
  }

  ngOnInit() {
  }

  mouseWheelFunc(event: any) {
    let currentScrollPos = window.pageYOffset;
    let elemStartsAt = this.ref.nativeElement.offsetTop;
    var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));
    if(delta > 0) {
        console.log("Up "+currentScrollPos+" "+elemStartsAt);
    } else if(delta < 0) {
        console.log("Down"+currentScrollPos+" "+elemStartsAt);

    }
  }

  constructor(private router : Router) {}

}

Answer №1

Success! I found the answer

Here is the parent component HTML

<router-outlet></router-outlet>

And this is the parent component's TS

import { Component, HostListener, ElementRef, Output, EventEmitter, OnInit } from '@angular/core';
import { Router } from "@angular/router"


@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit  {

  public components = ["/1","/2"]; // List of component paths
  public current : number;
  public lastPos : any;

  @Output() mouseWheelUp = new EventEmitter();
  @Output() mouseWheelDown = new EventEmitter();

  @HostListener('mousewheel', ['$event']) onMouseWheelChrome(event: any) {
    this.mouseWheelFunc(event);
  }
  @HostListener('DOMMouseScroll', ['$event']) onMouseWheelFirefox(event: any) {
    this.mouseWheelFunc(event);
  }
  @HostListener('onmousewheel', ['$event']) onMouseWheelIE(event: any) {
    this.mouseWheelFunc(event);
  }

  ngOnInit() {
    /** Default route to component 1 */
    this.router.navigate(["/1"]);
    this.current = 0;
    this.lastPos = -1;
  }

  mouseWheelFunc(event: any) {
    let currentScrollPos = window.pageYOffset;
    var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));
    if(delta > 0) {
        if (currentScrollPos == 0) {
          this.navigateToPrevious();
        }
    } else if(delta < 0) {
        if (currentScrollPos == this.lastPos) {
          this.navigateToNext();
        } else {
          this.lastPos = currentScrollPos;
        }
    }
  }

  constructor(private router : Router, private ref : ElementRef) {}

  private navigateToNext() {
    if (this.current + 1 < this.components.length) {
      let path = this.components[++this.current];
      this.router.navigate([path]);
    }
  }

  private navigateToPrevious() {
    if (this.current > 0) {
      let path = this.components[--this.current];
      this.router.navigate([path]);
    }
  }

}

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

Enable Class exclusively on upward scrolling on the browser

Is there a way to dynamically change the class of an element only when the user scrolls the browser page upwards? Issue Filide>> JavaScript $(window).scroll(function() { var scroll = $(window).scrollTop(); if (scroll <= 100) { ...

Does Angular2 come with built-in responsiveness?

Recently, I've begun exploring the wonders of Angular2 and have been hearing many praises about its capabilities. This got me thinking: as I embark on building an application with Angular2 that will eventually need to be responsive, should I turn to a ...

What sets apart the states of the select tag from other input tags in Angular?

I am having trouble displaying an error message for a select tag when it is in a touched state. The error handling seems to be working fine for other input tags, but not for the select tag. Below is the code snippet: <div class="form-g ...

managing the HTML class names and IDs for various functions such as styling, jQuery interactions, and Selenium automation

While there is an abundance of articles on writing clean HTML/CSS, one aspect that seems to be lacking advice is how to organize class names and IDs for different purposes such as design, jQuery, and Selenium testing. The challenge lies in deciphering the ...

Extjs: How to Select a Node After Creating a Tree Structure

I am facing an issue with my TreePanel where I want to preselect a specific node when loading it. The nodes are fetched from a remote json file and the tree structure loads correctly. However, the selected node is not getting highlighted and Firebug is sho ...

Struggling to use the uploadFiles function with the kendo-upload component

I'm currently facing an issue with uploading my selected files from my component code. I chose the component code route because I need to upload those files after creating the parent aggregate object. This way, I can assign the necessary IDs to my und ...

Is the Kendo Spreadsheet supported in Angular 2?

We are interested in knowing if future releases of Angular2 will include Kendo Spreadsheet or the ability to export data to Excel for the grid. We currently use the Angular1 version and would like to upgrade, so having these features available in Angular2 ...

Encountered a server error while trying to export from Content

I'm attempting to retrieve data from a specific space in Contentful by utilizing the https://github.com/contentful/contentful-export npm package. However, when I execute my code following the example provided on the GitHub page, I encounter the follow ...

Personalized data based on the language within Next.js

Is there a way to customize Metadata for users based on search engine keywords? To enhance SEO performance on my website, I am working on setting up unique Metadata for the two languages my website supports: English and Portuguese. Specifically, I aim to ...

Implement a CSS style for all upcoming elements

I'm currently developing a Chrome extension tailored for my personal needs. I am looking to implement a CSS rule that will be applied to all elements within a certain class, even if they are dynamically generated after the execution of my extension&ap ...

Extract information from a lengthy text (vcard)

While scanning data from a vcard QR-code, the string I receive always follows this format: BEGIN:VCARD VERSION:2.1 N:Lastname;Firstname FN:Firstname Lastname ORG:Lol Group TITLE:Project Engineer TEL;WORK:+32 (0)11 12 13 14 ADR;WORK:Industrielaan 1;2250 Ol ...

JavaScript popup cannot be shown at this time

I'm encountering an issue with displaying popups using JavaScript. Currently, only the div with class "popup" is being shown. When a user takes action, both popup and popup2 should be displayed but for some reason, it's not working as expected. ...

"Select2 dropdown search bar vanishing act: The hunt for results comes up empty

Currently, I am dealing with a scenario involving two modals, each containing a select2 search dropdown. An issue has arisen where selecting modal one filters the dropdown data effectively. However, upon selecting modal two, although the data is filtered i ...

Retrieving information from Next.js and Typescript with the help of getStaticProps

I've been working on a personal project with Next.js and TypeScript. I'm attempting to fetch data from an API and then map the items, but I'm running into issues. When I use console.log, it returns undefined. The file is located in the pages ...

Using AngularJs: Invoking Service/Provider in app.config

I need to access my service from within app.config. While searching for a solution, I came across this question, which presented a potential solution that I attempted to implement (not the accepted answer, but the one below with the title "Set up your ser ...

Issues with BoxWidth configuration in ChartJS causing unexpected results

Check out my demo on JSFidle: https://jsfiddle.net/uniqueusername/example123/ In the chart, there is a noticeable pink box at the top. I'm trying to remove it. Some suggestions I found involved adding the following code: legend: { labels: { ...

The property 'enabled' is not a standard feature of the 'Node' type

Within the code snippet below, we have a definition for a type called Node: export type Node<T> = T extends ITreeNode ? T : never; export interface ITreeNode extends TreeNodeBase<ITreeNode> { enabled: boolean; } export abstract class Tre ...

Port 4200 is currently being utilized. Please utilize the '--port' option to designate an alternative port

Hi there, I am currently running an Angular 2 app with Express as the backend and encountering the following issue: [3] Port 4200 is already in use. Use '--port' to specify a different port. [3] [nodemon] app crashed - waiting for file changes b ...

Encountered a connection error while attempting to establish a connection in Node.js

Every time I try to execute the code, I encounter this error message: throw new Error('Most middleware (like ' + name + ') is no longer bundled with express and must be installed separately ^ Error: Most middleware(like BodyParser) is ...

Setting up a custom function for the cancel button in Angular X-editable

Can this be done? I've got a code snippet that resembles the following: <div class="popover-wrapper"> <a class="glyphicon glyphicon-time" ng-if="activity.type === 'continuous'" ng-style=" { 'border': 'none', ...