Attach element using only AngularJs

I've been attempting to create a fixed element on my page using only AngularJs, without relying on jquery.

I've tried a few different methods but none of them are producing the desired result. The challenge lies in getting the offsetTop of the element I want to fix after scrolling.

This is all happening within a directive that runs every time the page is scrolled.

Here's the code I've experimented with:

.directive("scroll", ['$window', function ($window) {
    return function(scope, element, attrs) {
        angular.element($window).bind("scroll", function() {

            //This code returns: '0'
            var filter= document.getElementById('filter').offsetTop;

            //This code returns: Error: [jqLite:nosel] 
            var filter = angular.element('#filter').prop('offsetTop');

            //This code returns: [object HTMLDivElement]
            var filter = angular.element(document.querySelector('.filter')).prop('offsetTop');

            //This code returns: '0'
            var filter = angular.element(document.getElementsByClassName('filter')).prop('offsetTop');

            [.. more code ..]

        })
    }
}]);

The issue is that none of these codes are giving the correct output. It either results in an undefined value or returns a value of 0, even when the element should have an offset of 700.

Is there a way to retrieve the offsetTop value of this element using pure AngularJs or vanilla Javascript? I'm hesitant to include Jquery just for this one function.

Answer №1

Through extensive research and code modifications, I have devised a solution to select an element and implement an affix effect.

The necessary code includes:

  • Utilization of AngularJS (without jQuery);
  • A parent element with an ID and the directive, along with a child element;
  • The child element containing the desired content;
  • Application of a custom CSS class for the effect (the CSS could alternatively be integrated within the directive, but for my convenience as I am using SASS with other functions, maintaining separation is preferred).

page.html

<div class="parentElement" affix-me id="affix">
    <div class="childElement">
        <!-- insert your content here -->
    </div>
</div>

style.css

.affix {
    position: fixed !important;
    top: 0; //Adjust this value accordingly;
    z-index: 990;
}

directive.js

.directive('affixMe', ['$timeout','$window', function($timeout, $window) {
    return {
        restrict: 'A',
        link: function(scope, element) {
            scope.width = element.prop('offsetWidth');
            var elWidth = scope.width + 'px',
                elChild = angular.element(element[0].querySelector(':first-child'));
                elChild.css('width', elWidth);
            angular.element($window).bind("scroll", function() {
                var affixElement = document.getElementById('affix'),
                    xPosition = 0,
                    yPosition = 0;
                function getPosition(element) {
                    while(element) {
                        yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
                        element = element.offsetParent;
                    }
                }
                getPosition(affixElement);
                if (yPosition >= 0) {
                    elChild.removeClass('affix');
                } else if ( yPosition < 0) {
                    elChild.addClass('affix');
                };
            });
        }
    };
}])

To-do: ##

Although not implemented yet, it would be beneficial to incorporate functionality that checks if the element has reached the bottom of the page or its parent element, in order to cease the affix effect at the top and reapply it at the bottom.

In my specific scenario, a 400px footer causes slight overlap with the affixed element.

If anyone can offer assistance with this matter, it would be greatly appreciated!



========== Previous Response ==========
Drawing inspiration from a relevant resource, I have fine-tuned the code to align with my requirements.

This is the revised snippet in use:

scope.affixFiltro = false;

var filtro = document.getElementById('filtro'),
    filtroOffset,
    yPosition = 0;

function getPosition(element) {
    while(element) {
        yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
        element = element.offsetParent;
    }
}
getPosition(filtro);
if (yPosition >= 0) {
    filtroOffset = yPosition;
} else if ( yPosition < 0) {
    filtroOffset = 0;
};

//Toggle affix class on/off
if (filtroOffset == 0) { //verify offset
    scope.affixFiltro = true; //enable affix class
} else {
    scope.affixFiltro = false; //disable affix class
}

Essentially, since offsetTop calculates the distance from the first relatively positioned ancestor, iteration is required until reaching the top of the page.

Answer №2

Check out this documentation for more information: https://docs.angularjs.org/api/ng/service/$anchorScroll. I also came across a similar question: AngularJS $anchorScroll yOffset within a child element

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

Attempting to create a fresh string by substituting certain characters with different ones

Exploring TypeScript, I encountered a puzzle where I needed to substitute specific characters in a string with other characters. Essentially, replacing A with T, T with A, C with G, and G with C. The initial code snippet provided to me looked like this: e ...

Tips for logging out a user from Auth0 in Next.js when token refresh fails with the help of Axios interceptor

I integrated the Auth0 SDK into my Next.js application to handle authentication, and I implemented an Axios interceptor for automatically refreshing the access token upon expiration. Below is the setup for the Axios interceptor: async function renewAccessT ...

