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

Struggling to configure an input field using ExtJS

I am trying to use an onChange event to update an input field with the selected option. Below is my code: HTML: <select id="builds" onchange="setBuild()"> <option value="select">Select</option> ... </select> <input ty ...

Directive's nested function fails to trigger popup alert

Can I access the showData() function from the controller in a directive that is not within it? The alert is still not working. Any advice on what could be going wrong? var myApp = angular.module('myApp', []); myApp.controller('pr ...

I am looking to have my page refresh just one time

I have created an admin page where I can delete users, but each time I delete a user, the page requires a refresh. I attempted to use header refresh, but this action caused my page to refresh multiple times. Is there a way to ensure that my page only refr ...

Tips for encoding AngularJS ng-model in real-time

Recently, I embarked on a new project and wanted to incorporate some AngularJS magic. The only obstacle is my limited expertise in AngularJS or JavaScript, making it difficult for me to figure out how to make it work. One key requirement is that the functi ...

A guide on converting JSON strings into arrays using Javascript

In my JavaScript program, I have a Mocha test that checks if all available currencies are displayed in a drop-down list: it('displays all available currencies in drop down list', () => { return invoiceEditPage.details.currencyDropDown.dr ...

Alter a prototype method belonging to another module

If I wanted to create a custom plugin or module that alters the behavior of an object exported in another module, how can I go about modifying one of its methods? The code below illustrates my attempt at achieving this, but it seems like there may be a cru ...

Filtering and selecting tables in HTML

I am dealing with an HTML table that combines static data and MySQL input. The filtering functionality is working properly, but I am struggling to add the options "yes" and "no" to the selection list. These values are test inputs fetched from MySQL. I need ...

Updating the regex pattern for the date format to dd-M-yy in jQuery Validation Engine

Snippet for validating date format using JavaScript: "date": { // Custom function to check if date is valid with leap year consideration "func": function (field) { //var pattern = ne ...

What are the best practices for securely using JSON.stringify in JavaScript?

When I use JSON.stringify on a string that includes <script> tags, the script tags somehow escape and show up in the body of my document, causing unexpected results with the "injected" data. I'm puzzled by how they manage to escape, considering ...

Tips for testing watch expression in a directive using unit tests

I'm a beginner when it comes to unit testing and I couldn't find a solution to my issue anywhere online. That's why I decided to turn to the community for help. I have a directive that looks like this: angular.module('app') ...

Display a dynamic array within an Angular2 view

I have a dynamic array that I need to display in the view of a component whenever items are added or removed from it. The array is displayed using the ngOnInit() method in my App Component (ts): import { Component, OnInit } from '@angular/core' ...

AngularFire and Ionic - There is no data being sent to the server from the form

I am using Ionic and AngularFire to build my app, but I have encountered a new issue: the form data is empty! Only the fields in my Firebase database are visible. How can I retrieve the user-entered form data from the Firebase database? Here is a screensh ...

What is the method to render certain text as bold using a json string?

I need assistance with concatenating two strings in react while ensuring that the first string is displayed in bold, while the second one remains unchanged. The first string I want to emphasize is stored in a JSON file, and the second string comes from an ...

Sketch a variety of numerical values in a circular formation

I was working on a number circle using the below fiddle, but I need it to always start from 0 at the top. How can I achieve this? Additionally, I would like to connect the numbers from the inner circle border to the number with a dotted line. How can I dr ...

What is the best way to restrict a text box in angularjs to only accept numerical input

Hi there, I'm new to AngularJS. How can I make a textbox accept only numbers but show an error if the user enters a decimal value or a string in AngularJS? <div class="col-md-6 col-sm-6"> <label class="col-md-5 col-sm-5 pad-top5 pad-l ...

"Troubleshooting: Angular ng-show not triggering correctly upon first loading of the

Utilizing Angular's ng-show directive to adjust the display of questions in a quiz and show a result upon completion, everything is functioning as intended except for the initial question. Upon loading the quiz, $scope.image is initialized as false. S ...

Rotate an object upwards in three.js in order to achieve dynamic movement and enhance

I'm struggling with 3D calculations and could really use some assistance. In my scene, I have a sphere representing the earth and I'm using OrbitControl to "rotate" it (although in reality, OrbitControl rotates the camera). I need a function, s ...

Implementing a permanent class following an incident

Is it possible to dynamically add a class to an element when an event occurs rather than based on a condition? For example, I have a td that displays a variable. <td>{{myVar}}</td>//myVar=10 When the variable changes to myVar=15, I want to ad ...

Is there a way to determine if jQuery lightslider has been initialized, and if so, how can I effectively remove the instance?

Currently, I have integrated the JQuery lightSlider into my project. Despite some code adjustments, it is functioning well. My goal is to dynamically replace the lightSlider content with data returned via AJAX, which I have successfully achieved. After r ...

Store the value of $scope.data in a variable within the same controller

Here is the issue with my code: $scope.data = {}; var init = function () { $http.post('views/Report.aspx/GetMailReport', {}) .success(function (data, status, headers, config) { $scope.data ...