Generating rows within Angular while implementing ng-repeat

In my code, I am facing an issue where posts from the API are being repeated and displayed in rows of 9. My objective is to create a grid layout with 3 rows, each containing 3 posts. Unfortunately, the solution I attempted did not work as expected. I also tried implementing 'clearfix', but that approach was unsuccessful as well. Does anyone have a solution for achieving this grid layout?

Below is the code snippet:

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

    myApp.config(function ($routeProvider) {
        $routeProvider.when('/', {
            templateUrl: 'allposts.htm',
            controller: 'PostsController'
        }).when('/post', {
            templateUrl: 'post.htm',
            controller: 'PostController'
        }).when('/addpost', {
            templateUrl: 'addpost.htm',
            controller: 'AddController'
        }).otherwise({
            redirectTo: '/'
        });
    });

    myApp.controller('PostsController', function ($scope) {
    });

    myApp.controller('PostController', function ($scope) {
    });

    myApp.controller('AddController', function ($scope) {
    });


    myApp.controller('controller', function ($scope, $http) {
        $scope.title = "My app";
        $http({
            method: 'GET',
            url: "http://jsonplaceholder.typicode.com/posts"
        }).then(function (response) {
            $scope.posts = response.data;
            $scope.post = response.data[0];
            $scope.viewby = 9;
            $scope.totalItems = $scope.posts.length;
            $scope.currentPage = 1;
            $scope.itemsPerPage = $scope.viewby;
            $scope.maxSize = 5;
        });

        $scope.setPage = function (pageNo) {
            $scope.currentPage = pageNo;
        };

        $scope.setItemsPerPage = function (num) {
            $scope.itemsPerPage = num;
            $scope.currentPage = 1; //reset to first page
        };

        $scope.getRowClass = function (index) {
            if (index % 3 === 0) {
                return "row";
            }
        };
    });
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>App</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js'></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-route.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-animate.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.1.3/ui-bootstrap-tpls.js"></script>
</head>

<body layout="column" ng-app="myApp" ng-cloak ng-controller="controller">
    <h1>{{title}}</h1>
    <a href="#post">Post</a> |
    <a href="#addpost">Add a post</a>
    <script type="text/ng-template" id="allposts.htm">
        View
        <select ng-model="viewby" ng-change="setItemsPerPage(viewby)">
            <option>9</option>
            <option>18</option>
            <option>36</option>
            <option>100</option>
        </select> posts
        <div layout="row">
            <div class="col-sm-4" ng-class="getRowClass($index)"
                 ng-repeat="post in posts.slice(((currentPage-1)*itemsPerPage), ((currentPage)*itemsPerPage))">

                <a href="#post">{{post.title}}</a>
                <hr>
                <p>{{post.body}}</p>
            </div>
            <div class="clearfix" ng-if="$index % 3 == 0"></div>

        </div>
        <ul uib-pagination total-items="totalItems" ng-model="currentPage" class="pagination-sm"
            items-per-page="itemsPerPage"></ul>

    </script>
    <script type="text/ng-template" id="post.htm">
            </script>
    <script type="text/ng-template" id="addpost.htm">
            </script>
    <div ng-view></div>
</body>
</html>

Answer №1

One issue that arises is the mixing of Angular Material and Bootstrap classes. To remedy this, it's best to stick with just Bootstrap, as shown in the following example.

Another problem occurs when creating a grid using 6 divisions with the .col-xs-4 class within a single .row element. The layout will only adjust properly if all 6 divisions are the same height. Otherwise, the display may end up looking messy like in your case.

To address this issue, consider creating multiple .row elements either by writing a directive in the view or organizing the list prior to passing it to the view.

The code snippet below shows an approach where the collation is handled in the controller before sending it to the view:

// Helper function for collating a list
Array.prototype.collate = function(collateSize) {
    var collatedList = [];

    if (collateSize <= 0) {
        return [];
    }
    angular.forEach(this, function(item, index) {
        if (index % collateSize === 0) {
            collatedList[Math.floor(index / collateSize)] = [item];
        } else {
            collatedList[Math.floor(index / collateSize)].push(item);
        }
    });

    return collatedList;
};

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

// Define routes for the app
myApp.config(function($routeProvider) {
    $routeProvider.when('/', {
        templateUrl: 'allposts.htm',
        controller: 'PostsController'
    }).when('/post', {
        templateUrl: 'post.htm',
        controller: 'PostController'
    }).when('/addpost', {
        templateUrl: 'addpost.htm',
        controller: 'AddController'
    }).otherwise({
        redirectTo: '/'
    });
});

