Is it possible for AngularJS custom filters to handle undefined arrays gracefully and still filter correctly?

I am currently working with an array of objects that are being assigned to the $scope within a controller. These objects are then filtered in multiple div elements within a partial template:

  <div class="entity-list">
    <!-- Folders -->
    <div class="entity-listing folder" ng-repeat="child in folders | filterName:nameFilter | entityType:filterType | orderBy:orderProp:orderAscDesc">
      <!-- Some HTML -->
    </div>
    <!-- Files -->
    <div class="entity-listing document" ng-repeat="child in documents | filterName:nameFilter | entityType:filterType | orderBy:orderProp:orderAscDesc">
      <!-- Some HTML -->
    </div>
  </div>

The filters can be found within a separate fieldset element:

  <fieldset id="filters">
    <legend>Filters</legend>
    <label for="filter-name">Name Contains:</label>
    <input id="filter-name" ng-model="nameFilter">
    <label for="filter-type">Show:</label>
    <select id="filter-type" ng-model="filterType">
      <!-- some options -->
    </select>
    <label for="sort-field">Sort By:</label>
    <select id="sort-field" ng-model="orderProp">
      <!-- some options -->
    </select>
    <select ng-model="orderAscDesc">
      <!-- some options -->
    </select>
  </fieldset>

I have incorporated two filters within a module, and then passed that module into my app:

angular.module('widget', ['filters']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/homefolder', {templateUrl: 'widget/partial/entity-list.html', controller: HomeFolderCtrl}).
      when('/folder/:uuid', {templateUrl: 'widget/partial/entity-list.html', controller: FolderCtrl}).
      otherwise({redirectTo: '/homefolder'});
  }]);
angular.module('filters', []).
  filter('entityType', function() {
    return function(items, type) {
      var returnArray = [];
      for (var i=0,ii=items.length;i<ii;i++) {
        if (type == "both") {
          returnArray.push(items[i]);
        } else if (items[i].type == type) {
          returnArray.push(items[i]);
        }
      }
      return returnArray;
    }
  }).
  filter('filterName', function() {
    return function(items, str) {
      var returnArray = [];
      if (str != '') {
        for (var i=0,ii=items.length;i<ii;i++) {
          if (items[i].name.indexOf(str) !== -1) {
            returnArray.push(items[i]);
          }
        }
      } else {
        returnArray = items;
      }
      return returnArray;
    }
  });

However, I am encountering errors in the error console stating

Cannot read property 'length' of undefined
specifically related to the filterName and entityType filters' for loops. To address this issue, I wrapped those filters in an if statement to check if items is defined (as seen in the modified filterName):

  filter('filterName', function() {
    return function(items, str) {
      var returnArray = [];
      if (items) {
        if (str != '') {
          for (var i=0,ii=items.length;i<ii;i++) {
            if (items[i].name.indexOf(str) !== -1) {
              returnArray.push(items[i]);
            }
          }
        } else {
          returnArray = items;
        }
      }
      return returnArray;
    }
  });

This modification eliminates the error and allows the code to function correctly. However, I am left wondering why AngularJS would pass in undefined items to the filters. Where else could these filters be getting called if they are only explicitly utilized in my two ng-repeat directives?

Answer №1

Can we assume that the information passing through your filters is fetched from the server asynchronously? Initially, when the page loads and angular processes everything, there is no data available, resulting in undefined values. However, once the data is received, the digest cycle runs again, and this time there is valid data, allowing everything to function properly. It is recommended to include a defined check at the start of the filter function for this purpose.

Answer №2

Upon page rendering, Angular thoroughly inspects all elements. In the event that initial data is missing, it is advisable to implement a check for undefined.

      app.filter('greaterThenHundred', function () {
    return function (items) {

        if (items === undefined)
            items = [];
        var filtered = [];
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            if (item.Salary > 100) {
                filtered.push(item);
            }
        }
        return filtered;
    };
});

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

Having issues with using jsonplaceholder.typicode.com as a data source in AngularJS

I am facing a challenge with my AngularJS project focused on creating a Users application. Instead of storing the users' data array within the controller, as I have already accomplished successfully in this example (jsFiddle), I aim to utilize jsonpl ...

Adjust the alignment of radio buttons in an HTML form based on the orientation of the device

As a newcomer to HTML and jQuery, I am currently working on an html form that will be used across multiple tablets. My goal is to have the available options displayed in two rows when the tablet is in portrait mode, like this: However, when the tablet is ...

Transferring variables from parent scope to the ui-view component

I'm currently utilizing angular-ui/ui-router and have directives/components with isolate scope declared for rendering on state change. $stateProvider .state('about', { url: '/about', template: '<about>&l ...

