Tips for organizing and refining ngTable data that is stored in milliseconds?

I'm new to Angularjs and I could use some assistance with sorting dates in milliseconds in descending order, as well as implementing a filter for the table columns. I've set up a plunker example, but when I enter a filter parameter, the data doesn't seem to be filtered properly, and it disappears from the table.

Can someone help me with sorting the date column and setting up a case-insensitive filter search? Below is the code I am currently using:

<table ng-table="tableParams" show-filter="true" class="table">
  <tr ng-repeat="item in $data" height="10px">
    <td data-title="'Date'" filter="{ 'item[0]': 'date' }" sortable="'item[0]'">{{translate(item[0])}}</td>
    <td data-title="'Count'" filter="{ 'item[1]': 'text' }" sortable="'item[1]'">{{item[1]}}</td>
  </tr>
</table>

$scope.translate = function(value) {
    if (value == null || value == undefined)
        return value;
    var monthNames = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
    var myDate = new Date( value );
    return myDate.getDate() + " " + monthNames[myDate.getMonth()] + " "+myDate.getFullYear();
}
$scope.tableParams = new ngTableParams({
    page: 1,
    count: 10       
}, {
    total: $scope.tasksRunDataForTable.length,
    getData: function($defer, params) {
        
        var sortedData = params.sorting() ?
                            $filter('orderBy')($scope.tasksRunDataForTable, params.orderBy()) :
                            $scope.tasksRunDataForTable;
        var orderedData = params.filter() ?
               $filter('filter')(sortedData, params.filter()) :
               sortedData;
        params.total(orderedData.length);
        $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
    }
});

Update

I managed to get the filter working for the count column, but I'm still struggling with filtering dates and sorting on both columns. Here's the link to the updated plunker.

<td data-title="'Count'" filter="{ '1': 'text' }" sortable="'1'">{{item[1]}}</td>

Answer №1

Sorting Dates

The issue at hand is not with ngTable itself, but rather the inner workings of the angular filter for 'OrderBy'.

To address this, simply utilize valueOf()[0] and valueOf()[1] where 0 & 1 represent the indexes of your inner array. Below is the HTML code that doesn't require any modifications to your getData callback function:

<table ng-table="tableParams" show-filter="true" class="table" >
    <tr ng-repeat="item in $data" height="10px">
        <td data-title="'Date'" filter="{ '0': 'text' }" sortable="valueOf()[0]">{{ item[0] | date: 'd MMM yyyy HH:mm' }}</td>
        <td data-title="'Count'" filter="{ '1': 'text' }" sortable="valueOf()[1]">{{ item[1] }}</td>
    </tr>
</table>

Note that there is no need to translate dates from milliseconds as it can be achieved using the 'date' angular filter.

For further reference, check out a related post on Stack Overflow:

Filtering Dates (from string)

To enable filtering based on dates, you'll need to implement a custom "comparator" function as the third argument when doing filtering on your controller. Here's an example snippet to get you started:

var dateComparator = function(obj, text) {
   var valueAsText = obj + '';
    if (valueAsText.length == 13) { // must be in milliseconds.
      valueAsText = $filter('date')(obj, 'd MMM yyyy HH:mm');
    } 
    return !text || (obj && valueAsText.toLowerCase().indexOf(text.toLowerCase()) > -1);
};

In your controller's getData callback function:

getData: function($defer, params) {
        var sortedData = params.sorting() ?
                            $filter('orderBy')($scope.tasksRunDataForTable, params.orderBy()) :
                            $scope.tasksRunDataForTable;

        var filterInfo = params.filter();
        var comparer = (filterInfo && filterInfo['0']) ? dateComparer : undefined;

        $log.log(angular.toJson(filterInfo))

        var orderedData = filterInfo ?
               $filter('filter')(sortedData, filterInfo, comparer) :
               sortedData;

        params.total(orderedData.length); 

        $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
    }

UPDATE: The answer has been updated to address filtering concerns. UPDATE 2: Further updates have been made to handle searching based on both date and count.

For a complete demo, refer to this plunker example: http://plnkr.co/edit/D2n7MdAfugXpKeKOGosL?p=preview

I hope this explanation proves helpful.

Answer №2

