Choose All Box for Dynamic Tables in AngularJS

Hi everyone, I'm currently working on adding a select-all checkbox to the top of my list of checkboxes using a custom directive. I found some guidance on how to do this in a thread that I came across: https://github.com/lorenzofox3/Smart-Table/issues/270

However, I am encountering an error that reads TypeError: Cannot read property 'forEach' of undefined. If anyone could lend me a hand with this issue, I would greatly appreciate it. Thank you.

Here is the snippet of my HTML:

<div class="row">
      <div class="col-md-12">
        <table id="document-table" st-table="documents" class="table">
          <thead>
            <tr>
              <th>
                <st-select-all all="yourDisplayedCollection"></st-select-all>
              </th>
            </tr>
          </thead>
          <tbody>
            <tr ng-repeat="document in documents">
              <td><input type="checkbox" ng-model="checkedDocument"/></td>
            </tr>
          </tbody>
         </table>
      </div>
    </div>

And here is my Directive code:

.directive('stSelectAll', function () {
        return {
            restrict: 'E',
            template: '<input type="checkbox" ng-model="isAllSelected" />',
            scope: {
            all: '='
            },
            link: function (scope, element, attr) {

            scope.$watch('isAllSelected', function () {
                scope.all.forEach(function (val) {
                val.isSelected = scope.isAllSelected;
                })
            });

            scope.$watch('all', function (newVal, oldVal) {
                if (oldVal) {
                oldVal.forEach(function (val) {
                    val.isSelected = false;
                });
                }

                scope.isAllSelected = false;
            });
            }
        }
        });

Answer №1

If you don't want to watch everything, just focus on isAllSelected. Consider eliminating that watch entirely. I'm using the same directive with Smart Table and I never watch all. Ensure that all exists by adding a check:

