Navigate to the most recent entry in the array while using ng-repeat

I am attempting to implement scrolling to the last added entry within an ngRepeat directive.

After researching related questions on Stack Overflow, such as #1 and #2, I still cannot find a solution to my problem.

The code is straightforward. When a user adds a new record to the array, the controller sends a 'scroll-event' with the name of the newly added item. The directive then listens for this event and scrolls to the new entry in the list.

<div ng-controller="MainCtrl">
    <input ng-model="newItem" ng-keydown="$event.which === 13 && addNewItem(newItem)"/>
        <button ng-click="addNewItem(newItem)">Add</button>

        <div id="items-list" scroll-to-new-item> 
            <div ng-repeat="item in items | orderBy: 'name'">
                <input ng-model="item.name" ng-readonly="true"/>
            </div>
        </div>
 </div>

app.controller("MainCtrl", function($scope){
    $scope.items = [
        {id: 1, name: "aaa"}, {id: 2, name: "bbb"},         
        {id: 3, name: "ccc"}, {id: 4, name: "ddd"},
        .......
    ];

    $scope.addNewItem = function(newItem){
        $scope.items.push({name: newItem});
        $scope.$broadcast('scroll-event', newItem);
        $scope.newItem = "";
    };
});

This is my directive that should scroll to the last added record in the list.

app.directive("scrollToNewItem", function(){
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            scope.$on('scroll-event', function (event, newValue) {
                if(newValue){
                    var newItemHeightPosition = // !!! MY ISSUE HERE !!!
                    $('#items-list').animate({
                        scrollTop: newItemHeightPosition
                    }, 'slow');
                }
            });
        }
    };
});

However, I am struggling to determine how to retrieve the top-height position of the newly added item. Various attempts using jQuery selectors have not been successful:

$('#items-list').find('input[value=' + newValue +']');
$('#items-list').find('input').eq(newValue);

It is important to note that the array is sorted alphabetically, adding complexity to this task.

Here is my JSFiddle.

If anyone has insight on how to resolve this issue, I would greatly appreciate it.

Thank you in advance!

Answer №1

There were a couple of issues with the code I was working on.

1) One issue arose because the ngRepeat directive wasn't rendering newly added items in the repeat before the scrollToNewItem directive kicked in.

To solve this, I enclosed the DOM selector in a $timeout. This ensured a safe way to call $scope.$apply and confirmed that the $digest cycle had completed. More information can be found here.

2) The second issue stemmed from my input items not having any value-containing attributes. Consequently, I couldn't locate any DOM elements using the specified JQuery selectors.

$('#items-list').find('input[value=' + newValue +']')

I addressed this by including an additional attribute value within the input under the ngRepeat directive.

value="{{vehicle.Name}}"

For a comprehensive example of the revised code, check out my updated JSFiddle here.

Answer №2

I don't particularly advocate for efficiency, but unless your list is extremely long, I personally don't have an issue with using .each() in this manner.

app.directive("scrollToNewItem", function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            scope.$on('scroll-event', function (event, newValue) {

                var newItemHeightPosition

                if (newValue) {
                    $('#items-list input').each(function () {
                        if ($(this).html().indexOf(newValue)) {
                            newItemHeightPosition = $(this).position().top;
                        }
                    })

                    $('#items-list').animate({
                        scrollTop: newItemHeightPosition
                    }, 'slow');
                }
            });
        }
    };
});

To elaborate further, when you use

$('#items-list').find('input[value=' + newValue +']');

you're attempting to select a DOM element that might look like the following

<input type="submit" value="name">

However, your input elements may not actually have a value attribute. Instead, I iterate over the inputs and find the one whose HTML contains the recently added name. It's not flawless, but it demonstrates how you can navigate around this issue.

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

Ways to ensure the jQuery Sticky Float plug-in responds dynamically to updates on the page