Here is the approach I took:

        $scope.tableParams = new ngTableParams({
        page: 1,            // displaying first page
        count: STATIC_CONST.COUNT_PAGAING,         // determining count per page as crucial 
        sorting: { Id: "desc" }

    }, {
        total: data.length, // calculating length of data
        paginationMaxBlocks: 13,
        paginationMinBlocks: 2,
        getData: function ($defer, params) {

            var filters = angular.copy( params.filter() );
            //var filters = params.filter();
            var filteredData = data;

            //Implementing Custom filters:
            if (typeof filters['LastUpdateDate'] !== 'undefined') {
                filteredData = $filter('filterByUI')(filteredData, 'LastUpdateDate', filters['LastUpdateDate'], $filter('date'), ['dd.MM.yyyy']);
                delete filters['LastUpdateDate'];
            }

            //Applying General filters:
            if (filters) {
                // using built-in angular filter
                filteredData = $filter('filter')(filteredData, filters);
            }


            //if (filters.FromDate) {
            //    filteredData = $filter('filterDates')(data, filters.FromDate);
            //}

            var orderedData = params.sorting() ?
              $filter('orderBy')(filteredData, params.orderBy()) :
              filteredData;


            params.total(orderedData.length); // setting total for recalculating pagination
            $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
        }
    });

In Layout.html:

<table ng-table="tableParams" show-filter="true" class="table" >
<tr ng-repeat="item in $data" height="10px">
    <td data-title="'Date'" filter="{ 'LastUpdateDate': 'text' }" sortable="valueOf()[0]">{{ item[0] | date: 'd MMM yyyy HH:mm' }}</td>
    <td data-title="'Count'" filter="{ '1': 'text' }" sortable="valueOf()[1]">{{ item[1] }}</td>
</tr>

\apps\app.module.js:

app.filter("filterByUI", function () {

    debugger;

    return function (arrayData, dateKey, dateValue, filterFunction, filterFunctionParams) {
        var returnarr = [];
        returnarr = arrayData.filter(function (element) {
            var evalCode = "filterFunction( element." +dateKey;
            filterFunctionParams.forEach(function (element, index, array) {
                evalCode += ", filterFunctionParams["+index+"]";
            });
            evalCode += ")";

            try{
                var dudi86 = eval(evalCode);

                if(typeof dudi86 === 'number') {
                    dudi86 = dudi86.toString();
                }

                if(typeof dudi86 === 'string') {
                    return dudi86.toLowerCase().indexOf( dateValue.toString().toLowerCase() ) > -1;
                }

                if( Array.isArray(dudi86) ) {
                    if( Array.isArray(dateValue) ) {
                        return dateValue.every( function(val) { return  dudi86.indexOf(val) >= 0; } );
                    }

                    if(typeof dateValue === 'string' || typeof dateValue === 'number') {
                        //TODO: Consider this case:
                        return dudi86.indexOf( dateValue.toString().toLowerCase() ) > -1;
                    }
                }



            }catch(e){
                console.log("app.filterByUI: Error on evaluating: " +evalCode);
            }


            return false;

        });

        return returnarr;

    }
});

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

Using Redis for pub/sub functionality within or outside of the io.connect callback

