Unbounded scrolling with Ionic

Currently, I am integrating Wordpress as the backend for my app and facing challenges in implementing infinite scroll due to issues with concatenating articles.

To fetch the data, I have created a service using a factory:

.factory('Worlds', function ($http) {
    var worlds = [];

    storageKey = "worlds";

    function _getCache() {
        var cache = localStorage.getItem(storageKey );
        if (cache)
            worlds = angular.fromJson(cache);
    }
    return {
        all: function () {
            return $http.get("http://www.examplesite.com/tna_wp/wp-json/posts?filter[category_name]=international&filter[posts_per_page]=10").then(function (response) {
                worlds = response.data;
                console.log(response.data);
                return worlds;
            });
        },

        GetNewPosts: function () {
            return $http.get("http://www.examplesite.com/tna_wp/wp-json/posts?filter[category_name]=international&filter[posts_per_page]=2").then(function (response) {
                worlds = response.data;
                console.log(response.data);
                return worlds;
            });
        },
        get: function (worldId) {
            if (!worlds.length) 
                _getCache();
            for (var i = 0; i < worlds.length; i++) {
                if (parseInt(worlds[i].ID) === parseInt(worldId)) {
                    return worlds[i];
                }
            }
            return null;
        }
    }
    })

Additionally, here is how my controller is structured:

.controller('WorldCtrl', function ($scope, $stateParams, $timeout, _, Worlds) {
    $scope.worlds = [];
    Worlds.all().then(function (data){
      $scope.worlds = data;
      window.localStorage.setItem("worlds", JSON.stringify(data));
    }, 

    function (err) {
      if(window.localStorage.getItem("worlds") !== undefined) {
        $scope.worlds = JSON.parse(window.localStorage.getItem("worlds"));
      }
    }
  );

  $scope.loadMore = function() {

    Worlds.GetNewPosts().then(function (worlds){
        var loadedIdss = _.pluck($scope.worlds, 'id');
        var newItemss = _.reject(worlds, function (item){ 
           return _.contains(loadedIdss, item.id); 
      });
      $scope.worlds = newItemss.concat($scope.worlds);
      $scope.$broadcast('scroll.infiniteScrollComplete');
      });
    };

})

My aim is to utilize underscore to filter out already loaded posts, however, the infinite scroll seems to be stuck in a loop fetching more posts without displaying them in my ng-repeat, and the ionicLoading feature is making the app unresponsive.

Answer №1

ion-infinite-scroll is designed to work with paginated results, but it appears that you are feeding your list with all the results at once.

Here is an example of how your API should be structured:

http://www.examplesite.com/tna_wp/wp-json/posts?filter[category_name]=international&filter[posts_per_page]=2&filter[page]=1

Notice the addition of the page filter.

Your data service responsible for fetching the data should look something like this:

.factory('dataService', function($http) {
   return {
      GetPosts: function(page, pageSize) {
        return $http.get("http://mywebservice/api/test/posts/" + page + "/" + pageSize);
      }
   };
});

Your controller should initialize an array of objects and a boolean flag to indicate when you've reached the end:

$scope.posts = [];
$scope.theEnd = false;

You can also have variables to manage pagination:

var page = 0;
var pageSize = 10;

Load items when the view is loaded:

$scope.$on('$stateChangeSuccess', function() {
    $scope.loadMore();
});

The $scope.loadMore function increments the page number:

page++;

and calls the data service:

dataService.GetPosts(page, pageSize)

When you reach the end of the data stream, set the end flag:

$scope.theEnd = true;

to inform the directive that no more items can be appended.

.finally(function() {
    $scope.$broadcast("scroll.infiniteScrollComplete");
});

The finally block is executed when the promise is resolved.

Instead of using ng-repeat, consider using collection-repeat for improved performance.

You can test this functionality here.

Answer №2

Here's a suggestion: create a function called

infiniteScrollCompleteCancelLoadMore
and use it when you reach the end of your list to stop the scrolling.

function infiniteScrollCompleteCancelLoadMore() {
        $timeout(function () {
            $timeout(function () {
                $scope.$broadcast('scroll.infiniteScrollComplete');
                $rootScope.canLoad = false;
            });
        });
    }

$scope.loadMore = function() {
   Worlds.GetNewPosts().then(function (worlds){
      var loadedIdss = _.pluck($scope.worlds, 'id');
      var newItemss = _.reject(worlds, function (item){ 
         return _.contains(loadedIdss, item.id); 
   });
  $scope.worlds = newItemss.concat($scope.worlds);
  infiniteScrollCompleteCancelLoadMore() // MAKE A CHANGE HERE  
  });
};

Include this snippet in your HTML

<ion-infinite-scroll on-infinite="loadMore()" ng-if="canLoad" distance="1%"
                         immediate-check="false"></ion-infinite-scroll>

OR You can also use this function if you just need to cancel the loadMore loop.

function infiniteScrollComplete() {
        $timeout(function () {
            $timeout(function () {
                $scope.$broadcast('scroll.infiniteScrollComplete');
            });
        });
    }

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

Using Ionic 4 with Angular to set the root of the application and control navigation with the back button