// Controllers for different views
myApp.controller('PostsController', function($scope) {});
myApp.controller('PostController', function($scope) {});
myApp.controller('AddController', function($scope) {});

// Main controller handling data retrieval and pagination
myApp.controller('controller', function($scope, $http) {
    // Initialize variables and fetch data
    $scope.title = "My app";
    $http({
        method: 'GET',
        url: "http://jsonplaceholder.typicode.com/posts"
    }).then(function(response) {
        $scope.posts = response.data;
        $scope.viewby = 9;
        $scope.totalItems = $scope.posts.length;
        $scope.currentPage = 1;
        $scope.itemsPerPage = $scope.viewby;
        $scope.maxSize = 5;
        $scope.collatedPosts = getCollatedPosts($scope.posts);
    });

    // Function to collate posts based on current page and items per page
    function getCollatedPosts(posts) {
        if (!posts) {
            return [];
        }

        var paginatedPosts = posts.slice((($scope.currentPage - 1) * $scope.itemsPerPage), (($scope.currentPage) * $scope.itemsPerPage));
        return paginatedPosts.collate(3);
    }

    // Functions for pagination control
    $scope.setPage = function(pageNo) {
        $scope.currentPage = pageNo;
    };

    $scope.setItemsPerPage = function(num) {
        $scope.itemsPerPage = num;
        $scope.currentPage = 1; // Reset to first page
        $scope.collatedPosts = getCollatedPosts($scope.posts);
    };

    $scope.pageChanged = function(currentPage) {
        $scope.currentPage = currentPage;
        $scope.collatedPosts = getCollatedPosts($scope.posts);
    };
});
.row {
  /* Using red border for visual clarity */
  border-bottom: 2px solid red;
  margin-bottom: 10px;
  margin-top: 10px;
}
<html>

<head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js'></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-route.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-animate.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.1.3/ui-bootstrap-tpls.js"></script>
</head>

<body layout="column" ng-app="myApp" ng-cloak ng-controller="controller">
    <h1>{{title}}</h1>
    <a href="#post">Post</a> |
    <a href="#addpost">Add a post</a>
    <script type="text/ng-template" id="allposts.htm">
        View
        <select ng-model="viewby" ng-change="setItemsPerPage(viewby)">
            <option>9</option>
            <option>18</option>
            <option>36</option>
            <option>100</option>
        </select> posts
        <div class="row" ng-repeat="collatedPostList in collatedPosts">
            <div class="col-xs-4" ng-repeat="post in collatedPostList">
                <a href="#post">{{post.title}}</a>
                <hr>
                <p>{{post.body}}</p>
            </div>
        </div>
        <ul uib-pagination total-items="totalItems" ng-model="currentPage" class="pagination-sm"
            items-per-page="itemsPerPage" ng-change="pageChanged(currentPage)"></ul>
    </script>
    <script type="text/ng-template" id="post.htm">
  </script>
    <script type="text/ng-template" id="addpost.htm">
  </script>
    <div ng-view></div>
</body>

</html>

Answer №2

To accurately determine the total number of rows required based on your variables, consider incorporating an ng-repeat in your "row" div. Utilize the array to establish the desired quantity of elements without necessarily displaying them. Then, modify your existing ng-repeat to correctly segment the array from the appropriate starting point for the specified number of columns.

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 invoke a C# method upon completion of the callback function in ScriptManager.RegisterStartupScript?

I am currently developing JavaScript methods that will be called from C# code. Once the JS methods are complete, I need to include C# code to send an email. Can anyone provide guidance on how to achieve this? ScriptManager.RegisterStartupScript(this, G ...

Using jQuery Ajax to send data and retrieve responses in the Codeigniter framework

I am struggling with passing values in CodeIgniter and I need some guidance. Could you provide an example code snippet using CodeIgniter to send a value from a view to a controller using Ajax and jQuery, and then display the result on the same page? In my ...

Issue with retrieving data from controller in Spring MVC 3 using jQuery and AJAX via $.get method. The value is not being returned to the

I am currently diving into the world of AJAX, particularly in conjunction with Spring MVC. However, I am encountering some challenges along the way. Before delving into my actual real-time project requirements, I decided to test out the AJAX+Spring MVC+jQ ...

Go to a different page section using MUI 5

I am currently working on a React application and I want to implement a functionality where pressing a button on my Nav Bar will navigate to a specific section on the first page. To achieve this, I have created an onClick function for my button: const onNa ...