What is the best way to modify javascript to make it load regardless of Ajax?

I am facing a challenge with my JavaScript code on a Squarespace site that requires Ajax-loading. The current code only functions properly after a page refresh, which is not ideal. More details on this issue can be found here. I would appreciate any guida ...

Tips for avoiding performance bottlenecks in Polymer 1

Environmental Issue Polymer 1 Challenge: I am facing an issue where I have an Array containing 35 objects. When I use a dom-repeat template to create a list of elements (all identical), it takes around 10 seconds for all the elements to render. The ent ...

Preventing JavaScript from Removing Operators When Transmitting/Storing Data in PHP with AJAX

My goal is to transmit a string equation, like "3+3", but when PHP processes it, it displays as "3 3" instead. It seems that somewhere along the way, the operators are disappearing. function sendEquation() { let str = document.querySelector(".equation ...

Angular form submission error: Type mismatch detected

I'm encountering a TypeError with the message: Cannot set property 'songname' of null, when attempting to update a row in firebase. The error is specifically related to the record.songname in the edit function. I can add new rows but editing ...

AngularJS promise fails to resolve when attempting to read a file using the FileReader

Can someone assist me with a function I am trying to create in my service? I want the function to use FileReader to read a small image file and return the result in a promise to my controller. The issue is that while the file reaches the service without an ...

Validate with JavaScript, then display and submit

I've created a submit function to verify form inputs, and then, if desired (via checkbox), print as part of the submission process. The issue is that when printing, the form submission never finishes. However, without printing, the form submits corre ...

Unique title: "Curved Blocks with Unusual Shapes in SVG Path

Hey there, I'm new to working with SVG and Highcharts. I found a jsfiddle online that I would like to customize for my project, but I've encountered an issue with the rounded corner blocks of lines in the Result panel. Here is the link to the js ...

Display a popup on a button click or icon click in ASP.NET

On Facebook, you may notice that you have 4 friend requests or notifications in the small mail icon on the right side. When you click on it, a pop-up appears with an accept button, and once you accept, it disappears and the remaining three requests are sho ...

Best placement for jQuery in Ionic index.html

I have encountered an unusual issue. Currently, I am developing a project using Ionic (AngularJS) and incorporating jQuery in one of my controllers. As a result, I need to include a reference to it in index.html If I add the reference like this - <! ...

Decipher the JSON data for a Facebook cover photo

I am utilizing the Facebook Graph API to retrieve the user's cover picture. By accessing the link provided at , a JSON object containing the picture link is returned. How can I fetch this link using JQuery or JavaScript? Here is my attempt: HTML: & ...

The tree expansion does not activate the CSS transition

Currently, I am in the process of creating a TreeView using only CSS and JS. My goal is to include a subtle transition effect when expanding or collapsing a node. The transition effects are successfully implemented for collapsing nodes, however, they do no ...

Is there a way for me to determine if there are elements in one object array that exist in another object

Is there a method to check if two object arrays have any common elements, and if so, find the intersecting object? Similar to a Contains function. For instance, in the provided example, ProductId3 in Object Array 1 is also present in Object Array 2. I&apo ...

Can you explain the process of variable allocation?

I have a query regarding the following JavaScript code snippet. It might be a basic question, but I'm seeking clarification. // 'response' contains JSON data received from the backend: ....then(response => { this.myVar = response.data; ...

Enhancing Laravel functionality by sending JavaScript array to Controller with jquery

My array looked something like this: var a = [ { "start":"2015-01-12T00:00:00.000Z", "allDay":false, "promotion_option":"banner" }, { "start":"2015-01-13T00:00:00.000Z", ...

Angular digest is triggered when the method setValidation is called

Upon form submission, backend validation is performed to ensure email uniqueness with the following code snippet: $http.post('/api/users.json', dataObj) .then (function() { // All good }) .catch(function(response) { ...

Importing a 3D Model Using Three.js

I've been trying to import a 3D model by following tutorials. I managed to successfully import using A-Frame Tags, but encountering issues with Three.js. The code snippets are from a tutorial on YouTube that I referred to: https://www.youtube.com/watc ...

Is it possible to activate the :active pseudoclass by pressing the 'enter' key on the keyboard using solely CSS?

The CSS: a:focus { opacity: .75 } a:active { transform: translateY(4px) } The purpose: When keyboard users tab to the link, the :focus style serves as a visual indicator Upon pressing the enter key to activate the link, the :active style provides ...

External IPs cannot access Node.js

I am facing an issue with my Amazon EC2 Server where I have set up a node js server. It is not accessible from the outside using the public DNS, but it can be accessed from the same instance (localhost). Any assistance in resolving this problem would be gr ...