Prevent Angular from automatically scrolling to the top when subscribing to a timer

I have a real-time updating list of orders that is scrollable. This is the main component, where the list gets updated every 2 minutes with the following setup:

ngOnInit(): void {
    this.internalError = false;
    this.subscription = timer(0, 120 * 1000).pipe(
        switchMap(() => this.shopService.getPreferencesAsObservable()),
        filter(preferences => !!preferences), // emit only if `preferences` is defined and truthy
        tap(() => {
            this.isDeliverySlotsActive = this.shopService.isDeliverySlotsActive();
        }),
        switchMap(() => 
            forkJoin([
                    this.getInitialPendingOrders(true), 
                    this.getInitialPendingOrders(false),
                    this.getInitialDeliveredOrders(true),
                    this.getInitialDeliveredOrders(false),
                    this.getInitialCancelledOrders(true),
                    this.getInitialCancelledOrders(false)
                ]
            )
        )
      ).subscribe(res => {
            /* pending slots */
            this.loadedPendingSlotsOrders = [...res[0]["results"]];
            this.pendingSlotsOrderTimelines = this.ordersService.createTimelines(this.loadedPendingSlotsOrders, true);
            /* pending no slots */
            this.loadedPendingNoSlotsOrders = this.ordersService.filterOrders(res[1]["results"], OrderStatus.PENDING, false);
            this.loadedProcessedNoSlotsOrders = this.ordersService.filterOrders(res[1]["results"], OrderStatus.PROCESSED, false);
            this.loadedPendingNoSlotsOrders = [...this.loadedPendingNoSlotsOrders, ...this.loadedProcessedNoSlotsOrders];
            this.pendingNoSlotsOrderTimelines = this.ordersService.createTimelines(this.loadedPendingNoSlotsOrders, false);
            /* delivered slots */
            this.loadedDeliveredSlotsOrders = [...res[2]["results"]];
            this.deliveredSlotsOrderTimelines = this.ordersService.createTimelines(this.loadedDeliveredSlotsOrders, true);
            /* delivered no slots */
            this.loadedDeliveredNoSlotsOrders = this.ordersService.filterOrders(res[3]["results"], OrderStatus.DELIVERED, false);
            this.deliveredNoSlotsOrderTimelines = this.ordersService.createTimelines(this.loadedDeliveredNoSlotsOrders, false);
            /* cancelled slots*/
            this.loadedCancelledSlotsOrders = [...res[4]["results"]];
            this.cancelledSlotsOrderTimelines = this.ordersService.createTimelines(this.loadedCancelledSlotsOrders, true);
            /* cancelled no slots */
            this.loadedCancelledNoSlotsOrders = this.ordersService.filterOrders(res[5]["results"], OrderStatus.CANCELLED, false);
            this.cancelledNoSlotsOrderTimelines = this.ordersService.createTimelines(this.loadedCancelledNoSlotsOrders, false);
            /* data is ready, we can stop showing spinner */
            this.isLoaded = Promise.resolve(true);
    });
}

getInitialPendingOrders(hasSlots: boolean){
    return this.apiService.fetchShopOrders("status=PENDING&status=FULFILLED" + (hasSlots ? "&only_slots=true" : ''));
}

getInitialDeliveredOrders(hasSlots: boolean){
    return this.apiService.fetchShopOrders("status=DELIVERED" + (hasSlots ? "&only_slots=true" : ''));
}

getInitialCancelledOrders(hasSlots: boolean){
    return this.apiService.fetchShopOrders("status=CANCELLED" + (hasSlots ? "&only_slots=true" : ''));
}

Moreover, the component hierarchy is as follows:

OrdersComponent (prepare data to send to children) -> OrdersListComponent (*ngFor of sections) -> OrdersListSectionComponent (*ngFor of orders) -> OrdersListItemComponent (single order)

