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

Is it possible to track unsuccessful email deliveries using MailApp?

In my Google Script program, I incorporate MailApp in the following manner: MailApp.sendEmail(AddressStringGlobal,EMailSubjectProperLanguageGlobal,"",{htmlBody: EMailBody}); The issue arises when I encounter a bad email address in my data set, causing my ...

Vue Js: Creating an array of checkboxes

I have a collection of checkboxes sourced from the main system object where I store all system settings (referred to as getSystem{}). Within this form, I am retrieving information about a User, who possesses an array of roles []. How can I cross-reference ...

JavaScript special character encoding techniques

I'm trying to create a function to remove special characters in my JavaScript code. However, whenever I try using chr(46), it throws a syntax error. Does anyone have any suggestions on how I can successfully implement chr(46) in my JS code? storageV ...

javascript issue with setting the id attribute on a select option

I can't seem to set the id attribute in my select element using JavaScript. When I inspect it, the id attribute isn't showing up... Here's the first method using JS: var selectorElem = document.getElementById('selector') var ...

Having an issue with saving multiple checkbox values in a CSV file using PHP. Unfortunately, only one value seems to be getting

I have encountered an issue with exporting data from a form to a csv file. While the radio buttons are working perfectly fine, I am facing problems in exporting the value of textarea and all selected checkboxes. Only one value is being exported, and I can& ...

Is it possible to substitute the template for the Angular UI Bootstrap accordion?

I'm currently using the Angular UI Bootstrap accordion alongside templates. My goal is to find a way to replace the injected template that comes with the accordion directive, without having to modify the actual UI library. Is there any possible method ...

Is it better to utilize a sizable JavaScript file or opt for a compact one?

I recently created a JavaScript file with over 6000 lines of code for various sections of my website. I'm debating whether to keep it as one large file or break it up into smaller parts and call them in their respective sections. What do you think? ...

Angular Date Filtering to Show dd-mm-yyyy Format

I am having trouble filtering the date correctly in my controller. My desired date format is Thu Mar 31 2016 05:05:00 GMT-0400 (EDT). However, when I use the code mentioned above, the results show up as 03-31-2016. This is the code snippet from my contr ...

How to set up $mdDialog in Angular Material before using it?

Upon the initial call to $mdDialog, there may be a slight delay as it initializes. However, subsequent animations are smooth. Is there a way to preinitialize $mdDialog so that it always appears smooth to the user? $mdDialog.show({ //contr ...

Exporting State From Another ReactJS Module: A Step-by-Step Guide

A new project is underway with 3 students who are diving into the world of React for the first time. To make our work more efficient, I suggested dividing the code so that each student could work on a different aspect simultaneously. However, when I attemp ...

Inconsistencies in date formatting between Javascript and PHP yield varying results

While working with PHP, I noticed this: echo date("Y/m/d",786668400); The output is 1994/12/06 However, when I tried the same thing in JavaScript: console.log(new Date(786668400*1000).getDate() + "." + (new Date(786668400*1000).getMonth() + ...

After loading Google Maps, initiate an AJAX request

Is there a way to determine if Google Maps has finished loading? I need to send an Ajax request once the map is fully loaded. Currently, I am displaying a group of users on a map with info windows. However, the browser becomes unresponsive due to the larg ...

"Embrace the powerful combination of WinJS, Angular, and TypeScript for

Currently, I am attempting to integrate winjs with Angular and TypeScript. The Angular-Winjs wrapper functions well, except when additional JavaScript is required for the Dom-Elements. In my scenario, I am trying to implement the split-view item. Although ...

Incorporate a pseudo class to a unique custom template or directive within an Angular project

I have been developing a custom dropdown menu directive in AngularJS. The issue I'm facing is that the buttons in my template become inactive when interacting with the dropdown menu, unlike a regular HTML select which remains active while the dropdown ...

Continuous polling with Ajax in Rails does not trigger the display of an alert box

Trying to implement ajax polling using the RailsCast tutorial on ajax polling (#229) but encountering an issue where the alert box doesn't pop up after running the server. Here's the code in app/views/quotes/index.js.erb: alert('Hey') ...

Troubleshooting issue with refreshing selectpicker in Bootstrap-select and Vue.js

Incorporating the bootstrap-select plugin (found at ) into a ruby on rails app with Vue.js as the javascript framework has been my latest project. The goal is to have two select options where one selects a category and the other displays all available tea ...

Error in AngularJS when passing object to modal dialog

I'm facing a challenge with an AngularJS application I'm developing. It involves displaying a list of contacts, each accompanied by a button that triggers a modal containing a form for editing the contact information. The issue arises when attemp ...

Communication between child and parent components in Vue.js is an essential feature

Attempting to invoke functions from my component to Vue for the login process. This is the code snippet of my component : Vue.component('auths', { data: function() { return { ip: '', sessiontoken: '' } ...

What is the best way to configure input fields as readonly, except for the one being actively filled by the user

Is there a way to make all input fields readonly except the one that the user is trying to fill data into? After the user loads the page index.php and attempts to input data into, for example, <input id="edValue2" ...>, I want to set all input field ...

Looking to switch from using HTTP to HTTPS in Node.js on localhost... encountering a few error messages

I'm facing an issue with integrating my code into the entire localhost project "app." It works fine with a simple implementation: https.createServer(options) But when I try to run it within the "app" project using the following setup: const server = ...