Display table rows that are hidden in an HTML/Angular toggle function

I am relatively new to Angular and I have a task of setting up a table. The dataset that I have is as follows:-

data = [{rollno: 1,name: 'abc',subject: 'maths'},
        {rollno: 4,name: 'xyz',subject: 'history'},
        {rollno: 2,name: 'pqr',subject: 'history'}
       ];

My goal is to create a table with summarized rows based on this data. Upon clicking the expand button, sub-rows should be displayed below the summary row showing the actual data.

Here's an example for clarification:-

Expand/Collapse | No of Students | Subject
 click here        1                Maths
 click here        2               History

When I toggle the expand/collapse button on the second row, I expect the actual rows beneath it to appear as follows:-

 Expand/Collapse | No of Students | Subject
 click here        1                Maths
 click here        2               History
 RollNo | StudentName
   4       xyz
   2       pqr

I'm looking for advice on how to achieve this. Any assistance would be greatly appreciated!

Answer №1

1) Sorting the information according to subject

To begin, organize the data by subject and then calculate the quantity of items in each category.

You can utilize the angular.filter module's groupBy filter for this purpose.

1a) Add a dependency on that module as shown below:

var app = angular.module("yourModuleName", ["angular.filter"]);

1b) Subsequently, employ the groupBy filter within an ng-repeat directive on a <tbody> tag like so:

<tbody ng-repeat="(key, value) in data | groupBy: 'subject'">

1c) The data will now be structured in the format outlined below. This constitutes an object consisting of key/value pairs where "maths" and "history" function as keys, with the arrays serving as the corresponding values:

{
  "maths": [
    {
      "rollno": 1,
      "name": "abc",
      "subject": "maths",
    }
  ],
  "history": [
    {
      "rollno": 4,
      "name": "xyz",
      "subject": "history",
    },
    {
      "rollno": 2,
      "name": "pqr",
      "subject": "history",
    }
  ]
}

2) Presenting the organized data and tallying the entries in each category

Employ key and value to showcase the categorized data in a table as demonstrated here:

<table>
  <thead>
    <tr>
      <th>Subject</th>
      <th>Number of Students</th>
      <th>Expand/Collapse</th>
    </tr>
  </thead>
  <tbody ng-repeat="(key, value) in data | groupBy: 'subject'">
    <tr>
      <td>{{ key }}</td>
      <td>{{ value.length }}</td>
      <td>
        <button>
          Expand/Collapse
        </button>
      </td>
    </tr>
    <tr>
      <td colspan="3">
        <table>
          <thead>
            <tr>
              <th>Roll Number</th>
              <th>Name</th>
            </tr>
          </thead>
          <tbody>
            <tr ng-repeat="student in value">
              <td>{{ student.rollno }}</td>
              <td>{{ student.name }}</td>
            </tr>
          </tbody>
        </table>
      </td>
    </tr>
  </tbody>
</table>

Note the additional <tr> and nested table featuring another ng-repeat to exhibit the student details. At present, all nested student records will be visible; the subsequent step involves selectively displaying or concealing the nested tables based on the expand/collapse button clicked.

3) Revealing/Concealing the grouped student data

3a) Append an ng-click directive to the button so it transmits the key to an onExpandClicked function residing within your controller:

<button ng-click="onExpandClicked(key)">
  Expand/Collapse
</button>

3b) Formulate the onExpandClicked function within your controller:

$scope.onExpandClicked = function(name){
  $scope.expanded = ($scope.expanded !== name) ? name : "";
}

This assigns a value on the $scope which can determine whether to reveal/conceal a segment of student data in the view. The key is relayed into the function as the name parameter, whereby $scope.expanded will either adopt the value of name or reset to "" contingent on whether the provided name aligns with the current $scope.expanded content.

3c) Lastly, leverage the $scope.expanded variable within an ng-if directive featured on the second <tr> tag within <tbody> to show or hide the nested student data:

<table>
  <thead>
    <tr>
      <!-- Excluded for brevity -->
   </tr>
  </thead>
  <tbody ng-repeat="(key, value) in data | groupBy: 'subject'">
    <tr>
      <!-- Excluded for brevity -->
    </tr>
    <tr ng-if="expanded === key">
      <!-- 
        Excluded for brevity
      -->
    </tr>
  </tbody>
