Delay the execution of the function in AngularJS until the browser has finished rendering completely and the view-model synchronization cycle has ended

I'm uncertain about the appropriate title for this inquiry, so please correct me if I am mistaken.

Suppose that upon page refresh (load), I require an animated scroll to an anchor based on the current location's hash (I am aware of ngAnchorScroll, but I specifically need animated scrolling, which ngAnchorScorll cannot accomplish).

To achieve this, I have created a service that will be called upon controller initialization:

var Ctrl = function ($scope, initAnchorScrolling) {
    initAnchorScrolling($scope);
};

Ctrl.$inject = ['$scope', "initAnchorScrolling"];

applicationServices.factory("initAnchorScrolling",
    ['scroll', '$location', '$timeout', function(scrollUtils, $location, $timeout) {
    return function(scope) {

    /** Some stuff here */

    function scroll() {
        var hash = $location.hash(), elm;

        if (!hash) {
            scrollUtils.scrollTo(0, 0);
        } else if ((elm = getAnchorElement(hash))) {
            scrollUtils.scrollToElement(elm);
        } else {
            scrollUtils.scrollTo(0, 0);
        }
    }

    scope.$watch(function scrollWatch() { return $location.hash(); },
        function scrollWatchAction() {
            $timeout(function () {
                scroll();
            }, 0, true);
        });
    };
}]);

You can observe that this anchor implementation is very similar to ngAnchorScroll. The main distinction is that I utilize jQuery.animate() to transition between anchors.

According to my understanding from here, in order to delay function execution until the browser has finished rendering, one simply needs to call the $timeout service with a delay parameter set to 0. However, this method is not proving effective for me. Occasionally, the page scrolls to different positions unexpectedly. I attribute this issue to the fact that the scroll function is invoked before the digest cycle completes synchronization of views and models—the HTML blocks therefore possess inaccurate height and position at the time of invocation.

Hence, my query: is there a way to defer function invocation until the moment when the browser has fully completed rendering and the digest cycle has synchronized views and models (applied bindings)?

Answer №1

This particular solution addresses the issue of maintaining scroll position regardless of any changes, rather than simply scrolling to a specific hash. While it may offer a resolution to your problem, it's important to note that the directive created works specifically on window scroll events (although it could be adapted for other elements).

Here is an example of how you can implement this in your HTML code:

<div ng-keep-scroll="service.scrollY">
<!-- Place your scrolling content here -->
</div>

It's crucial to ensure that "service.scrollY" is a variable within a service. Services retain their data and values, unlike controllers which reset every time they load. The controller should have a scope variable that references the service.

Below is the directive JavaScript code:

app.directive('ngKeepScroll', function ($timeout) {
    return function (scope, element, attrs) {

        // Load scroll position after everything has rendered
        $timeout(function () {
            var scrollY = parseInt(scope.$eval(attrs.ngKeepScroll));
            $(window).scrollTop(scrollY ? scrollY : 0);
        }, 0);

        // Save scroll position when there's a route change
        scope.$on("$routeChangeStart", function () {
            scope.$eval(attrs.ngKeepScroll + " = " + $(window).scrollTop());
        });
    }
});

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

Manipulating the display style of an element without using jQuery

Could anyone assist me with this issue? I am currently facing a challenge in making the following script functional. It is intended to hide the button after it has been clicked. The script is being called through Ajax and PHP, so I am unable to utilize jQ ...

Guide to transferring a JavaScript/Ajax variable to a PHP webpage with the help of AJAX

