0

I have to use AngularJS to build a dashboard and one of the components is a table. Since I did not find relevant dependencies/libraries for angularjs (like tabulator or datatables), I am doing it myself.

Instead of using the native angular filter, I built a custom method, but I am not sure if I am following a good approach.

The main idea is that when I pull the data object (array of objects) via Ajax, I create both an "original" and a "current" data object,s and at the beginning, they are exactly the same of course.

Then I created an input field above every column heading and I linked the search function to the blur and keyup events (enter key).

When the search function is triggered, I start making changes to the "current" object. This way I can filter by multiple columns incrementally. I filter the data object using an awesome library called AlaSQL. I also linked to a button the "reset" method, which simply makes the "current" object equal to the "original" object, and cleans up the input fields.

The point is, am I missing any best practices? Are there better ways to do so with AngularJS? Any suggestions?

Thanks a lot.

HTML

  <div ng-app="myApp">
    <div ng-controller="divController">
      <my-table></my-table>
    </div>
  </div>

JS

   var app = angular.module('myApp', []);

    app.controller('divController', function ($scope, $http) {
      $scope.data = {};
      $scope.data.current = null;
      $scope.data.original = null;

      $scope.filter = {
        id: {
          field: "id",
          value: null
        },
        name: {
          field: "name",
          value: null
        },
        owner: {
          field: "owner",
          value: null
        },
      }

      $scope.reset = function () {
        console.log("reset");
        $scope.data.current = $scope.data.original;

        for (let prop in $scope.filter) {
          $scope.filter[prop]["value"] = null;
        }
      }

      $scope.filterExec = function (field, value) {
        if (value) {
          console.log(`Executing filter on field "${field.trim()}" by this value "${value.trim()}"`);
          var filtered = alasql('SELECT * FROM ? where ' + field + ' LIKE "%' + value + '%"', [$scope.data.current]);
          $scope.data.current = filtered;
        }
      }

      $http.get("./workspaces_demo_obj.json")
        .then(function (response) {
          console.log(response);
          $scope.data.original = response.data;
          $scope.data.current = response.data;
        });

    });

    app.directive('myTable', function () {
      return {
        template:
          '<div>Total rows {{data.current.length}} <button ng-click="reset()">RESET</button></div>' +
          '<table class="table table-responsive table-sm">' +
          '<thead>' +
          '<tr><th>Workspace ID</th>' +
          '<th>Name</th>' +
          '<th>Owner</th></tr>' +
          '<tr><th><input ng-model="filter.id.value" ng-blur="filterExec(filter.id.field, filter.id.value)" ng-keydown="$event.keyCode === 13 && filterExec(filter.id.field, filter.id.value)"  placeholder="Filter by id"></input></th>' +
          '<th><input ng-model="filter.name.value" ng-blur="filterExec(filter.name.field, filter.name.value)" ng-keydown="$event.keyCode === 13 && filterExec(filter.name.field, filter.name.value)" placeholder="Filter by name"></input></th>' +
          '<th><input ng-model="filter.owner.value" ng-blur="filterExec(filter.owner.field, filter.owner.value)" ng-keydown="$event.keyCode === 13 && filterExec(filter.owner.field, filter.owner.value)" placeholder="Filter by owner"></input></th></tr>' +
          '</thead>' +
          '<tbody>' +
          '<tr ng-repeat="x in data.current">' +
          '<td>{{ x.workspace_id }}</td>' +
          '<td>{{ x.name }}</td>' +
          '<td>{{ x.owner }}</td>' +
          '</tr>' +
          '</tbody>' +
          ' </table>',
        restrict: 'E'
      };
    });

Mauro
  • 102
  • 14
  • First of all: do you _have to_ use AngularJs? The framework is heavily outdated and any new project should use Angular instead. – jBuchholz Jan 04 '21 at 09:19
  • I don't see the need for AlaSQL here. You could just use `Array.prototype.filter` as in `$scope.data.current = $scope.data.current.filter(el => el[field].contains(value))` – jBuchholz Jan 04 '21 at 09:21
  • Yes, I must use it since I am working on a platform that only supports this technology (Service Portal Widgets in ServiceNow). Thanks for the tip regarding alaSQL, but since the platform does not even support fat arrow function and other modern JS things, I prefer to use a line of alaSQL to keep the syntax clean. What do you think about the filter method itself? – Mauro Jan 04 '21 at 09:27
  • The general idea is good. A problem might arise because technically both `original` and `current` point to the same array. If you were to edit a value inplace in `current` it would also be altered in `original`. – jBuchholz Jan 04 '21 at 09:46
  • Since Angular uses TypeScript it is compiled to JavaScript. You should be able to select a JavaScript-version that suits your needs (via `tsconfig.json` file). – jBuchholz Jan 04 '21 at 09:48
  • In angularjs you can create a custom filter too in which you can compare value of an object with old and changed one for each instances. – Sunny Jan 04 '21 at 23:56

0 Answers0