</table>

Demo

CodePen: Demonstrating how to display/hide categorized data created using the angular.filter module's groupBy filter

Answer №2

Create a unique table layout using HTML and utilize the ng-repeat loop to iterate through your data object for displaying the information dynamically.

For more information on how to effectively use ngRepeat, check out the official documentation here.

If you're looking for some simple examples of AngularJS tables, W3Schools offers tutorials on the topic. Check them out here.

Answer №3

To start, the best approach would be to replace the existing table with a div structure. Mixing two types of tables as you are planning is not feasible (if I understand correctly).

One way to achieve this is by toggling each row using ng-click along with the relevant expanded content. Here's an example of how it can be done (pseudo code for illustration):

<div class="row-header">
  <span>RollNo</span>
  <span>StudentName</span>
</div>

<div class="row-content" ng-if="!row_4_expanded" ng-click="row_4_expanded = !row_4_expanded">
  <span>4</span>
  <span>xyz</span>
</div>

<div ng-if="row_4_expanded">
  <div class="row-expanded-header">
    <span>No of Students</span>
    <span>Subject</span>
  </div>
  <div class="row-expanded-content">
    <span>1</span>
    <span>Math</span>
  </div>
  <div class="row-expanded-content">
    <span>2</span>
    <span>History</span>
  </div>
</div>


<div class="row-content" ng-if="!row_2_expanded" ng-if="row_2_expanded" ng-click="row_2_expanded = !row_2_expanded">
  <span>2</span>
  <span>pqr</span>
</div>

<div ng-if="row_2_expanded">
  <div class="row-expanded-header">
    <span>No of Students</span>
    <span>Subject</span>
  </div>
  <div class="row-expanded-content">
    <span>1</span>
    <span>Math</span>
  </div>
  <div class="row-expanded-content">
    <span>2</span>
    <span>History</span>
  </div>
</div>

By clicking on a row, you will toggle its corresponding expanded content display.

Answer №4

Check out this practical solution that will address your issue.

var mainCtrl = ['$scope', function($scope){
  $scope.count = 0;
  $scope.data = [{id: 1,name: 'john',category: 'science'},
        {id: 4,name: 'jane',category: 'history'},
        {id: 2,name: 'doe',category: 'literature'}
       ];
  $scope.toggleDisplay = function(id){
    $scope.count = id;
  };
}];
<!DOCTYPE html>
<html ng-app>
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body ng-controller='mainCtrl'>
<table>
  <tr>
  <td>Expand/Collapse</td>
  <td>Student Count</td>
  <td>Category</td>
  </tr>
  <tr ng-repeat='item in data' ng-class="count == $index ? active : none">{{}}
    <td ng-click='toggleDisplay($index)'><a href="javascript:void(0)">click here</a></td>
    <td>{{$index +1}}</td>
    <td >{{item.category}}</td>
   </tr>
</table>
  <table>
  <tr>
  <td>ID</td>
  <td>Name</td>
  </tr>
  <tr ng-repeat='item in data'>
    <td ng-show='count == $index'>{{item.id}}</td>
     <td ng-show='count == $index'>{{item.name}}</td>
  </tr>
</table>
  <style>
   table tr td{
        border: 1px solid black
    }
</style>
</body>
</html>

I trust this solution meets your needs.

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

How should an iterable be sorted in React?

Let's break down the scenario using pseudo code: {this.props.myIterable.map((iterable) => { return ( <div>iterable.somevalue</div> ) }).sort((a,b) => {return b - a}) To clarify, I am iterating over certain props and displaying ...

Transform basic text into nested JSON structure with JavaScript

There is a plain string in my possession which contains various conditions. const optionString = '{2109} AND ({2370} OR {1701} OR {2702}) AND {1234} AND ({2245} OR {2339})'; The goal is to transform this string into an object structured as foll ...

Incorporating jQuery to Load Content into a DIV while preserving the original JavaScript

