Angular datatables sorting issue - angularjs

I am using this example https://l-lin.github.io/angular-datatables/archives/#!/bootstrapIntegration to configure my data tables. The problem is it won't sort the date and double price.
So far I try to sort the date but failed. I did find a lot of answers but no one is working.
My javascript
$scope.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withOption('order', [0, 'desc']);
$scope.dtColumnDefs = [
{ targets: 0, type: 'date' }
];
My html
<table datatable="" dt-options="dtOptions" dt-column-defs="dtColumnDefs" class="row-border hover"></table
I also tried something like
$scope.dtColumnDefs = [
DTColumnDefBuilder.newColumnDef(0).withOption('type', 'date'),
];
And I did tried change the date to dd/MM/yy but not working. My date in column is showed as 23/03/19

DataTables' date sorting is based on Date.parse() so any not-parseable date (or timestamp) will break the sorting.
A date in north european notation ala 23/03/19 parses to NaN, and there you have your problem. You can parse the date in a render() callback :
DTColumnDefBuilder.newColumnDef(0).renderWidth(function(data) {
data = data.split('/')
return Date.parse(data[1]+'-'+data[0]+'-'+data[2]).valueOf()
})
or you can use a custom sorting plugin like date-eu -> https://datatables.net/plug-ins/sorting/date-eu

Related

Angular loop from the received data from JSON

I pass array ImageList to view
res.render('imagelist', { title: 'Imagelist',listImages:imageList });
In view there are this skope (for example):
$scope.planets = [
{
name : 'Mercury',
distance : 0.4,
mass : 0.055
},
{
name : 'Venus',
distance : 0.7,
mass : 0.815
}
]
How I can add data from listImages to the scope in the loop?
Past one varible to scope:
$scope.planets = [
{
name: <%- JSON.stringify(title); %>,
distance: 0.4,
mass: 0.055,
test: 'test'
},
];
But I need to send the array (first code part).
Question: I need to pass array (List) to Angular frontEnd. There I use a table with filtering.
There I use a table with filtering. This table will get data from the scope (See the example above).
But I want to transfer an arbitrary number of rows in a list and display them in a table. How can I do that? I need a cycle in scope, but I do not understand how to write it.
Table code:
<table>
<tr><th>Name</th><th>Average Distance</th><th>Mass</th></tr>
<tr><td><input ng-model="f.name"></td><td><input ng-model="f.distance"></td></td><td><input ng-model="f.mass"></td></tr>
<tr ng-repeat="p in planets | filter:f"><td>{{p.name}}</td><td>{{p.distance}}</td><td>{{p.mass}}</td><td>{{p.test}}</td></tr>
</table>

ChartJS: Translate x axis month to other languages

