Troubleshooting AngularJS directives: Why ng-repeat isn't refreshing when communication is needed

Sorry for the mess, this is my first time on stackoverflow :)

Here is the link to the jsfiddle example: http://jsfiddle.net/1u1oujmu/19/

I am facing an issue with communication between directives and refreshing ng-repeat. I have two pages - homePage and dashboardPage. Everything works fine when I refresh the dashboardPage, but when I switch to the homePage and then back to the dashboardPage, problems start occurring.

Steps to reproduce the issue:

  • dashboardPage - reload - add a new link - list-link directive refreshes and the new link appears in the list
  • go to homePage
  • return to dashboard page
  • try to add a new link - after adding the link (on the server and receiving response), I call a factory to store the data:
dataFactory.editData("userLinksList", result.data);

//part of the factory to edit and propagate data
editData: function(name, data){
        dataArray[name] = data;
        $rootScope.$broadcast(name);
    },

Then in the directive controller, I have a condition to listen for propagation of "userLinksList" called checkRootScope, which serves as a flag for only registering one listener.

The problem seems to be in this line:

$scope.data.links = dataFactory.getData("userLinksList");

Although I receive new data in $scope.data.links, ng-repeat does not seem to refresh.

Interestingly, when I go to the homePage and return to the dashboard, the new link will appear in the list.

if(checkRootScope){
  $rootScope.$on("userLinksList", function () {
    $scope.data.links = dataFactory.getData("userLinksList");
  });
  checkRootScope = false;
}
  • homePage contains the list-link directive:

     <div class="columns marketing-grid">
         <div class="col-md-6">
             <list-link hp="true"></list-link>
         </div>
     </div>
    
  • dashboardPage also has the same directive without parameters:
<div class="row">
  <div class="col-sm-12 col-md-8">
    <list-link></list-link>
  </div>
</div>

Template of list-link:

<ul ng-if="data.links">
  <li ng-repeat="link in data.links | filter: search" class="link-list-item" data-id="{{link.id}}">
    <div class="row">
      <div class="col-md-9">
        <a ng-href="link.url"><h3>{{link.title}} <span>{{link.host}}</span></h3></a>
      </div>
      <div class="col-md-3 link-list-time text-right">
        {{link.date | date : 'd/MM/yyyy' }}
      </div>
      <div class="col-md-12">
        <blockquote ng-show="link.comment">{{link.comment}}</blockquote>
      </div>
      <div class="col-md-2">
        <span class="link-list-counter all" title="Number of links">{{link.counterAll}}</span>
      </div>
      <div class="col-md-6 link-list-tags">
        <span>tags:</span>
        <ul ng-if="link.tags">
          <li ng-repeat="item in link.tags"><a href="#" ng-click="">#{{item}}</a></li>
        </ul>
      </div>
      <div class="col-md-4 text-right link-list-buttons">
        <button class="btn btn-default btn-xs" title="Edit" ng-click="edit(link.id);">Edit <span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
        <button class="btn btn-default btn-xs" title="Delete" ng-click="delete(link.id);">Delete <span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
      </div>
    </div>
  </li>
</ul>

Directive list-link:

app.directive("listLink", ['path', function(path){
    var path = path.url(),
        checkRootScope = true;

    return {
        restrict : "E",
        scope : {
            hp : "="
        },
        templateUrl: path.template.listlink,
        replace : true,
        transclude : false,
        controller : ['$rootScope', '$scope','conn', 'auth', 'loaderService','stringOperation','dataFactory', function($rootScope, $scope, conn, auth, loaderService, stringOperation,dataFactory){

            var dataConenction = function(){
                conn.getData(path.server.link, { params : $scope.data })
                    .then(function(result){
                        if($scope.data.all == true){
                            dataFactory.addData("popularLinksList",result.data);
                            $scope.data.links = dataFactory.getData("popularLinksList");
                        } else{
                            dataFactory.addData("userLinksList",result.data);
                            $scope.data.links = dataFactory.getData("userLinksList");
                        }


                    }, function(msg){
                        console.log(msg);
                    });
            };

            $scope.hp = (typeof $scope.hp === "undefined" ? false : $scope.hp);
            $scope.path = path;
            $scope.userInfo = auth.getUserInfo();
            $scope.data = {
                auth : $scope.userInfo,
                check : false,
                all : $scope.hp
            };

            dataConenction();

            if(checkRootScope){
                $rootScope.$on("userLinksList", function () {
                    $scope.data.links = dataFactory.getData("userLinksList");
                });
                checkRootScope = false;
            }

            $scope.edit = function(id){
                $rootScope.$broadcast("editLink", {"id": id});
            };

            $scope.delete = function(id){
                var check = confirm("Are you sure you want to remove?");
                if (check == true) {
                    conn.deleteData(path.server.link, {"params" : {auth : $scope.userInfo, id : id}})
                        .then(function(result){
                            dataFactory.editData("userLinksList",result.data.links);
                            $scope.data.links = dataFactory.getData("userLinksList");

                            dataFactory.editData("userTagsList",result.data.tags);

                        }, function(msg){
                            console.log(msg);
                        });
                }
            };

        }]
    }
}]);

Answer №1

I'm not sure if you've already addressed this issue, but I took a shot at it.

Let's delve into the "why isn't it working" aspect -
Page1 establishes a new scope, which we'll call scope1.
Page2 also creates a new scope, referred to as scope2.

When Page1 is clicked, the data.link is set to 5 items and the following code is executed [scope1.data.link = 5 items] -

        if(checkRootScope){
            $rootScope.$on("userLinksList", function () {
                $scope.data.links = dataFactory.getData("userLinksList");
            });
            checkRootScope = false;
        }

Upon clicking on Page2, 7 items are assigned to dataFactory and broadcasted to trigger $rootScope.on to update scope2.data.links to 7 items. However, despite setting scope.data.links to 7, scope2.data.links remains at 5. The reason behind this is that when $rootScope.on is initially triggered, the "$scope" variable inside the "on" function points to the closure scope, i.e., scope1, and NOT scope2. Consequently, even though scope.data.links is updated to 7, scope2.data.links retains its value of 5.

In essence, ng-view generates a new scope, meaning that if a directive exists in each view, the data.link values will always differ between views.

To address this: There are two potential solutions:

Option 1: It might be more effective to set the value in the scope as soon as the promise resolves, rather than setting it in the factory and retrieving it within the $on listener, at least in this scenario.

http://plnkr.co/edit/IdrsO1OT9zDqdRiaSBho?p=preview

Option 2: If broadcasting is indeed essential, binding the data.link to rootscope may be necessary (though this may not be ideal practice).

http://plnkr.co/edit/VptbSKRf7crU3qqNyF3i?p=preview

Perhaps there are additional options to consider...

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

Error: Koa.js framework is unable to find the "users" relation in the Sequelize database

I am currently facing an issue while attempting to establish a relationship between two tables, 'user' and 'accessToken'. The error message I am encountering is hindering the process. Below are the models in question:- User model:- ...

Using JavaScript/JQuery to Access an External SQLite Database

Is there a way to incorporate my own SQLite database into a website using JavaScript and JQuery? I've searched for examples but have yet to find any helpful articles on the topic! ...

Placing two Slickgrid tables next to each other

Is there a way to arrange two slickgrid tables next to each other? Currently, I am creating two grids using grid = new Slick.Grid..., but the dimensions are hardcoded in CSS like this: #dynamic1 { /*this is grid one*/ position: absolute; top: 120px; ...

Exploring the internet with selenium

I'm currently facing difficulties navigating a website for information scraping with Selenium. The issue lies in the site's use of ng-click to update a table, requiring me to activate different tabs on the page in order to access the desired data ...

The Mapbox map fails to display properly upon initial page load