scope.$watch('isAllSelected', function() {
  if(scope.all) {
    scope.all.forEach(function (val) {
      val.isSelected = scope.isAllSelected;
    }
  }
});

Additionally, remember to create a copy of your original array for the st-safe-src attribute in your table. Use the original array for your directive.

// Copy the original array in your controller
$scope.yourDisplayedCollection = [].concat($scope.documents);

Update your view accordingly.

<table id="document-table" st-table="documents" st-safe-src="yourDisplayedCollection" class="table">

<st-select-all all="documents"></st-select-all>

Answer №2

 each  <input type="checkbox" ng-click="ctrl.toggleAll(ctrl.all)" ng-model="ctrl.all">
 one    <input type="checkbox" ng-model="ctrl.checks.alpha" ng-value="allChecked">
 two    <input type="checkbox" ng-model="ctrl.checks.beta" ng-value="allChecked">

JavaScript Section

function MyController() {
    this.data = [
        {title: 'a', data: [1,2,3]},
        {title: 'b', data: [4,5,6]},
        {title: 'c', data: [7,8,9]}
    ];

    let ctrl = this;

    ctrl.checks = {
       alpha: false,
       beta: false
    };

    ctrl.toggleAll = function(toggle) {
        for (let check in ctrl.checks) {
            ctrl.checks[check] = toggle;
        }
   };
   return this;
}
angular.module('test').controller('MyController',MyController);

In this scenario, the child checkboxes will mirror the state of the parent checkbox instead of simply switching between states.

Hope you find it useful and please feel free to reach out if you encounter any issues or have questions.

Answer №3

To make changes in your javascript, update your directive as follows:

function modifyRowSelection() {
    return {
        require: '^stTable',
        $scope: {
            all: '=rowSelectAll',
            selected: '='
        },
        link: function (scope, element, attr) {
            $scope.isAllSelected = false;
            element.bind('click', function (evt) {
                $scope.$apply(function () {
                    $scope.all.forEach(function (val) {
                        val.isSelected = $scope.isAllSelected;
                    });
                });
            });

            $scope.$watchCollection('selectedItems', function(newVal) {
                var s = newVal.length;
                var a = ($scope.all !== undefined) ? $scope.all.length : 0;
                if ((s == a) && s > 0 && a > 0) {
                    element.find('input').prop('checked', true);
                    scope.isAllSelected = false;
                } else {
                    element.find('input').prop('checked', false);
                    $scope.isAllSelected = true;
                }
            });
        }
    };
}
app.directive('modifyRowSelection', modifyRowSelection);

In the HTML file, use your directive inside the table header and assign the displayed collection to it.

<th modify-row-selection="displayedCollection" selected-items="selected_items" ng-click="selectAll(displayedCollection)"><input type="checkbox" ng-disabled="displayedCollection.length == 0"></th>

If you need to select elements, include the following code:

    $scope.selected_items = [];
    // Function to get data for all selected items
    $scope.selectAll = function (collection) {
        // If 'selected_items' array is empty, push all elements into it.
        if ($scope.selected_items.length === 0) {
            angular.forEach(collection, function(val) {
                if (val.bank_flag) {
                    $scope.selected_items.push(val);
                }
          });

        // If there are items in 'selected_items', add only those that are not present.
        } else if ($scope.selected_items.length > 0 && $scope.selected_items.length != $scope.displayedCollection.length) {
            angular.forEach(collection, function(val) {

                var found = $scope.selected.indexOf(val);
                if(found == -1) {
                    $scope.selected_items.push(val);
                }

            });
        // Otherwise, reset the variable.
        } else  {
            $scope.selected_items = [];
        }
    };

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

AngularJS IP Address Sorting

My table has a header labeled IP Address, and I am using AngularJS to sort it. However, the sorting functionality does not seem to work properly on IP addresses. <th class="text-left"> <a href="" ng-click="sortType = 'device.ip_address&a ...

What steps should be taken to enable the "You and moderator can reply" feature in a bot when sending proactive messages to channels?

A project I am currently working on involves creating a bot that sends proactive messages to channels. The client has requested that I include options like No reply or You and moderator can reply with the messages posted by the bot proactively. Here is wh ...

Is there a way to fix the error "The requested resource does not have the 'Access-Control-Allow-Origin' header" within Express using Firebase functions?

Trying to send an email through nodemailer using Firebase functions, but encountering errors. The data for the email will come from a form. Error message: Access to XMLHttpRequest at 'my-firebase-functions' from origin 'my-angular-web-app&a ...

Unveiling the secret to accessing properties using v-if within a custom component template relocation

I'm currently working on an application that reveals a hidden div when the text "Create Test" is clicked. Everything works well when the code isn't placed inside the template of a component. This seems strange to me, what could be causing this is ...

What is the best way to display a Base64 image in a server-side DataTable?

This HTML code is designed to load server-side data into a table. The data is retrieved from the controller using AJAX requests. <script type="text/template" id="tablescript"> <td><%=Name%></td> <td><%=PhoneNumber%> ...

What is the process to insert a record into a table by triggering an AJAX call upon clicking "save

I'm looking to dynamically update a table with data from a database using AJAX. Specifically, I want the table to reflect any new records added by the user without having to refresh the entire page. Below is my JavaScript code snippet for handling thi ...

Tips for sending a set to a directive in angular.js?

Forgive me for my confusion. I am passing the name of a collection to my directive: <ul tag-it tag-src="preview_data.preview.extract.keywords"><li>Tag 1</li><li>Tag 2</li></ul> This is how the directive is defined: a ...

Employ the express platform to refrain from responding to particular inquiries

Is there a way for my server to not respond at all when receiving a specific user-agent in the request header, while still serving HTML normally for other browsers? I tried different methods like using res.status(404).end() and res.destroy(), but they did ...

Tips for testing an Angular factory function

I am attempting to run a test on a factory using protractor and angular.mocks Below is the code for the factory: angular.module('googlemarker', []) .factory('newMarker', newMarkerFactory); newMarkerFactory.$inject = ['$windo ...

Begin the process of setting up PDF.js on the website

I've been attempting to incorporate PDF.js into my website, but I'm struggling to do it correctly. When I try to display the PDF file on the screen, I encounter this issue: Although I can't see the PDF file on the screen, when I click on P ...

A unique technique for creating a stunning visual effect with images using

Can anyone help me with this issue: Check out this animated GIF The images in my project are overlapping when scrolling! How can I achieve a similar effect for my images? Is there a tutorial or plugin available for this? Here is the current code sn ...

Can a JavaScript function be sent back via AJAX from PHP?

Can a javascript function be returned via Ajax from php? Typically, I would just return a value and handle it in plain javascript. However, since I am working on an Apache Cordova mobile app, I need to approach things differently. account = localStorage.g ...

Arranging numerous Text elements within a solitary Drag and Drop container with the z-index property

I am facing a challenge with stacking twelve arguments in no particular order on a drag and drop element. The texts overlap each other, making it difficult for the end user to see them clearly when dragging and dropping. Is there a way to stack texts using ...

jquery function context

I'm having trouble grasping function scope in this scenario. When a button is clicked, it triggers a dialog box with a textarea inside displaying a URL that can be copied for camera setup. <button id="axis-details" onclick="apikey('<?php e ...

Is it possible to utilize two different versions of a JavaScript library on a single page without causing function conflicts?

My current project involves using multiple versions of the Nvd3 library for different charts on a single page within an Angular application. Each chart is loaded through its own template and requires a specific version of Nvd3 (e.g., v1.8 for partial_1.htm ...

How can I fix the issue of clearInterval not functioning properly in an Electron JS application?

The clearInterval function is not working properly in this code. What can be done to fix this issue? var inter; ipcMain.on("start-stop",(err,data)=>{ console.log(data.data) function start(){ inter = setInterval(fu ...

The ideal login page design

I apologize for my lack of knowledge in React, but I am quite new to it and have been struggling with this issue for days. I am having trouble creating a login page in ReactJS. Here is the code in my app.js: import React from 'react'; import {Ha ...

Upon employing the setTimeout method, the element with the id "sign-in-block" will have its display style set to "none" after a delay of 1000 milliseconds

I incorporated the setTimeout() function to make the HTML component appear for 1 second upon pageload. However, I would prefer this component not to load at all. Should I set the delay in the setTimeout() function to 0ms? Alternatively, is there another ...

Using AngularJS and Jasmine to tackle challenges in writing spec tests

After setting up my seed and successfully getting Jasmin Running (huge thanks to SoEzPz for the assistance), I encountered an issue with my specs. When I tried to write a spec on a controller, it resulted in errors. However, when running an isolated spec, ...

Tips for implementing jQuery on HTML loaded post document.ready():

I've encountered a scenario where I have multiple HTML elements being rendered by a JavaScript function on the page: <a href="#" class="test1">Test</a> <a href="#" class="test2">Test</a> <a href="#" class="test3">Test< ...