I'm having difficulties in finding out how to translate the time axis. I'm using MMM YYYY for time displayFormats in xAxes.
It always displays date like May 2018. Does anyone know how to localize here?
For example, if the language is french, the month should be displayed as Mai instead of May. I searched everywhere, only find someone said it is possible to do that using time.parser, but I am not sure how to do that.
Any suggestions would be appreciated.
I was struggling with the same problem in my Ruby on Rails application.
We don't use angularjs, but I think the way of using Chart.js is very similar.
I will post the way I managed it to work in Ruby on Rails and polish locale. But you should be able to easy customize the solution to work with Angular.js
Include moment.js locale in the JavaScript bundle apart of moment.js library
//= require moment
//= require moment/pl.js
Add custom displayFormats to make it easier to parse date in callback function. And add callback function to parse and format date again.
options: {
...
scales: {
xAxes: [{
type: 'time',
time: {
displayFormats: {
'hour': 'HH:mm',
'day': 'DD-MM-YYYY',
'week': 'DD-MM-YYYY',
'month': 'DD-MM-YYYY',
},
unit: '<%= #report.scale %>',
},
ticks: {
callback: function(value, index) {
let displayFormats = {
'hour': 'HH:mm',
'day': 'DD-MM-YYYY',
'week': 'YYYY WW',
'month': 'MMMM YYYY',
};
let unit = '<%= #report.scale %>';
let format = displayFormats[unit];
return moment(value, 'DD-MM-YYYY').format(format, value);
}
}
}],
For some reason moment.js inside of Chart.js ignores locales. But when calling moment.js again inside of the callback function it works well.
I added guard return for all units other than month. I didn't want to reparse and reformat dates other than months.

Parsing from /Date(1487185200000)/ to date format

I want to convert this type of object to date format as (Sat 10/4/2016 5:03 PM)
how can I do that of input type /Date(1487185200000)/ using angularJs
May json is something like this
[{
"Post_Id": 1,
"Posts_Date":/Date(1487185200000)/,
"Post_Description": "Test",
},
{
"Post_Id": 2,
"Posts_Date": /Date(1487358000000)/,
"Post_Description": "Test",
}
]
This is my script in my controller
$http.post("/Home/GetPostData").then(function (d) {
$scope.Posts = d.data;
});
And this is my View
<div class="post_content" ng-repeat="p in Posts">
<h3> {{p.Post_Id}}</h3>
{{p.Post_Description}}
{{p.Posts_Date}}
</div>
And the output is somthing like this
1
Test
/Date(1487185200000)/
2
Test
/Date(1487358000000)/
want to convert my date as Standard format like (Sat 10/2/2016 4:50 PM) etc
If you are also interested in getting a Javascript Date (not just displaying), you can convert the JSON formmatted date/time information like this:
function parseJsonDate(jsonDateString){
return new Date(parseInt(jsonDateString.replace('/Date(', '')));
}
Credit
You need to visit this Angular Date filter
html
{{p.Posts_Date|removeBaces| date: 'medium'}}
js
myApp.filter('removeBaces', function() {
return function(input) {
return input.replace('/Date(','').replace(')/','');
}
});

Dynamically add filter in ng-repeat

I am building a table where the rows and columns are built entirely based on the data that is sent to it.
I'm very close to having it work, I'm having trouble figuring out how to build a custom filter and pass in the filter patterns dynamically
The object that makes up the columns looks like
{ name: 'transactionDate', displayName: 'Date / Time', displayOrder: 1, filter: "date: 'MM/dd/yy hh:mm a'" }
The object that makes up the transaction for the rows looks like this:
{ transactionDate: '2015-06-11', transactionType: 'This Type', transactionAmount: 25 }
The HTML I have is this:
<td ng-repeat="col in columns">{{transaction[col.name] | dynamicFilter: col.filter}}</td>
The filter I currently have built is:
function dynamicFilter($filter) {
return function (value, filter) {
console.log(filter);
console.log(value);
var test = $filter(filter)(value);
return test;
}
}
Both filter and value are getting passed correctly. I'm having trouble figuring out how to apply the filter to the value before returning. A value that might be passed in would 2015-06-10T16:17:14 be and a filter that would be passed in could be date: 'MM/dd/yy hh:mm a' to create date/time filter. Or 21 and currency for a dollar value.
I would like to be able to use Angular's built in features in a similar way you could on the view
For these dynamic filters that have partial params (such as the format you're providing with date), you have to remove the param from the filter and apply it later.
So filter: "date: 'MM/dd/yy hh:mm a'", needs to be just filter: "date".
The additional constraint, MM/dd/yy hh:mm a, would be sent along with the value $filter(filter)(value, 'MM/dd/yy hh:mm a');
To do this generically, you can take advantage of apply. The Object can be:
{filter: { type: "date", params: ['MM/dd/yy hh:mm a'] } }
And the directive can have (assuming you send the params as well):
var filterFn = $filter(filter.type);
return filterFn.apply(filterFn, [value].concat(filter.params));
EDIT: here's a JSFiddle with two buttons, the first demonstrates your original approach with "date: 'MM/dd/yy hh:mm a'", and the second demonstrates applied approach that I outline above http://jsfiddle.net/4whemakt/
You can apply and return the filtered value conditionally in your dynamicFilter. Something like this
function dynamicFilter($filter) {
return function (value, filter) {
if (filter.indexOf('date:') !== -1) {
//Note: I am using moment js to format the date
return moment(value).format(filter.match(/'([^']+)'/)[1]);
}
else {
return $filter(filter)(value)
}
}
}
moment.js reference http://momentjs.com/

Updating NVD3 /D3 chart as per user input radio button

http://nvd3.org/examples/cumulativeLine.html
This example show 4 lines chart. What i want to achieve below.
currently, Series 1, Series 2, Series 3, Series 4 (Charts and Respective legends)
I want keep Series 1, Series 2, Series 3 as common
and I have few radio buttons(Outside chart Area) like Series 5, Series 6, Series 7 and on and on.
Now clicking on those radio button i want to show respective chart and common charts(in this case series 1 ,2 and 3)
for Example
Series 5 radio button clicked
Now Series 1, Series 2, Series 3, Series 5 is shown, [This would removed chart3 legend-chart and add legend-chart of Series 5].
I am trying to achieve above in AngularJS and NVD3 Directive. But i am ok i am known to D3 code logic i should be able to change to angular way. Providing Angular work around is warm welcomed.
[Update]
Strange, instead of cumulative i used simple line chart. I changed the data and chart is being updated as anticipated. I dont what is wrong with cumulative. Any Idea?
With angularjs you can try angular-nvd3 directive. It allows you to manipulate with chart data and chart options via JSON, like:
//html
<nvd3 options="options" data="data"></nvd3>
//javascript
$scope.options = { /*some options*/ }
$scope.data = [ /*some data*/ ]
So, in your case, we just extend this approach to when we interactively update data. We can write something like (using checkboxes):
//html
<div ng-repeat="series in initData">
<input type="checkbox" ng-model="checkboxes[series.key]" ng-init="checkboxes[series.key]=true" ng-change="onchange()"/>{{series.key}}
</div>
<nvd3 options="options" data="data"></nvd3>
where initData is a whole static dataset. And in controller
//javascript
$scope.options = { /*some options*/ }
$scope.initData = [
{
key: "Long",
mean: 250,
values: [ ... ]
},
...
];
$scope.data = angular.copy($scope.initData);
$scope.checkboxes = {};
$scope.onchange = function(){
$scope.data = [];
angular.forEach($scope.initData, function(value, index){
if ($scope.checkboxes[value.key]) $scope.data.push(value);
})
}
See live example: http://plnkr.co/edit/ZLcS6M?p=preview
Note: angular-nvd3
http://embed.plnkr.co/tsJntqq5YJnNUGK6goLZ/preview
See plunkr, I did for a button adding a new serie so it shouldn't have too different just changing for the radio. Notice that if you are getting the data from Web Services or similar resources you probably have to redraw the graph
See https://github.com/krispo/angular-nvd3/issues/37
In the directive
<nvd3 options="options" data="data" api="api"></nvd3>
In the Controller
$scope.api.refresh();
Hope this help

Resources