I am attempting to implement the following <script> $(document).ready( function() { var data = 'testing' $("#about").on("click", function() { $("#main-content").load("/about.html"); ...

Is there a way for me to determine if something is hidden?

My goal is to have selector B toggle when selector A is clicked or when clicking outside of selector B. This part is working fine. However, I'm struggling with preventing selector B from toggling back unless selector A is specifically clicked - not w ...

unable to show image retrieved from JSON data

Looking to showcase the data from my JSON objects, which are displayed in 2 images below https://i.stack.imgur.com/yhqFy.png https://i.stack.imgur.com/DUgFO.png In the data, I have properties like c_name, max_slots, and an array slots. Within the array, ...

angular.js:13920 Alert: [ngRepeat:dupes] Multiple occurrences in a repeater

I encountered an issue while attempting to parse a JSON file and map it in HTML. Here is the JavaScript code snippet: searhController.orderlogs.results = JSON.stringify(response.data); This is how it's implemented in Angular: <tr ng-hide="searh ...

What sets apart Angular's $http.post from jQuery's $.post?

What is the difference between Angular's $http.post and jQuery's $.post? $http.post() vs $.post() Does $http.post() internally use $.ajax from jQuery or does it create its own XMLHttpRequest? I am currently experiencing an issue with Angular&a ...

obtain data in JSON format from a Node.js server and display it on an HTML

I am currently working on a feature that involves sending an AJAX request to the server and receiving the output of a MySQL query on the page http://localhost:3000/result.html upon clicking a button. <body> <form action="/setLocation" method=" ...

Is it possible to adjust the scroll top position using inline style in angularJS/CSS?

I am working on storing the scrollTop value of a vertical menu in my controller so that I can set it up each time I return to the page for persistent scrolling. Does anyone know how I can achieve this? This is the code snippet I am currently using: < ...

When attempting to toggle the view on button click, it is not possible to select a shadowRoot

I am facing an issue with my parent component named ha-config-user-picker.js and its child component called edit-user-view.js. Parent Component: It contains a mapping of users and includes the child component tag along with its props. When a click event i ...

I can't seem to retrieve any values from the API other than "chicken"

Is there a way to make the search bar in my recipe app look for recipes that I provide, rather than fetching data from useState? Any suggestions on how I can achieve this? import React, { useEffect, useState } from 'react'; import Recipe from &ap ...

The issue of duplicate results appearing in the Wikipedia viewer persists even after conducting a second search

I have been working on a project to create a wiki viewer, but I've encountered an issue. Currently, I am utilizing the Wikipedia API. When a user enters a search query, they are presented with 5 possible articles (title and first sentence), and upon ...

Generating and saving a text file in a React Native application

Is there a way to convert a string into a text file within the client application and then download it directly onto a phone? If so, how can this be achieved? ...

Arranging two <ul> elements within an angular template

I need assistance with aligning two ul blocks. Currently, they are displaying next to each other, but their alignment is starting from the bottom instead of the top: <div class="ingredients-container"> <div style="display: inline-block; width: ...

Update the promise status to reflect any changes

While attempting to modify the button text based on the promise status, I created a custom directive for this purpose. Below is the code snippet for my custom directive: .directive('myDir',function(){ return { scope: { ...

ngResource is mistakenly handling POST requests as if they were GET requests

It has come to my attention that despite specifying "POST" in my ngResource factory, the parameters are actually being passed as GET. Here's an example of a user factory: myApp.factory('facUser',['$resource', function ($resource) ...

Storing the information received from an API as an HTML element

My HTML file contains JavaScript, along with a URL that displays data retrieved from an AWS lambda API call via AWS API Gateway. The page initially appears blank and the data is structured like this: [ {"user": "bob", "groups": ["bobsGroup"], "policies": ...

Utilize a standard JavaScript function from a separate document within a function of a React component

I am facing an issue where I need to incorporate a standard JavaScript function within a React component function. The script tags are arranged in the footer in the following order: <script src="NORMAL JAVASCRIPT STUFF"></script> // function ...

Get rid of the title on Superfish Menu in Drupal 7

Exploring Drupal for the first time, I've been able to find solutions to all my queries except one - removing the "Main Menu" header from my superfish menu. The region called superfish has successfully had superfish added to it, but I'm unable t ...

Ways to circumvent route handling in Angular UI Router

I'm currently developing a web application where most of the functionality is implemented as an AngularJS single-page application. However, there are also some static content pages that are served traditionally. The navigation within the SPA utilizes ...