Is it preferable to move the redis subscription event outside of the io.connect callback if the intention is to broadcast the data to all connected users? Or would it be better to keep it inside the io.connect callback, as shown below: io.on('con ...

What is the best technique to incorporate dark/light mode in Bootstrap 5?

Is it best to introduce themes such as dark and light themes in Bootstrap 5 using CSS/SCSS, JavaScript, or a combination of both? Should we create a separate CSS file like dark.css to overwrite classes? Or should we use JavaScript to switch classes like ...

Utilizing the power of AngularJS directives along with the functionality of a

I am completely new to angular js, but I have successfully integrated a jQuery UI datepicker into my Angular JS project. Now, I am facing the challenge of formatting the date selected by the jQuery datepicker into ISO date format. Here is the code snippet: ...

calling requestAnimationFrame from within a freshly created instance

I'm encountering an issue with executing an animation. Specifically, this problem arises within var ob1 = function() {};. Once triggered, the animation runs for a brief period before I receive the error message Uncaught RangeError: Maximum call stack ...

I can't figure out why my unslider isn't adapting to the screen size. Check out the fiddle for more details

I recently implemented unslider to create a slideshow that spans 100% of the width on my website. Everything seemed to be working fine until I tried resizing the screen, and the slides remained the same size as they were initially loaded. Here is the code ...

Execute asynchronous JavaScript request

When a user types something into the input id=2, an ajax function triggers. Here is the HTML: <input id="2" type="text" onkeyup="posttitulo(this.value)" /> And here is the SCRIPT: function posttitulo(value){ $.post("getdata/posttitulo.php",{p ...

Has the Angular 2 community established a standardized ecosystem?

As a developer specializing in Angular 1, I am now eager to dive into the world of Angular 2. However, navigating through the changes and rewrites can feel like traversing a confusing maze. All of the comprehensive guides I have come across date back to l ...

Tips for identifying a pair of numbers (with varying ranges) in which one number must be present at all times

I am currently trying to understand the regex I have implemented in Angular 2 using Typescript: /[0-5]?[0-9]?/ Surprisingly, this regular expression works flawlessly to match any valid minute from 1 to 59, even though it seems like an empty string would ...

"Identify the protocol name (string) based on a specific port number in TCP/UDP communication

Is there a built-in function in any web-oriented language to return protocol names based on port numbers? For example, if we have the following code: protocol = get_protocol_name(22) print protocol We would expect it to print out "ssh". A more detailed ...

jQuery array objects are not compatible with Semantic UI transitions

My goal is to transition a jQuery object based on its index within an array. This code successfully transitions all objects with the page class: $('.page').transition() And this code targets only one object, but not based on index: $('$p ...

What is the ideal location to set up Content Security Policy?

I am working with an angular application that interacts with a REST API hosted on either Tomcat or Jetty, depending on the setup. The angular-app itself is deployed as a war file on the same tomcat/jetty server. In some cases, the Tomcat setup includes Ap ...

How to conditionally prevent event propagation to children in VueJs

This Vue component is called ColorButtonGroup, and it serves as a group of checkbox/toggle buttons. It has a maximum limit of 4 colors that can be selected. The component utilizes another component called ToggleButton, which is a simple toggle selection w ...

Javascript's associative arrays: a versatile tool for data organization

Is there a way to achieve the same functionality in JavaScript as this PHP code?: $this->gridColumnData[] = array('field' => 'id', 'width' => 50, 'title' => 'Enquiry Id') ; $this->gridColumn ...

Having trouble with Vue.js implementation of Bootstrap tab navigation?

I am currently working on a vue.js application that consists of 2 routed components. I recently attempted to integrate a bootstrap tab navigation into the first component, but unfortunately, the tab contents are not being properly displayed. <templat ...

What is the best way to test the output of HTML code in a unit test scenario

I am new to web development and testing, taking it slow. I have a website with a button that reveals information when clicked. How can I create a test case to ensure that the displayed output is correct? I need to verify that the text appears on the scre ...

The shared global variable or store feature is currently not functioning as expected in Vue JS

Currently, I am in the process of developing a Simple Web application using Vue JS for educational purposes. Although I am new to Vue JS and still learning the ropes, I have encountered an issue with sharing a state variable across all components. In my a ...

Searching for specific items within an array of objects using Mongoose

Currently, I am working with a Mongoose schema that looks like this: var MessageSchema = new Schema({ streamer: { streamer_username: String, streams: [{ id: String, messages: [{ date: String, ...

Utilizing factory service within a decorator in AngularJS

Utilizing the TextAngular plugin and attempting to customize a toolbar, I am striving to inject my own service (LinkService) into the module but encountering an [$injector:unpr] Unknown provider issue. module.config(function($provide, LinkService){ $p ...

Sending data between two elements when a jQuery event is triggered

As a JavaScript beginner, I am facing an issue where I need to push data from an h1 tag to a textarea. My website is built using WooCommerce and when a visitor clicks on a product, a chat box with the product title opens. Currently, I have successfully p ...

When a React component mounts repeatedly, it can lead to complications within the useEffect hook

In our React application, we have implemented a custom hook to send data to Google Analytics. To avoid sending duplicate values, we included a unique "marker" string that captures the value of the data being sent. The hook generates a new "marker" each tim ...