Here you can see how the list looks (it's an inner scrollable div):

https://i.sstatic.net/4wHos.png

The CSS for the scrollable div:

.scrollable {
    min-height: 10vh;
    max-height: 50vh; 
    overflow: auto;
    background: 
        linear-gradient(white 33%, rgba(179,86,216, 0)),
        linear-gradient(rgba(179,86,216, 0), white 66%) 0 100%,
        radial-gradient(farthest-side at 50% 0, rgba(34,34,34, 0.5), rgba(0,0,0,0)),
        radial-gradient(farthest-side at 50% 100%, rgba(34,34,34, 0.5), rgba(0,0,0,0)) 0 100%;
    background-repeat: no-repeat;
    background-attachment: local, local, scroll, scroll;
    background-size: 100% 1.5rem, 100% 1.5rem, 100% 0.5rem, 100% 0.5rem;
    scroll-behavior: smooth;
}

The template for the OrdersListSectionComponent:

<div *ngFor="let order of sectionOrders">
    <app-orders-list-item
        [order]="order"
        [timeline]="timeline"
    ></app-orders-list-item>
    <hr class="order-divider"/>
</div>

I have encountered an issue where the scroll of the list resets to the top whenever the timer triggers a refresh. This disrupts the user experience as it shouldn't reset the scroll position while the user is scrolling. Does anyone have a solution to prevent this unwanted scroll behavior?

Answer №2

To keep track of time, subscribe to a timer and reset it on scroll events using the following code snippet:

timer = timer(0, 120 * 1000);
timersubscription: Subscription;

initializeTimer(): void {
    this.timersubscription = this.timer.subscribe(() => console.log("Timer triggered");
}

refreshTimer(): void {
    this.timersubscription.unsubscribe();
    this.initializeTimer();
}

<div (scroll)="refreshTimer()"></div>

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

The dimensions of the div element are adjusting as I scroll on Firefox Mobile, however, there is a way to prevent this from happening using Angular

I've been conducting tests on my Angular application on various mobile devices. While everything seems to function properly on Chrome and Safari, an issue arises when it comes to Firefox: during scrolling, the browser's toolbar and URL bar appear ...

Tips on utilizing a local file as a background image URL

How can I modify my CSS to link to a local file path like C:\xampp\htdocs\Folder instead of the URL https://source.unsplash.com/1600x1050/?nature. I am currently using Bootstrap 4 and below is my CSS code: .jumbotron{ background: ...

Guide on Implementing jQuery Plugin with Vue, Webpack, and Typescript

I am currently exploring the integration of the jQuery Plugin Chosen into my vue.js/Webpack project with TypeScript. After some research, I discovered that it is recommended to encapsulate the plugin within a custom Vue component. To kick things off, I m ...

The ability to scroll horizontally for individual items within a larger container div

JSFIDDLE: http://jsfiddle.net/7zk1bbs2/ If you take a look at the JSFiddle project, you'll notice that the icons are placed inside an orange box. However, there is a vertical scroll needed to browse through them and I am attempting to enable horizont ...

Obscure silhouette enveloping the text enclosure

I'm a beginner in CSS and I need to create a text box like this: https://i.sstatic.net/4HQ4n.png My supervisor asked for a shadow effect around the box when clicked. How can I accomplish this? Any assistance would be greatly appreciated. ...

Angular2 Final: Issue with inline template - incorrect format for number pipes

Problem <h2>{{totalTargetValue | currency:'EUR':true:'2'}}</h2> Issue Error while using inline template: the specified digit info for number pipes is invalid. Do you have any suggestions on how to resolve this error? ...

What are the drawbacks of introducing a dependency within the constructor?

I'm struggling to understand why breaking the rules is considered bad. import {DepClass} from './di-import' // <- some dependency imports here class DI1 { dep1: DepClass constructor(){ this.dep1 = new DepClass() // ...

Props and theme merge to create uniquely designed styled components with a thematic twist

Out of sheer curiosity, I've been incorporating styled-components into my React application. Within this framework, I make use of the recommended theme to ensure consistency in colors and sizes throughout. Currently, my approach looks something like ...

Tips for implementing page-break-after:always within a bootstrap row?

I have a bootstrap row with a set of divs inside like this: @media print { p { page-break-after : always } } <div class = "row"> <div> data1 </div> <p> break page here </p> <div> data2 </div> <div> ...

Unable to extract the 'data' property from an undefined source in React, causing an error

I encountered this error message: TypeError: Cannot destructure property 'data' of '(intermediate value)' as it is undefined. export const getServerSideProps: GetServerSideProps = async () => { // categories const { data: categor ...

What is the best approach to integrating payment solutions into a React Native application running on version 0

Seeking advice on integrating payment systems in React Native 0.70. Previously utilized react-native-credit-card-input and react-native-credit-card-input-plus with earlier versions, but they are now incompatible. ...

Can the hexadecimal value from an input type color be extracted and used to populate form fields that will then be displayed in a table after submission?

Hello everyone, I'm new to this platform and seeking guidance on how to improve my post! I recently created a CRUD app using Angular. It consists of a basic form with 4 fields, a color picker using input type='color', and a submit button. U ...

How can we direct the user to another tab in Angular Mat Tab using a child component?

Within my Angular page, I have implemented 4 tabs using mat-tab. Each tab contains a child component that encapsulates smaller components to cater to the specific functionality of that tab. Now, I am faced with the challenge of navigating the user from a ...

Is it possible to create an HTML textarea that supports HTML formatting?

Is it possible to have HTML tag support in an HTML textarea within a form, similar to what is seen on Stack Overflow when asking a question? I would like to be able to capture the user's input in a textarea using PHP and print exactly what the user ty ...

Achieve sliding animations with Pure CSS using slideUp and slideDown techniques

Currently, I have implemented a code snippet to showcase a menu along with displaying submenus upon hovering over the main menus. Now, I am looking to introduce some animation effects for the submenus when they appear, similar to the slideUp and slideDown ...

The search box and submit button display without any visible borders

Question: I am facing an issue with the appearance of the searchbox and submit button in my PHP project. They look different compared to a simple HTML form. How can I fix this? The code on the PHP subpage is as follows: <header id="header"> <div ...

The POST method in XHR encounters issues on IOS when used with the Canvas to Blob script

Observation I've noticed a specific part of the code that's not functioning correctly only on IOS devices. xhr.open('POST', 'upload.php', true); xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); var da ...

What is the best way to ensure that the base class Resolver finishes before allowing the derived class Resolver to execute?

I have a situation where many of my resolvers (@angular/router Resolve) need to query the same data before executing their route-specific queries. To streamline this process, I want to create a resolver base class that resolves the initial data before the ...

Preventing the use of scripting tags in text boxes

I'm currently trying to integrate the post feature on my website using codeigniter (PHP). However, I've run into an issue where when I input and submit the following code: <script> alert("aaaa"); </script> The JavaScript starts exec ...

The CSS code for ::before is not functioning properly

Trying to enhance the style in Ionic2, I have a message box: https://i.sstatic.net/PCRtA.png I am attempting to integrate this image into it: https://i.sstatic.net/PSQID.png To create a seamless look with the message box. Facing an issue where the ima ...