Incorporating stick-to-top scroll functionality using AngularJS and ng

I am trying to implement a 'sticky' scroll on dynamic content. My current working example can be found here. It seems to be working, but I encounter a small 'flicker' when new items are appended. This issue seems to be related to the setTimeout(0) function. However, if the timeout is removed, the example does not work properly when trying to add 50 new items. Unfortunately, using virtual/custom scroll solutions like in the Ionic example is not an option. The scroll must be native HTML.

Any ideas on how to solve this problem?

HTML:

<body ng-app="demoApp">
    <div ng-controller="TestCtrl">
        <div id="first">
            <list item-source="items" id="list"></list>
        </div>
        <div>
            Total: {{items.length}}
            <button type="button" ng-click="prepend(1);">Prepend (1)</button>
        </div>
    </div>
</body>

JavaScript:

(function(angular) {
    var app = angular.module('demoApp', []).controller('TestCtrl', function($scope) {
        $scope.items = [];
        $scope.count = 0;
        $scope.manualCount = 0;
        $scope.prepend = function(count){
            for(var i = 1; i <= count; i++){
                $scope.count++;
                $scope.items.unshift({
                    imageSrc: 'http://placehold.it/90x140&text='+$scope.count
                });
            }
        };
    }).directive('list', ['$timeout', function($timeout){
        return {
            restrict: "EA",
            transclude: false,
            replace: false,
            template: '<div id="list_wrapper"><div list-item ng-repeat="item in itemSource track by $index" class="item"><img ng-src="{{item.imageSrc}}"/></div></div>',
            scope: {
                itemSource: '='
            },
            compile: function(){
                return {
                    pre: function(scope, element, attrs, ctrl){
                        ctrl.setElement(element[0]);
                    }
                };
            },
            controller: function($scope){
                var element = '';
                $scope.linesCount = 0;
                var colcount = 3;
                this.setElement = function(el){
                    element = el;
                };
                this.addItem = function(item){
                    var newLinesCount = Math.ceil($scope.itemSource.length / colcount);
                    var linesInserted = newLinesCount - $scope.linesCount;
                    if(linesInserted > 0){
                        var prevScroll = element.scrollTop;
                        $timeout(function(){
                            var newScroll = prevScroll + (item.clientHeight * linesInserted);
                            element.scrollTop = newScroll;
                        }, 0);

                    }
                    $scope.linesCount = newLinesCount;
                };
            }
        };
    }]).directive('listItem', [function(){
        return {
            require: "^list",
            link: function(scope, element, attributes, listCtrl){
                listCtrl.addItem(element[0]);
            }
        };
    }]);
})(window.angular);

Answer №1

Remember to switch out $timeout for $scope.$evalAsync in order to perform operations asynchronously in the background.

SAMPLE CODE

$scope.$evalAsync(function() {
    var updatedScroll = previousScroll + (element.clientHeight * insertedLines);
    element.scrollTop = updatedScroll;
});

Check out this working example

For a more detailed explanation, take a look at this answer on Stack Overflow, another helpful response on SO Or This informative link

Answer №2

Have you had a chance to experiment with this specific directive? I incorporated it into my own project and found it to be quite effective.

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

ScriptManager.RegisterClientScriptBlock is failing to execute the already existing script

Background When a client-side button click triggers a server-side function, a loading panel (div) is displayed before the server-side function is executed. The loading panel should be removed once the server-side function completes. My Approach Upon com ...

Netlify deployment is failing to display the CSS styling on a website built with Hugo

Currently in the process of creating my own website using the "Call Me Sam" hugo theme. Everything looks great locally but once deployed on Netlify, the CSS styling seems to be completely disregarded. If you want to check out my repository: https://github ...

Asynchronous AJAX request using JQuery loader with async:false setting

As a newbie to the world of jQuery, I find myself lost in solving my current issue. Despite checking various solutions to similar problems, none seem to work for me. Working on MAC OS X using Safari with JQuery 2.1.1, I must ensure that my platform is comp ...

Node.js Express post query failing to set content type