When my Mapbox map loads, I am experiencing issues with it only rendering partially. It seems that adjusting the width of the browser or inspecting the page will cause the map to snap into place and display correctly. To demonstrate this problem, I created ...

Ways to disable autofill in React Ant Design

I am currently working with Ant Design Forms within my React application. I am facing an issue where the browser's credential manager keeps auto populating the password field. Despite trying to add the DOM attribute autocomplete="off", it do ...

Navigate to a different state in Angular JS without altering the current URL

Hey there! I've been utilizing stateprovider for quite some time now, and I'm looking to implement a feature where I can transition to the not found state without altering the URL. Here's my code snippet: (function () { angular.module(&apo ...

How to utilize a Boolean return value in React Class component following a promise fetch operation

Hello, I have a question about a class I am working on in React. When I call Auth.isAuthenticated() from another component, it always returns false, even though the server is returning a 200 response which should set this.authenticated to true. How can I ...

Obtain the text that is shown for an input field

My website is currently utilizing Angular Material, which is causing the text format in my type='time' input field to change. I am looking for a way to verify this text, but none of the methods I have tried give me the actual displayed text. I a ...

What is the process for uploading an image using Vue.js?

Looking for guidance on how to upload an image using Vue.js. This is my HTML code to insert a picture: <input type="file" id="wizard-picture"> And here is my Vue.js code: <script> submitBox = new Vue({ el: "#submitBox", data: { usernam ...

Explore the latest update in the AngularJS single page application that introduces a new feature specifically designed for the initial login

Our AngularJS single page application has a new feature that we are ready to launch for customer use. We want to inform the logged in user about this new feature so they can start using it. We are looking for a small animated information symbol with a too ...

The Express module is encountering an error and cannot locate the helper function with the module titled "isPrime"

Looking to optimize my webapp by reusing an express.js block. For instance, I have a function called isPrime in my router file that I want to refactor and move to a separate helper file at ./helpers/isPrime: module.exports = function isPrime(num) { for ...

Disabling form submission when pressing the enter key

Is there a way to prevent a submit action from occurring when the enter key is pressed within an ASP:TextBox element that triggers an asyncpostback upon text change? Instead, I would like it to click on another button. The Javascript function I am using wo ...

A guide to verifying array inputs in Laravel 5 with the help of proengsoft/laravel-jsvalidation

Greetings! I am currently attempting to validate an array input and select option in the following format: <td width="23%"> {!!Form::select('mmscod_id[]',['' => '- Select a mate ...

The error message "Cannot access 'id' property of undefined" is being displayed

I have a file named auth.js along with a middleware called fetchuser. The code provided below is causing an error that I cannot figure out. The error occurs during the process of sending a token to the user and verifying whether the user is logged in or n ...

Collapsing tabs feature in Bootstrap 4

I am working on a project with Bootstrap 4 Tab. My goal is to initially hide all tab contents and then show them when the corresponding tab is clicked. I achieved this by removing the active class from the tab-pane div. However, I encountered an issue wher ...

Tips for redirecting once a JavaScript timer has run out?

Looking to update the code once the timer (See code) has run out. Currently, I am working on an exciting auction project for a friend and when the timer expires, I want to change the page so that no more bids can be placed. All bids are time-sensitive, so ...

The Gatsby and React navigator

Hey there, I've run into a little snag while working on my React component. I'm trying to display a pop-up using JS, but when I try to build my Gatsby site, I encounter an error stating: WebpackError: ReferenceError: navigator is not defined. Bel ...

Using Axios and Typescript to filter an array object and return only the specified properties

I'm currently working on creating an API to retrieve the ERC20 tokens from my balance. To accomplish this, I am utilizing nextjs and axios with TypeScript. However, I'm encountering an issue where the response from my endpoint is returning exces ...

What causes the error message "ng-model is undefined"?

Within my form, there are three angular-ui-bootstrap typehead elements <form> <div class="form-group"> <label for="fieldname" class="col-md-3 control-label">Name</label> <div class="col-md-6"> <input type="text ...