Filtering data from an Ajax request in Angular using a filter function with JSON

Hi everyone,

I recently started learning AngularJS and created a basic item list with search functionality and pagination. Everything was working smoothly, so I decided to move my list outside the controller and store it as a JSON file.

Here's what I did:

HTML

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" > <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Test angular</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script type="text/javascript" src="js/angular.min.js"></script>
        <script type="text/javascript" src="js/controllers.js"></script>
        <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
    </head>
    <body >

      <section class="app" ng-app="myApp" data-scope="$scope = myApp" > 

         <div ng-controller="myCtrl" data-scope="$scope = myApp.myCtrl">
            <input type="text" ng-model="search" data-scope="$scope = myApp.myCtrl.items(repeater scope)">
            Search = {{ search }}
            <div class="item" ng-repeat="item in newItems | filter:search | startFrom:currentPage*pageSize | limitTo:pageSize">
              {{ item.name }}
            </div>
             <button ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1">
              Previous
          </button>
          {{currentPage+1}}/{{numberOfPages()}}
          <button ng-disabled="currentPage >= items.length/pageSize - 1" ng-click="currentPage=currentPage+1">
              Next
          </button>
          </div>

      </section>



    </body>
</html>

Note: The data-scope attributes are used for scope visibility.

controllers.js

var myApp = angular.module('myApp', []); 

myApp.filter('startFrom', function() {
    return function(input, start) {
        start = +start; 
        return input.slice(start);
    }
});

myApp.controller('myCtrl', function($scope, $interval, $filter, $http){
    $scope.currentPage = 0;
    $scope.pageSize = 10;
    $scope.numberOfPages=function(){
        return Math.ceil($scope.items.length/$scope.pageSize);                
    }
    $scope.$watch('search', function () {
        $scope.currentPage = 0;
        $scope.newItems = $filter('filter')($scope.items, $scope.search);
        $scope.numberOfPages=function(){
            return Math.ceil($scope.items.length/$scope.pageSize);             
        }
    });   
    $scope.newItems = $scope.items;
    $http.get('js/items.json') 
       .then(function(res){
          $scope.items = res.data;          
        });


});

The JSON loads successfully, but there seems to be an error regarding the use of the startFrom filter:

TypeError: Cannot call method 'slice' of undefined

My assumption is that the filter is trying to slice something that isn't defined yet, possibly due to the ordering of operations.

UPDATE :

After initializing $scope.items = []; as suggested by VtoCorleone, the previous errors were resolved. However, a new issue emerged where the first page of the list doesn't display any items, although pagination works as expected.

My proposed solution involves setting two properties for items (items, newItems). items contains the original JSON data, while newItems stores filtered results. By using items, all items can be retained and restored if necessary.

Upon inspecting with Angular inspector, on page load, items is populated with the JSON data, whereas newItems remains empty. This leads to the items not displaying properly despite being available in the JSON. Why is this happening?

Answer №1

If you're wondering why the page isn't showing up:

The issue here is that your $watch is only on 'search'. So, when items are updated after an ajax callback, your numberOfPages remains at 0. It's only when you start searching that the watch function kicks in and updates numberOfPages.

To solve this, make sure to include the updating of pages within your ajax callback function.

$http.get('js/items.json') // retrieve json file
   .then(function(res){
      $scope.items = res.data; // assign data to items
      $scope.numberOfPages=function(){
        return Math.ceil($scope.items.length/$scope.pageSize);             
   }             
});

Answer №2

Success!!

myApp.controller('myCtrl', function($http, $scope, $interval, $filter){



    $scope.items = [];
     $http.get('js/items.json')
       .then(function(res){
          $scope.items = angular.fromJson(res.data);   
          $scope.newItems = angular.fromJson(res.data); // I set $scope.newItems directly in the Ajax response.
        });
    //$scope.newItems = $scope.items; // this doesn't work, don't know why.
    $scope.currentPage = 0;
    $scope.pageSize = 10;
    $scope.numberOfPages=function(){
        return Math.ceil($scope.newItems.length/$scope.pageSize);                
    }
    $scope.$watch('search', function () {
        $scope.currentPage = 0;
        $scope.newItems = $filter('filter')($scope.items, $scope.search);
        $scope.numberOfPages=function(){
            return Math.ceil($scope.newItems.length/$scope.pageSize);             
        }
    });  
    $scope.$watch('pageSize', function () {
        $scope.currentPage = 0;
        $scope.numberOfPages=function(){
            return Math.ceil($scope.newItems.length/$scope.pageSize);             
        }
    });       

});

Finally, I successfully set $scope.newItems directly in the Ajax response. Upon page load, newItems is already populated with all the elements. Then I updated numberOfPages(); to reflect the number of pages based on the newItems.

$scope.newItems = $scope.items;

If anyone knows why this line is not functioning as expected (newItems is empty on page load), please enlighten me :)

Answer №3

Encountered the same issue,

To resolve it, simply include this line in your filter: "input = input || '';"

.filter('startFrom', function() {
    return function(input, start) {
        input = input || '';
        start = parseInt(start,10);
        return input.slice(start);
    }
});