There has been a consensus to avoid using NavController in Ionic 4 and instead utilize Angular's router. For those not utilizing lazy loading, routes are set up like this: { path: '', component: WalkthroughComponent }, { path: 'login& ...

Customizing a WordPress theme by integrating content directly into the PHP script

I am currently in the process of revamping the homepage of my WordPress website. The homepage code is written in PHP, and I need to find a way to Change some of the image files Modify the text below those image files I have created new versions of the ...

Moving a function from the controller to the directive

After examining my angular controller, I realized that it is expanding and should ideally focus on passing data. Currently, there is a function within my controller that calculates the number of months' worth of data displayed (within a 12-month peri ...

How to pass a method from a child component to a parent component in Vue.js

Does anyone know how to pass a function from the child component to the parent component? I have a modal in the parent component with cancel and submit buttons. When either button is clicked, I want to close the child component. I tried setting "show" in t ...

Running `grunt serve` with CORS enabled allows for cross

Our team utilizes grunt serve for live recompiling and reloading of our web application, allowing us to make edits and see changes in almost real-time. The webapp is built using AngularJS, which means that all interactions on the site are done through API ...

Confirm Submission Issue in HTML Form

During my testing of the blacklist confirmation dialog, I encountered an issue where clicking the OK button did not submit the form as expected. Instead, it seemed to be stuck in a loop where clicking the button had no effect and the dialog remained on scr ...

How to use the window.confirm method to print the HTML tag in an AJAX post

Is there a way to display a confirmation window for users who want to delete data from the database without including HTML tags like <strong> or <br />? I am currently using the confirm() function as follows: var str = document.getElementById ...

How can I modify a dynamically generated table to include rowspan and colspan attributes in the rows?

My table was automatically created using data from the database. var rows = ""; rows += "<tr class='row_primary'>"; rows += "<td>COL 1</td>"; rows += "<td>COL 2</td>"; rows += "<td> ...

Showing options in the navigation bar upon user authentication with Passport in NodeJS

When a user is connected, I want the navbar to display "Profile of: {USER}", otherwise it should show a set of Sign up/Login tabs. The challenge lies in using EJS with separate "head.ejs" and "header.ejs" sections placed in a /partials folder within the / ...

The application denied the request to establish an insecure header with the label "Host", communicating using Ionic framework

Despite setting the access-control-allow-origin →* header in the response header from the server side, I am still unable to access the data from the Chrome browser. My approach in Ionic for loading data is as follows: var h = new Headers(); h.set("Host ...

unable to render a vector layer in openlayers 6

Currently, I am facing an issue with displaying a vector layer on an openlayers map using the source of local geojson and gpx files in my Vuejs project. Unfortunately, even when testing outside of Vue.js, the vector layer is not being displayed. Here is t ...

Expand or reduce the displayed content based on the preset value in Angular

I am trying to implement a "Show More" and "Show Less" functionality for a product's description. It works fine with normal strings, but when I try to apply the same logic to the value with {{product.description}}, the entire value inside {{product.de ...

The PHP post method is unable to retrieve the value of a button tag

In my code file login.php, I have the script to validate if the user exists or not, as well as an AJAX call. Inside the form, there is a button tag; When I set type='submit', the PHP works but the AJAX does not; and when I use type='button&a ...

having difficulty choosing a particular identifier from a JSON string

I'm currently working on a project to create an admin page for managing client information. However, I've encountered an issue where I am unable to select the client's unique ID to display all of their information on a separate page. On the ...

Adding an arrow to a Material UI popover similar to a Tooltip

Can an Arrow be added to the Popover similar to the one in the ToolTip? https://i.stack.imgur.com/syWfg.png https://i.stack.imgur.com/4vBpC.png Is it possible to include an Arrow in the design of the Popover? ...

The filter for Woocommerce, when added through the add_filter(‘woocommerce_product_get_price’) function, does not take effect when triggered by an ajax call

I have implemented the Role Based Pricing for WooCommerce plugin to customize prices based on user roles. Although the filter works correctly when I call the functions to retrieve products, it always returns the default price value when the function is ca ...

Getting your JQuery ready() statement right is crucial for the proper

I have come across all three variations below: $().ready(); $(document).ready(); $(document.body).ready(); All of them seem to work, but I'm wondering which one is the most appropriate or recommended to use when considering the usage of the ready() ...

Top approach for inserting Class instance into a group

I need some guidance on how to approach this issue. I am interested in creating a set of objects similar to the example below: Person P = new Person(); P.Name = 'John'; P.Surname = 'Dough'; var People = []; People.push(P); Can this b ...

Encountered a glitch while trying to install React JS using npx create-react-app xyz

After entering the command in the terminal, I encountered an error stating: npm Err! code-ENOENT npm Err! syscall lstat npm Err! path Interestingly, this same command worked perfectly on my instructor's laptops. For reference, I have attached a snaps ...

Encountered an issue with locating the module 'webpack-cli/bin/config-yargs' while attempting to run webpack-dev

Encountering an error while trying to start the webpack dev server with the command provided below. Despite suggestions that it could be due to outdated webpack versions, I am confident that all components are up to date: [email protected] [email ...