Recently, I came across the amazing 'stickyfloat' plug-in(http://plugins.jquery.com/files/stickyfloat_0.htm) for jQuery that I'm considering using for a project. The main goal is to have a fixed panel on the right side of the page as the con ...

AngularJS function for alternating addition and subtraction operations

I am looking to create a toggle button that will add money to a total price when clicked once, and subtract that amount when clicked again to "deselect" it. Currently, I have this HTML code that toggles between adding and removing a class to change the ba ...

Guide to locating the index of a div element that has been dropped onto a droppable div

My web application features drag and drop functionality allowing users to drag a div and dynamically drop it onto a droppable area. Additionally, the droppable area has sortable functionality enabled. Now, I need to determine the indexing in order to acc ...

Popup mode is utilized by CodeIgniter error pages to display error messages

Is there a way to show error messages without being redirected to the error pages located in application\errors\*error_pages*? We want to remain on the same page and display any errors that occur in a popup. Can someone provide an example code fo ...

Ensuring divs are centered when resizing the page

Is there a way to center an unordered list of tables while ensuring that it remains centered even when the window is resized? The list should move each table to a new line if they can no longer fit. Check out the code snippet below for reference: <d ...

Expand the video comparison slider to occupy the entire width and height

I am striving to develop a video comparison slider that fills the height and width of the viewport, inspired by the techniques discussed in this informative article: Article Despite my efforts, I have not been successful in achieving this effect so far a ...

Refreshing the DOM following an API call using VueJS

Struggling with updating the DOM after fetching data from an API. Although my object is successfully fetching the data, the DOM renders before receiving the API Data and fails to update afterward. I'm puzzled as to why it's not refreshing itself ...

Arranging the final item in the empty space above the div section using Flexbox

Kindly review this code for additional details. Take a look at the image above for a clearer understanding. On the right side of the image, you will notice that the last row contains two items and the second row has one empty slot. I need to rearrange one ...

Make the div in jQuery clickable to redirect to the child URL

Could someone shed some light on why this code isn't functioning as expected? I'm fairly new to javascript and jQuery. Below is the snippet in question: Javascript / jQuery: <script type="text/javascript"> $('.clickk').cl ...

Acquire the Dynamic HTML Tag from the source code of the page

I am currently using Selenium to develop a bot that will automate a task by fetching a report from a website. I must admit, I am not well-versed in HTML or Javascript, so please forgive any misuse of terms. Here is the problem at hand: Using Python, I wri ...

Executing several asynchronous functions in Angular 2

I am currently developing a mobile app and focusing on authentication. In order to display data to the user on my home page, I need to connect to various endpoints on an API that I have created. Although all endpoints return the correct data when tested i ...

Undo the selection on the checkbox

Good day! I am facing a challenge where I need to reverse the action when the client clicks on a checkbox in certain scenarios. However, despite using the following code snippets: $("#foo").attr('checked'); or $("#foo").attr('checked&apo ...

Error encountered while attempting to compile transcluded directives during unit testing with Angular version 1.3.0

I am facing an issue with a custom directive having transclude: true property. The directive contains a template pointing to a simple HTML file with an anchor element having an ng-transclude attribute. The anchor element wraps the content of the directive. ...

The jQuery script is functioning flawlessly in one specific direction

Currently, I am utilizing a basic script to alter the color of elements based on the div being hovered over. While this works smoothly in one direction down the line, when trying to reverse order and backtrack, the colors do not function as intended. The ...

Encourage (or kindly request) the user to refresh the browser

I manage a website that heavily relies on javascript and ajax functionality. I have found ways to make users refresh their browsers upon initial loading, but what about after they have already been using the site? I am looking to improve the speed of the ...

A guide on protruding a specific triangle within a mesh using three.js

Description: In my three.js project, I have implemented a selection tool that allows users to click and drag over the mesh to color the triangles red. Now, I am looking to create a function that will examine the mesh.geometry.attributes and extrude any tr ...

What is the minimum number of lines that can be used for javascript code?

Currently, I am in the process of developing a custom JavaScript minifier. One question that has come up is whether it is necessary to insert line breaks after a certain number of characters on a single line, or if it even makes a difference at all? For i ...

Creating a tree structure using an array of objects

I am working with an array containing the following data: const data = [ { id: 1, type: 'type 1' }, { id: 2, type: 'type 2', subtype: 'subtype 2' }, { id: 3, type: 'type 2', subtype: 'subtype 3' }, ...

Optimizing load behavior in React using Node.js Express and SQL operations

As someone who is fairly new to programming, I have a question regarding the connection between server and client sides in applications like React and other JavaScript frameworks. Currently, I am working with a MySQL database where I expose a table as an ...

Optimal methods for handling Ajax requests in the present day

Recently, I revisited some websites I co-built with a friend and was working on getting them functional again. It's been a while since I've done any AJAX work, and I'm realizing that there aren't many resources available to help trouble ...