function initiateIperfSpeedRequest(speedVar, actualIp) { var xmlhttp = getAjaxObject(); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { handleIperfResponse(xmlhttp.respo ...

Latest Information Regarding Mongodb Aggregate Operations

Struggling to toggle a boolean value within an object that is part of a subdocument in an array. Finding it difficult to update a specific object within the array. Document: "_id" : ObjectId("54afaabd88694dc019d3b628") "Invitation" : [ { "__ ...

Activating autocomplete outcomes via AJAX using Cucumber/Capybara/Selenium

Whenever I try to run my tests, the autocomplete dropdown menu doesn't appear unless I physically click on the search input field. This is a Cucumber test that utilizes Selenium Webdriver, and the data is sourced from the Crafty Clicks Address Autoco ...

Having difficulty retrieving data when running a React JS app on the IP address 192.168.XX.XXX

I'm attempting to retrieve backend data in a React app using the Fetch API. It's functioning correctly when I run the React app on localhost, but if I change the address from localhost to an IP, it stops working and displays Unhandled Rejection ( ...

What's the best way to integrate Bootstrap into my HTML document?

Hey there, I'm new to the coding world and just started learning. I could use some assistance with including Bootstrap v5.1 in my HTML code. The online course I'm taking is using an older version of Bootstrap, so I'm having trouble finding t ...

Updating the state of a Next.JS router component with React.JS: A step-by-step guide

I've implemented a toggleswitch in my app that changes its state based on the dynamic URL parameters. For instance, if the URL includes a parameter named followType set to following (e.g. https://www.example.com/home?followType=following), I want the ...

Leveraging the power of Google Closure Templates alongside the versatility of

We are embarking on developing an application using JavaScript and HTML5 that will utilize a rest API to access server resources, leveraging the power and convenience of jQuery which our development team is already proficient in. Our goal is to make this a ...

The Vue warning indicates that there was a failed type check for the "value" prop. It was expecting an array but received a number with a value of 1

I am facing an issue with an input of type number where I need to restrict the user from entering a number greater than ten. Initially, everything was working fine until I decided to change the value to an array (from value: 1 to value: [1, 1]) After swit ...

The performance of the React create app proxy agent in the package.json file seems to be sluggish,

In our react application (created as create-react-app), we have a proxy defined in the `package.json`. This proxy is used between the front-end (webpack) and back-end (express) during development, as outlined here. The section of the `package.json` where t ...

locate missing Gutenberg block on map

/** * Custom Block: display-mobile-advertising * * This block registers a basic block with Gutenberg that renders and saves content without any interactivity. */ // Import CSS. import { TextareaControl } from '@wordpress/components'; import ...

Is it possible to update the content page without having to refresh the master page?

Our website features a Master page with main menu options and corresponding sub menus. When a user clicks on a main menu item, the relevant sub menus should be displayed. After clicking on a sub menu, the content page should update without having to refr ...

Trouble with Bootstrap 5 Carousel swipe functionality: Issues arise when inner elements with overflow are involved, causing vertical scrolling to interfere with left to right swipes

I've been scouring the internet for answers to my unique issue with a Bootstrap 5 carousel. My setup is fairly basic, but I've removed the buttons and rely solely on swiping to navigate through the carousel items. When I swipe left to right, eve ...

Is there a way to create a duplicate form without any pre-filled text when clicking the "next" button using JavaScript?

This form contains the details that I would like to display on the page again when clicking the "Add Another Module" button. <div> <form class="in-line" id="module_info"></form> <div style="display: flex;"> < ...

Encountering a CORS issue when utilizing Stripe with various servers while navigating with a Router

I have a router that utilizes Router.express(). The backend operates on port 5000, while the frontend runs on port 3000. Within the frontend folder, there is a button with a fetch request (http://localhost:5000/create-checkout-session). In the backend, the ...

Deliver integers using Express.js

When I try to send a response with Express using the code below, it doesn't work: res.send(13245) An error message is displayed: express deprecated res.send(status): Use res.sendStatus(status) instead src/x.js:38:9 (node:25549) UnhandledPromise ...

Enhancement from the original JavaScript class framework created by John Resig

Greetings everyone, Lately, I've been on the lookout for a straightforward JavaScript class framework that focuses solely on basic inheritance. After some research, I stumbled upon John Resig's sample framework shared on his blog, and it seems t ...

How can I implement the ternary operator in React Native and resolve my code issue?

Hello, I'm looking to implement the ternary operator in my code. Specifically, I want to render a FlatList if `cookup` has a value. However, if `cookup` is an empty array, I want to display some text instead. <FlatList data={cookUp} ...

Exploring ReactJS: Utilizing the useEffect Hook for Retrieving Various Data Sources

I have recently started working with react and currently have a function that fetches data in my useEffect hook. I am using a loading state to handle component rendering, and then populating my state component with the fetched data successfully. However, ...

What is the best way to compare two strings without considering their capitalization?

Here is the issue I am facing: mytext = jQuery('#usp-title').val(); Next, I check if the text matches another element's content: if(jQuery("#datafetch h2 a").text() == mytext) { However, titles can vary in capitalization such as Space Mi ...