angular.element($window).scrollTop() is throwing "is not a function" with webpack

15,295

scrollTop function is added by jquery, you must be loading jquery after angular. In that case you wont get $.fn functions added to the angular.element instance. You could as well do $.fn.scrollTop.call($window) in that case. or $($window).scrollTop() or load jquery before angular so that your current code works as is.

Side Note: You don't have to do $(element), element is already jq(lite/query) wrapped which has add/removeClass function available already.

Share:
15,295
joy
Author by

joy

I am Senior Software engineer. These days I am mainly working as full stack engineer. Which includes frontend, backend, unit test, end to end test automation, mongodb etc. I mainly working on reactjs, react-native, nodejs, mongodb, EC2 instances.

Updated on June 17, 2022

Comments

  • joy
    joy almost 2 years

    I am using Angularjs for my frontend development. Recently I started implementing Webpack then I realized that angular.element($window).scrollTop() stopped working and started throwing error as "windowElement.width is not a function". Following are old code and new code with webpack.

    Old working code:

    app.directive("ajnav", ['$window', '$location', function ($window, $location) {
            return {
                restrict: "E",
                templateUrl: "/templates/common/AJNav.html",
                replace: true,
                scope: {
                    seo: '=',
                    conf: '='
                },
                link: function (scope, element, attrs) {
                    //Bind event change the postion of AJ Nav on scroll
                    var windowElement = angular.element($window);
                    var onScrollHandler = function () {                    
                        //Get current height of iNav.
                        var iNavHeight = $("#iNavNGI_Header").height();
                        if (windowElement.scrollTop() > iNavHeight) {
                            $(element).addClass('navbar-fixed-top');
                            $(element).removeClass('aj-nav-container-absolute');
                        }
                        else {
                            $(element).removeClass('navbar-fixed-top');
                            $(element).addClass('aj-nav-container-absolute');
                        }
                    };
                    //Bind event handler on scroll
                    windowElement.on('scroll', scope.$apply.bind(scope, onScrollHandler));                
                }
    
            };
        }]);
    

    New code with webpack is throwing error:

    var $ = require("jquery");
    var angular = require("angular");
    var Utilities = require("./../../utilities/Utilities");
    var AppUtilities = require("./../../utilities/AppUtilities"); 
    module.exports = ['$window', '$location', function ($window, $location) {
            return {
                restrict: "E",
                templateUrl: "/templates/common/AJNav.html",
                replace: true,
                scope: {
                    seo: '=',
                    conf: '='
                },
                link: function (scope, element, attrs) {
                    //Bind event change the postion of AJ Nav on scroll
                    var windowElement = angular.element($window);
                    var onScrollHandler = function () {
                        //Get current height of iNav.
                        var iNavHeight = $("#iNavNGI_Header").height();
                        if (windowElement.scrollTop() > iNavHeight) {
                            $(element).addClass('navbar-fixed-top');
                            $(element).removeClass('aj-nav-container-absolute');
                        }
                        else {
                            $(element).removeClass('navbar-fixed-top');
                            $(element).addClass('aj-nav-container-absolute');
                        }
                    };
                    //Bind event handler on scroll
                    windowElement.on('scroll', scope.$apply.bind(scope, onScrollHandler));                
                }
    
            };
        }];
    

    Follownig is stacktrace for the exception I am getting.

    TypeError: windowElement.scrollTop is not a function
        at module.exports.link.onScrollHandler (site.min.js:42181)
        at Scope.$get.Scope.$eval (ite.min.js:25066)
        at Scope.$get.Scope.$apply (site.min.js:25165)
        at eventHandler (site.min.js:12594)
    

    I am binding this directive in my entry poing App.js as below

    app.directive("ajnav", require("./directives/common/AJNav"));
    

    I tried all the option I could but not able to fix it. Please help.

  • joy
    joy almost 9 years
    what i found during debugging $window.$ is undefined, however in my old code $window.$ has full jqery object. I changed the order to require('jquery') however still facing same problem. How can i fix $window object?
  • PSL
    PSL almost 9 years
    @joy what happens when you do $($window).scrollTop(), Do you get $ at all (console log $ after var $ = require("jquery");)?
  • joy
    joy almost 9 years
    When I changed code to use $($window).scrollTop() then it worked. But it would be better I don't have to change my code :-)
  • PSL
    PSL almost 9 years
    @joy for that you need to load jquery script before loading angular itself. Also you don't need to do $(element).addClass instead element.addClass should just work
  • PSL
    PSL almost 9 years
    @joy Also see this to fix your loading order. You are doing manual bootstrap right?
  • joy
    joy almost 9 years
    Thank you. Very helpful.
  • joy
    joy almost 9 years
    & yes...i removed $(element) to "element" and its working :-) learning day by day!!!