When the page loads, the filter is triggered but the value may not be loaded yet, causing "input" to be undefined at that point.

++

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

Is there a way to efficiently line up and run several promises simultaneously while using just one callback function?

I am currently utilizing the http request library called got. This package makes handling asynchronous http connections fast and easy. However, I have encountered a challenge with got being a promisified package, which presents certain difficulties for me ...

Displaying content on the <div> element

Looking for recommendations for a jQuery plugin or JavaScript solution that allows me to load a full "view" into a <div> when a user clicks on a link. The challenge I'm facing is that I have 8 pages, with the Homepage consisting of 3 divisions: ...

The JQuery script is not producing any results

After integrating a script into my website template, it is not functioning as expected. I suspect there may be a conflict with JavaScript, but upon inspecting with firebug, I am unable to identify any abnormalities. Here is the link for reference: Link ...

Validating emails using Vue.js

After spending a solid 24 hours working with Vue, I realize there may be some gaps in my knowledge. Despite my efforts to search for solutions, I suspect that my lack of understanding on basic principles is hindering me. One issue I've encountered is ...

Failed to set Firebase data: The first argument provided contains an undefined property

When it comes to creating an event, here's my approach: export const handleEventCreation = ({ title, time, location }) => { const newEventKey = firebase.database().ref('/events').push().key; const updates = {}; const eventDetails ...

Are Ajax and ASP.NET MasterPages a compatible duo?

Curious if anyone has ever tried using these two technologies together. Any challenges encountered when trying to make them work together? How would a website utilizing both of these technologies differ from a regular ASP.NET Web Application with Ajax? Ap ...

There was an unexpected error: Unable to access the 'icon' property of null

Whenever I try to edit a tab using the form, an issue arises. If I open the dialog box by clicking the edit icon and then hit save without altering the icon field, I receive an error message stating Uncaught TypeError: Cannot read property 'icon' ...

I'm confused why this code is functioning in JSFiddle but not on my HTML webpage

For the first time, I am encountering this issue. I am currently attempting to integrate this code into my application http://jsfiddle.net/TC6Gr/119/ My attempts include: Pasting all the jsfiddle code in a new page without my code, but it doesn't w ...

Looking to include an additional field in mongoose documents when generating a JSON object in a Node.js application?

var commentSchema = new Schema({ text: String, actions:[{actionid:String, actiondata:String}], author: String }) When retrieving the records, I require a count for action = 1. The desired outcome is to include this count as an additional key ...

Items seem to vanish into thin air and become immovable when attempting to relocate them

I am attempting to create a unique grid layout with 3x3 dimensions, where each grid item represents a fragment of a single image. These items should have the capability to be dragged and dropped inside another 3x3 grid, in any desired sequence. I have hit ...

Tips for transforming a container div into a content slider

Working with Bootstrap 3, a custom div has been created as shown below: <div class="second-para"> <div class="container"> <div class="second-section"> <div class="c ...

What is the process for transforming an HttpEntity into JSON format?

Is my approach correct if I want to fetch JSON data from a web-service and parse it? HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet(url); HttpResponse response; try { response = httpclient.execute(h ...

html output generated by backbone server

Recently, I've written some basic backbone code that fetches images from a specific directory using the following URL: 'uploads/'. The fetching process is successful, but the results I receive are basically an HTML list of the images in the ...

Display/Conceal content with JQuery on a PHP webpage

I am having trouble with the following code. My intention is to show/hide the content between the #info id when clicking buttons, but nothing seems to be happening. Could you help me identify the issue? echo '<script> $( "#show' . $r ...

Retrieve the most recently added child from the Firebase cloud function

Seeking assistance in retrieving the most recently added child in a cloud function. Below is the code snippet I am using and I'm curious if there is a specific function or query I can utilize to achieve this task without having to iterate through each ...

What is the best way to remove headers and footers programmatically in print pages on Safari using JavaScript?

Struggling with eliminating the header and footer on print pages in Safari using JavaScript? While disabling the header and footer manually can be done through print settings in most browsers, my aim is to automate this process with code to ensure that use ...

What are the best strategies for handling complex task operations in Node.js Express.js?

How can I effectively manage lengthy task functions in Node.js Express.js to prevent timeout errors? Currently, my application includes a time-consuming function that does not require an immediate response but still needs to execute its tasks. How can I en ...

AngularJS and Ionic Framework - Click on a specific row to interact with it

I am struggling to open a new page when an item is touched in my HTML code. Despite trying multiple times, I can't seem to make it work and I'm at a loss as to why. Below is the snippet of my HTML: <!DOCTYPE html> <html> <hea ...

"Utilizing JSON data to implement custom time formatting on the y-axis with AmCharts

Looking to convert minutes to hh:mm:ss format in my JavaScript code var allDataTime = [{ date: new Date(2012, 0, 1), "col": "LONG CALL WAITING", "duration1": '720', "duration2": '57', "duration3": ...

Is it possible to refresh user data in PHP without reloading the page using Ajax technology?

I implemented a user information update feature in PHP, but I encountered an issue where the form is embedded within one of the tabs on my website: After filling out the form and submitting it, the page refreshes and redirects me back to the first tab. H ...