Tips for adjusting the height of a fixed-size child element on the screen using only CSS and JavaScript restrictions

I am faced with a challenge involving two child elements of fixed size: <div class="parent"> <div class="static_child"> </div> <div class="static_child"> </div> </div> .parent { border: 1px solid black; dis ...

Stop unwanted scrolling upwards by using jQuery ajax function $.load

I'm currently in the process of creating an ajax chat using jquery and php. Everything seems to be running smoothly except for one issue related to scrolling. Essentially, I've implemented a time-out function that automatically reloads the inner ...

Error message: "When using Webpack 4 with Bootstrap, a TypeError occurs where property 'jquery' is read as undefined."

I've recently delved into the world of webpack and everything seems to be running smoothly. However, when I run my webpack app, I encounter the following error within Bootstrap: var version = $.fn.jquery.split(' ')[0].split('.'); ...

Tips for wrapping a function call that may occasionally involve asynchronous behavior to ensure it runs synchronously

I am dealing with a function that functions as follows: _setDataChunk: function (action) { var self = this; /* some code */ var data = self._getDataChunk(action); populateWidget(data); } Sometimes GetDataChunk cont ...

Search across the entire table in your React application with Global

Having trouble implementing global search with the new Material UI Next table component. I have a handleSearch method that takes an event as a parameter and uses regex to check if the event.target.value matches any data in the table. However, when I dele ...

How can a variable that is potentially undefined be converted to lowercase in Node.js?

My latest project involves developing a discord.js bot with commands that can take different parameters like mc!start vanilla, mc!start tekkit. However, the bot is designed to handle only singular string entries. So, when a user inputs just mc!start with ...

Need to know how to invoke a function from an http callback function that resides in a separate file? Simply use the `app.get("/", callbackFun)` method

Directory Organization: testAPI contactDetail dispMobNo.js myModule.js index.js index.js const express = require("express"); const app = express(); const port = process.env.port || 3000; const getCustNo = require("./cont ...

What is the best method to calculate the total of multiple input values from various cells and display it in the final cell of an Angular table?

Hey there! I have a challenge where I need to calculate the sum of input values for each cell and display it dynamically in the last cell of the row. Take a look at the image below: https://i.stack.imgur.com/0iKEE.png In the image, you can see that the nu ...

Struggling with validating forms with JavaScript

I'm having trouble with the following JavaScript code: <script type="text/javascript"> function checkDetails(search) { var search = documment.getElementById('query'); if(search.value ==''||search.val ...

Error encountered in AngularJS and JSON server: [$injector:unpr] An unidentified provider was found: $resourceProvider <- $resource <- menuFactory

Hello everyone, I recently created a small AngularJS application and utilized a JSON server for my backend operations. Unfortunately, I am encountering an issue with the provider in my code. Upon running it, I am receiving errors as shown below: Uncaugh ...

The discrepancy between the heights of a div using Jquery and JavaScript

There is a container div encompassing all the site's content, which dynamically stretches. Additionally, there are multiple other divs that also stretch using the same method as in 20 other sites. Despite trying various methods with jQuery and JavaSc ...

Discover the pixel width of a Bootstrap grid row or container using JavaScript

How can I calculate the width of a Bootstrap grid row or container in pixels using JavaScript? I am working with Aurelia for my JavaScript project, but I'm open to solutions in standard JS (no jQuery, please). Looking at the Bootstrap documentation, ...

Implementing a switch feature with enable/disable functionality in a material table using table row data

Is there a way to incorporate an additional action in the Material table and have it included in the React material table along with the element? Furthermore, how can I obtain row data on onChange event while currently rendering it in the state? I would a ...

Properly managing mouseover events on a flipped div: tips and tricks

I created a div that flips when clicked using some HTML and CSS code. It works perfectly in Firefox 39 and Chrome 43. Here is the markup: <div class="flip-wrapper flippable-wrapper" id="fliptest-01"> <div class="flip-wrapper flippable ...

Protractor throwing error: 'Cannot access click property of undefined'

I need assistance with clicking on a specific CSS locator to perform a "math floor" operation. Can someone help me with this? The CSS code snippet in question: <input ng-attr-id="industry_{{$index}}" ng-attr-value="{{$index}}" ng-model="stateData.curr ...

The JavaScript error occurred: TypeError - Unable to access the property 'map' as it is undefined

import Link from 'next/link' export const getStaticProps = async () => { const res = await fetch('https://jsonplaceholder.typicode.com/users'); const data = await res.json(); return { props: { ninjas: data } } } const ...