An issue with Angular $parse arises when attempting to filter or order hash values that begin with numbers

I have encountered a challenging situation with my angular orderBy filter. It works perfectly except when the expression starts with a hash followed by an integer.

Check out this fiddle to see the issue in action.

The filter structure I'm using looks like this:

[{'ced8d91c7921a884a131fcc7086239':{'value':'somevalue1'},
  '0a9308d3092d092718e457d927f110': {'value':'anotherval'}},
 {'ced8d91c7921a884a131fcc7086239':{'value':'axxfi'},
  '0a9308d3092d092718e457d927f110': {'value':'zziojasf'}}];

A filter predicate like 'somehash.value' will only work if the hash starts with a letter.

I need to filter based on hash ids because the data is dynamic and Angular doesn't know the property names beforehand.

Even attempting to filter in JS using $filter results in the same error.

In reviewing the call stack, it seems that the problem lies within the Lexer.lex function, specifically at this point:

else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {
    this.readNumber();

Any suggestions to fix this issue?

Answer №1

Create a Custom Filter for Sorting Hash Keys

When dealing with AngularJS, instead of struggling with the Lexer or $parse, it's often more efficient to implement a custom filter. By doing this, we can circumvent any issues with the Lexer and address our problem directly before reaching out to the Angular Team for further assistance.

Please note: This solution is specifically tailored for AngularJS 1.2.1 as indicated in your fiddle. Compatibility with newer versions may vary.

The following code snippet showcases a straightforward pseudo associative array sorter that utilizes a predicate string expression to facilitate value comparison:

In order to prevent referencing conflicts, we must transfer the values from arrOfObjects to our output array arr. Directly using angular.copy is not recommended due to its potential impact on digest cycles.

Below is the custom filter implementation, and you can access an updated fiddle here:

angular.module('orderByFail').filter('orderByHashKey', [
  function orderByHashKeyFilter() {

    // Parameters: array of objects, property expression as a predicate,
    //             and reverse flag
    // NOTE: The property expression is a dot-notation string (e.g., obj.key1.key2) rather than an Angular expression
    return function(arrOfObjects, propertyExp, reverse) {
      
      if (typeof propertyExp === 'undefined') return arrOfObjects;

      propertyExp = propertyExp.split('.');
      var len = propertyExp.length;
      var arr = [];

      for (var i = 0; i < arrOfObjects.length; i++) { arr.push(arrOfObjects[i]); }

      arr.sort(function (a, b) {
        var i = 0;

        while(i < len) {
          a = a[propertyExp[i]];
          b = b[propertyExp[i]];
          i++;
        }

        if (a < b) {
          return -!reverse | 1;
        } else if (a > b) {
          return -!!reverse | 1;
        } else {
          return 0;
        }
      });
      return arr;
    }
  }
]);

Answer №2

Instead of specifying a predicate, consider writing a getter function. Check out this example here

(function () {
  angular.module( 'orderByFail', [  
]);
    
function MyCtrl($scope, $filter, $log) {
    $scope.reverse = true;
    $scope.sortColumn2 = '0a9308d3092d092718e457d927f110.value';
    
    $scope.entries = [{'ced8d91c7921a884a131fcc7086239':{'value':'somevalue1'},
                       '0a9308d3092d092718e457d927f110': {'value':'anotherval'}
                     },
                   {'ced8d91c7921a884a131fcc7086239':{'value':'axxfi'},
                    '0a9308d3092d092718e457d927f110': {'value':'zziojasf'}
                   }];
    
    $scope.sort1 = function() {
        $scope.reverse = !$scope.reverse;
        $scope.sortColumn1 = 'ced8d91c7921a884a131fcc7086239.value'
    }
    
     $scope.sort2 = function() {
        $scope.reverse = !$scope.reverse;
        $scope.sortColumn2 = '0a9308d3092d092718e457d927f110.value'
     }
    
     $scope.sort = function(val) {
         var cols = $scope.sortColumn2.split('.');
         angular.forEach(cols, function(col, colKey) {
             val = val[col];
         });
         return val;
     }
}
    
angular
  .module('orderByFail')
  .controller('MyCtrl', MyCtrl)
  ;
})(); 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<div ng-app="orderByFail">
  <div ng-controller="MyCtrl">
    <button ng-click="sort1()">This sort works</button>
    <div ng-repeat="entry in entries | orderBy:sortColumn1:reverse">{{entry['ced8d91c7921a884a131fcc7086239'].value}}</div>
    <button ng-click="sort2()">This sort will error in console</button>
    <div ng-repeat="entry in entries | orderBy: sort:reverse">{{entry['0a9308d3092d092718e457d927f110'].value}}</div>
  </div>
</div>

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

Angular 2: Executing a function after ngFor has completed

Within Angular 1, I crafted a personalized directive called "repeater-ready" to pair with ng-repeat for triggering a callback method upon completion of an iteration: if ($scope.$last === true) { $timeout(() => { $scope.$parent.$parent.$ ...

Unable to maintain constant slide down feature for jQuery dropdown

I am currently working on a website for a client and I am still learning the ropes of jQuery. The website required a dropdown menu to display links to galleries in a list format instead of having them all on the navigation bar. However, I encountered an is ...

The Vue router-view is not showing certain views as expected

Apologies for the extensive text. All of my router-views are functioning properly, except for one specific view which appears blank. Despite meticulously reviewing the code multiple times, I cannot identify any errors or warnings in the console. The struct ...

Issue with Mongoose.connect functionality

Upon executing the command server.js in Node.js, I encountered the following error: C:\Users\Shaelyn\WebstormProjects\CIT366Projects\cms>node server.js C:\Users\Shaelyn\WebstormProjects\CIT366Projects\c ...

Karma test encountered a provider that could not be identified

I am working with a provider called $_ConfigProvider: (function (angular) { angular.module('app') .provider('$_Config', ConfigProvider); function ConfigProvider() { .... //routes definition } ConfigProvider.prot ...

Tips for implementing vue-multiselect tagging within an ASP.NET solution in Visual Studio 2017

I am attempting to implement vue-multiselect tagging, but encountering some errors such as: "vue.js:634 [Vue warn]: Unknown custom element: - have you registered the component correctly? For recursive components, ensure that the "name" option is provided ...

What is the best way to reset the 3rd dynamic dropdown menu once a new selection is made in the 1st dropdown menu?

I have been working on creating a dynamic dropdown using Jquery ajax and json in js. Almost everything is working as expected, except for one issue that I am facing. The problem arises when I select an option in dropdown A, which then loads items into drop ...

Having trouble with the checkbox functionality. Attempting to dynamically toggle gridlines in a flot chart

First, I'll share the code and then provide an explanation. Below is a snippet of the relevant HTML: <div id='gridButton'> <form> <input type="checkbox" id="gridCheck" value="showGrid">Show Grid </form ...

External API data is shown in the browser console but appears as undefined on the page

Can you please lend me a helping hand? I am facing a critical issue while attempting to retrieve data from an external API using axios in NextJS (Reactjs)/TypeScript through getServerSideProps. The data fetching is successful, and the JSON is returned on t ...

How to toggle classes on specific items generated with Vue JS's v-for directive

I have a list rendering using the v-for directive in Vue.js. <li v-for="group in groupList" :key="group.id" @dragenter="toggleClass ...."@dragleave="toggleClass ...." > Content </li> My goal is to apply a class to the li el ...

Enhancing Nativescript elements with pseudo selectors

Is there a way to apply the button:hover effect in Nativescript Buttons? I attempted the following code: Button:highlighted{ background-color: red; } Button:hover{ background-color: red; } Button:touch{ background-color: red; } ...

Updating HTML select options based on the result of another select can be easily achieved by using JavaScript and

Hello, I'm reaching out on StackOverflow for the first time because I've hit a roadblock and can't seem to figure it out. My goal is to populate a second select dropdown (with id=libres) with the results of a query from my database. The con ...

Automatically fill in text fields with data from a different collection when an item is selected in a collection select in Rails

Welcome everyone I've been struggling to solve this issue, but unfortunately I haven't made any progress yet. Currently, I am developing a Rails 3 application that deals with invoices and payments. Within the payment form, there is a collection ...

A website utilizing single-page architecture and HTML navigation through servlet technology, all without the need to open additional pages

I am interested in downloading files using a servlet when a link is clicked. My website is built using single page architecture in HTML. How can I trigger a servlet without changing the page when a link is clicked? I have been attempting to achieve this ...

What is the best way to iterate through an ID using jQuery?

After pulling the list of doctors in my area from the database and displaying it on my webpage, I now want to load each doctor's "About" content inside a Bootstrap modal. I added an "about" column within the same database table where the doctors' ...

What is the best way to eliminate the ng-hide class dynamically in AngularJS?

https://i.sstatic.net/ShZ3n.pnghttps://i.sstatic.net/n7UsG.pngI need to implement the image upload feature and facing an issue <div class="container responsiveImageSet"> <div ng-show="imageLoader" style="text-align: center;"> <img cla ...

Determine in VueJS v-for loop if the previous element in the object has changed, such as switching cities

I'm facing a dilemma here... I have an array structured like this: [{'city':'LA','store':'Bobs Burgers'},{'city':'LA','store':'Burger King'},{'city':'Sacra ...

Using jQuery to rearrange an ordered list by moving items with a specific class to the top

Is there a way to use jQuery to rearrange ordered list items with a specific class and move them to the top of the list? Consider the following snippet of HTML code: <div id="notice">click here</div> <ul> <li>Coffee</li> ...

What mechanism does angularjs employ to detect the $dirty state in the absence of a form tag?

I have implemented $window.addEventListener('beforeunload' to detect changes on a page successfully. Additionally, I am using $transitions.onStart... to monitor navigation with the browser buttons. I find it puzzling though, as my HTML template l ...

One method for assigning a unique identifier to dynamically generated buttons with jQuery

<table border="0" class="tableDemo bordered"> <tr class="ajaxTitle"> <th width="2%">Sr</th> <th >SM</th> <th >Campaign</th> <th >Day1</th> <th >Da ...