The request from localhost:3000 to localhost:3003 could not be proxied by ReactJS

Currently, I am working on developing a Single Page Application (SPA) using create-react-app with an expressjs server as the backend. During development, my frontend test server runs on port 3000 while my backend expressjs test server runs on port 3003. T ...

Learn how to prompt an event in Angular when the browser is closed instead of being refreshed

Is there a method to remove a token from local storage only when the browser is closed, rather than on refresh? I have attempted the approach below but it is also being removed on refresh. If possible, please suggest a more effective solution as my previ ...

Is it possible to customize the mounting element of NextJS or apply additional classes to the __next div?

In a nutshell, I'm currently working on a project where my aim is to make the content "fill" the vertical space below the static header. Previously, in React with tailwind, I achieved this like so: <body class="flex flex-col h-screen text-gray ...

How can you replicate a mouseover event using Selenium or JavaScript?

I have recently been working on a task involving web UI automation using Selenium, Javascript and SeLion. My goal is to capture a screenshot of a scenario similar to the Google homepage, specifically focusing on the "Search by voice" feature when hovering ...

Show a loading progress image during the page loading process (not during form submission)

Is there a way to show a loading GIF image while a page is loading or during postbacks using jQuery and JavaScript for long running tasks or processes that take a significant amount of time to execute? I attempted a solution but the loading image is not d ...

Tips for managing $rootScope in the provider's config function

Can someone help me understand how to work with $rootScope in a provider method? I'm unsure of how to properly inject it. that.app.config ['$authProvider', ($authProvider) -> $authProvider.configure apiUrl: '/api/v1&apos ...

Trouble with Bootstrap Modal not closing properly in Chrome and Safari

ISSUE: I'm facing a problem where clicking on the X (font awesome icon) doesn't close the modal popup as expected. https://i.sstatic.net/yXnwA.jpg LIMITED FUNCTIONALITY ON CERTAIN BROWSERS: Currently, the X button for closing the modal works o ...

Encountered an error while attempting to load resource: the server returned a 404 (Not Found) status code when trying to load an image in an

I am looking to dynamically load an image when it is selected from a file picker dialog. The code provided below attempts to achieve this, however, the image does not load into the img tag. <script src="https://cdnjs.cloudflare.com/ajax/libs/jq ...

The command "cordova" cannot be identified as a cmdlet

After running the npm command, Cordova was successfully installed on my system. The files and folders can be found in the directories %appdata%/npm and %appdata%/npm/node_modules. However, when attempting to use any Cordova command within the VS Code termi ...

Having difficulty linking the Jquery Deferred object with the Jquery 1.9.1 promise

I have been developing a framework that can add validation logic at runtime. This logic can include synchronous, asynchronous, Ajax calls, and timeouts. Below is the JavaScript code snippet: var Module = { Igniter: function (sender) { var getI ...

Ways to verify AJAX Response String when data format is specified as JSON

When using AJAX to retrieve JSON data from a webpage, it's essential to set the responseType to json. If the data processing is successful, a valid JSON string is returned, which works perfectly. However, if there's an error on the webpage, inst ...

"The challenge of achieving a transparent background with a PointMaterial texture in ThreeJS

When creating a set of particles with THREE.Points and using a THREE.PointMaterial with texture, I noticed that the transparency of the particles is working only partially. The textures are stroke rectangles created with canvas. Here is what my particles ...

What is the best way to prevent a React app's scripts from loading on browsers that do not support them?

My current project makes use of create-react-app, where the React script main.js is loaded at the bottom of the <body/> tag. However, it crashes on unsupported browsers upon loading. Above the main.js script block, there is another <script> th ...

What is the reasoning behind CoffeeScript automatically adding a function when extending an Object?

I'm currently working on a helper method to identify the intersection of two hashes/Objects in this manner... Object::intersect = (obj)-> t = {} t[k] = @[k] for k of obj t x = { a: 1, b: 2, c: 3 } w = { a: true, b: 3 } x.intersect(w) #=> ...

What is the process for performing a redirection in Node JS?

I have been working on a task to redirect a page to the home page with the route '/search' upon form submission. Within my submit.html file, there is a form that utilizes the '/submit' post method to submit the form data when the submit ...

Transfer the index of a for loop to another function

Can you explain how to pass the 'i' value of a for loop to a different function? I want to create a click function that changes the left position of a <ul> element. Each click should use values stored in an array based on their index posi ...

Preserving intricate nesting in a Mongoose schema

I've encountered a problem when trying to save nested subdocuments - I'm not certain if it's because they're not in an array or some other reason. The docs suggest that nested objects should be auto-saved, but that doesn't seem to ...