I have a POST request implemented with the express framework to submit a query to a rest api. Here is the relevant code snippet: var request = require('request'); app.post('/compute', function(req, postResponse) { var queryJSON = re ...

Display picture next to content with the help of CSS/Bootstrap and Django's Jinja 2

I'm having trouble displaying an image next to text, it keeps showing up below. Here's the code snippet: <div class="container"> <div class="row"> <div class="col-md-8"> < ...

Is there a way to modify the Javascript for this Contact Form to trigger a different action if a specific key is pressed instead?

I have been working on a Contact Form that integrates Google Scripts. Everything seems to be functioning well as it successfully sends emails and formats them properly in my inbox. However, there are two issues that I am encountering: -I want to exclude t ...

When utilizing ui-router, the root url will automatically redirect to a state with an empty url

My parent state has a URL mapped for '/' and when I visit the root, like this example: http://localhost:8081/sin/TPW/, it automatically redirects me to a child state with an empty URL. I'm puzzled as to why this specific child state is bein ...

JavaScript: protecting data, revealing functionality

Looking to enhance my understanding of Javascript basics in order to delve into client-side frameworks like Knockout and Angular, as well as make headway in learning Node.js. I've selected a simple problem used in teaching C# and am now attempting to ...

I'm having trouble with my Laravel edit page not functioning properly when using vue.js. Can anyone help me troubleshoot

Currently, I am developing a dashboard to display details. Users can click on the edit button to modify their information. However, when I try to edit by clicking the button, nothing happens. It seems like the editing feature is not functioning properly, a ...

What is the best way to streamline the if statement in JavaScript?

Here is the given code snippet: public noArtistBeingEdited(): boolean { if (this.isFirstNameBeingEdited()) { return false; } if (this.isLastNameBeingEditable()) { return false; } return true; } What are some ways to ma ...

Troubleshooting issue with applying hover effect to child divs

How come when I hover over one of the child items in my parentDiv, the background of the last childDiv changes no matter which child I place my mouse on? for (let i = 0; i < Number(height); i++) { for (let j = 0; j < Number(width); j++ ...

What is the best way to establish a connection between a client and MongoDB

My attempt to connect my client with MongoDB resulted in an error message: MongoParseError: option useunifedtopology is not supported. I am unsure of the reason behind this issue and would greatly appreciate your assistance. Below is the snippet of code ...

I am facing an issue with properly linking my jQuery

After searching through numerous posts on this website, I have yet to find a solution to my problem. My issue involves trying to implement a simple jQuery function that is not functioning as expected. It appears that the jQuery link may not be properly set ...

What causes the "Unknown provider" error when using Cordova's secure storage plugin?

I'm attempting to utilize Secure Storage (https://ionicframework.com/docs/v2/native/secure-storage/) in my Ionic application. Within my controller: .controller('ExampleCtrl', function ($scope, SecureStorage) { var ss = new Secu ...

My website gets all wonky when I try to resize the browser

Here is a visualization of my website's ideal appearance: However, the actual display varies on different computers. After testing with browsershots.org, I noticed that my website looks messy on most browsers and even when resizing the browser window ...

Utilize React to reduce, replace, and encapsulate content within a span element

I have a Map that receives JSON data and generates a list item for each value. Then, I modify specific parts of the strings with state values. const content = { "content": [ { "text" : "#number# Tips to Get #goal#" ...

Protractor - Issue with clicking on hidden element with "ng-click" attribute

I'm facing an issue with a specific element that I am unable to click using Protractor. Everything was working fine until a few days ago. Technical information: Chrome version: 47.0.2526.106 Protractor version: 2.0 Selenium version: 2.44 CSS &l ...

Leveraging the ng-model value in ng-if

I am currently working on a feature that involves checking if an entered idNumber exists in a table, and then adding a glyphicon to the corresponding row. One issue I am facing is figuring out how to access the ng-model="idNumber" from within ng-if. My a ...

The Power of jQuery's .ajax() Utility

I'm a beginner with the jQuery AJAX ajax() Method and have recently created the AddATeacher() function. The function gets called successfully as I see all the alert messages popping up. However, the ajax() Method within the function is not working. Th ...

The date entered in the input field should also appear in all other textboxes on the

I currently have 2 tables set up on my page. In the first table, there is a textbox (txt1) that includes a date picker. The second table contains 5 similar textboxes (txt2, txt3, txt4, txt5, txt6) also with date pickers. My requirement is as follows: Ini ...