Sort table columns with angularjs in non-angular application - javascript

Ok, suppose I have a table
<table>
<tr>
<td>Name</td><td>Phone</td>
</tr>
<tr>
<td>John</td><td>2222222</td>
</tr>
<tr>
<td>Mark</td><td>3333333</td>
</tr>
<tr>
<td>Alice</td><td>1999999</td>
</tr>
</table>
That was rendered by non-angularjs app.
All the examples I see on the web suggest that I have a controller and a scope and all the angularjs stuff, but what if I want to deal with existing data?
One time I have this headache I've surrendered and re-wrote everything to be an angularjs app.
There is a major issue with: it's not indexed by the search engines. Or at least not by all of them (I know google is super-smart, but that's only google).
What if I want to use angularjs power and have this existing data? How do I bind those values of the table and make it sortable?

This is interesting and I think it is useful when we want to give old web application power of angularjs.
The following code is nothing more than my idea without careful consideration.
In Html
<div ng-app="myapp" ng-controller="myctrl">
<table>
<tr>
<td><a href ng-click="mgrtable.sort('name')">Name</href></td><td><a href ng-click="mgrtable.sort('phone')">Phone</a></td>
</tr>
<tr ng-init="mgrtable.add_row('John', '2222222')">
<td>{{mgrtable.rows[0].name}}</td><td>{{mgrtable.rows[0].phone}}</td>
</tr>
<tr ng-init="mgrtable.add_row('Mark', '3333333')">
<td>{{mgrtable.rows[1].name}}</td><td>{{mgrtable.rows[1].phone}}</td>
</tr>
<tr ng-init="mgrtable.add_row('Alice', '1999999')">
<td>{{mgrtable.rows[2].name}}</td><td>{{mgrtable.rows[2].phone}}</td>
</tr>
</table>
</div>
In javascript
angular.module('myapp', [])
.factory('ManagerTable', function(){
return function(){
this.rows = [];
var desc = {
name: true, phone: true
}
this.add_row = function(name, phone){
this.rows.push({name: name, phone: phone});
}
this.sort = function(key){
var _desc = desc[key];
desc[key] = !_desc;
this.rows.sort(function(a, b){
var vala = a[key],
valb = b[key];
if (_desc){
return vala > valb ? 1: -1;
}else{
return vala > valb ? -1: 1;
}
});
}
};
})
;
function myctrl($scope, ManagerTable){
$scope.mgrtable = new ManagerTable();
}
Demo jsfiddle is here.
When you want to add some feature about the table data, all you have to do is adding the function of ManagerTable. Although I know html is not clean, I think this way could keep the MVC principle and angular-way.
Please let me know what you think.

Related

Highlight cell with highest value in ng-repeat with AngularJS 1.4.14

I am working on a dashboard and I'd like some help '_'.
I get a JSON from an API and I get an array of 5 element and each contain this structure (I simplified it but it is close to that).
{
"app_id": "id",
"app_name": "name",
"users_percentiles": {
"users_percentile_1": "3408",
"users_percentile_2": "2356",
"users_percentile_3": "988",
"users_percentile_4": "1099",
}
}
Then, I use a table to organize those elements in my dashboard.
<tbody ng-repeat="dash in dashboard">
<tr>
<td>{{dash.app_id}}</td>
<td>{{dash.app_name}}</td>
<td ng-repeat="percentile in dash.users_percentiles">
{{(percentile}}%
</td>
</tr>
</tbody>
I'd like for each ng-repeat highlight the highest value of percentile (if two are equals, then both should be highlighted).
I think i should add something like :
ng-class="{max : percentile == maxPercentile}"
and a function :
$scope.maxPercentile = -1;
angular.forEach(percentiles, function (percentile) {
if (percentile > $scope.maxPercentile) {
$scope.maxPercentile = percentile;
}
});
But I don't know really where to use this method.
I tried with a $watch but no matter how I tried I didn't get it to work...
<tbody ng-repeat="dash in dashboard">
<tr>
<td>{{dash.app_id}}</td>
<td ng-init = "maxpercentile = getMaxPercentile(dash.users_percentiles)">{{dash.app_name}}</td>
<td ng-class="{max : percentile === maxpercentile}"
ng-repeat="percentile in dash.users_percentiles">
{{percentile}}%
</td>
</tr>
</tbody>
$scope.getMaxPercentile = function(percentiles){
var maxPercentile = -1;
angular.forEach(percentiles, function (percentile) {
if (percentile > $scope.maxPercentile) {
maxPercentile = percentile;
}
});
return maxPercentile;
}

orderBy not working with pagination and filters

<table>
<thead>
<tr>
<th class="col-md-3" ng-click="sortDirection = !sortDirection">Created At</th>
</tr>
</thead>
<tbody>
<tr dir-paginate="food in foods | filter:foodFilter | itemsPerPage:pageSize | orderBy:'created_at_date'">
<td class="col-md-"> {{food.created_at_date}} </td>
</tbody>
</table>
<dir-pagination-controls
max-size= 7
boundary-links="true">
</dir-pagination-controls>
This is only a snippet of my code but its too large to put up. Everything is working except only some of the created_at_date is in order. When I click on a different filter to add in or remove data depending on that filter, only some of it is entered into the correct place. My main question is: is there someway to sort all of the dates properly while still allowing the everything else function as well? All help is welcome, Thanks
(function () {
"use strict";
App.controller('foodsController', ['$scope'],
function($scope) {
$scope.sortDirection = true;
In your controller you can add the method to order the array before you loop over them.
Assuming your foods array has an array of objects, each with a key of created_at_date and a value:
App.controller('foodsController', function($scope) {
$scope.foods = [{
created_at_date: 6791234
}, {
created_at_date: 9837245
}, {
created_at_date: 1234755
}];
// create a method exposed to the scope for your template.
$scope.orderBy = function(key, array) {
// now you've received the array, you can sort it on the key in question.
var sorted = array.sort(function(a, b) {
return a[key] - b[key];
});
return sorted;
}
});
Now on your template, you have a method available to sort your values for you:
<table>
<thead>
<tr>
<th class="col-md-3" ng-click="sortDirection = !sortDirection">Created At</th>
</tr>
</thead>
<tbody>
<tr dir-paginate="food in orderBy('created_at_date', foods) | filter:foodFilter | itemsPerPage:pageSize">
<td class="col-md-"> {{food.created_at_date}} </td>
</tr>
</tbody>
</table>
The orderBy method which we've created on your controller returns an array, but it's just sorted by the key that's sent in as the first argument of the function. The second argument is the original array you're trying to sort.
At least this way you can check if you remove all your other filters to see if it's ordered correctly, if then after you add them back in it changes it's because those filters are also changing the order.

Formatting data before render it

I am displaying some data in the view, but I need to formatted first, I was doing something like
val.toFixed(2) and that is OK, it works but the problem is that val sometimes comes with letters, and toFixed(2) is not taking that into account so is not displaying the letters.
So I need something that takes into account letters and numbers, the letters don't have to change, only the numbers which comes like 234235.345345435, and obviously I need it like this 234235.34.
Here is some of the code I am using
<table>
<tr>
<th ng-repeat='header in headers'>{{header.th}}</th>
</tr>
<tr>
<td ng-repeat='data in headers'>
<div ng-repeat='inner in data.td'>
<span ng-repeat='(prop, val) in inner'>{{val.toFixed(2)}}</span>
</div>
</td>
</tr>
</table>
and in the controller
$scope.LoadMyJson = function() {
for (var s in myJson){
$scope.data.push(s);
if ($scope.headers.length < 1)
for (var prop in myJson[s]){
prop.data = [];
$scope.headers.push({th:prop, td: []});
}
}
for (var s in $scope.data){
for (var prop in $scope.headers){
var header = $scope.headers[prop].th;
var data = myJson[$scope.data[s]][header];
$scope.headers[prop].td.push(data);
console.log($scope.headers[prop].td);
}
}
};
and I prepared this Fiddle
the way it is right now, is displaying the table properly, but as you see, the table is missing the name, it is because of the toFixed method.
So, what can I do ?
Create a custom filter to use on your template.
<table>
<tr>
<th ng-repeat='header in headers'>{{header.th}}</th>
</tr>
<tr>
<td ng-repeat='data in headers'>
<div ng-repeat='inner in data.td'>
<span ng-repeat='(prop, val) in inner'>{{val|formatValue}}</span>
</div>
</td>
</tr>
</table>
angular.module('whatever').filter('formatValue', function () {
return function (value) {
if (isNaN(parseFloat(value))) {
return value;
}
return parseFloat(value).toFixed(2);
}
});
You can try this :
That is a clean way to render formated data in view using angularjs as MVC
frontend framework :
Create a filter in your angular application.
Include your filter in your index.html.
use your filter like this : {{somedata | filterName}}
That is a simple angular filter to solve your problem, hope it will help you :
angular.module('app')
.filter('formatHeader', function() {
return function(data) {
if(angular.isNumber(data)) {
return data.toFixed(2);
}
return data;
}
});
And us it like this :
<table>
<tr>
<th ng-repeat='header in headers'>{{header.th}}</th>
</tr>
<tr>
<td ng-repeat='data in headers'>
<div ng-repeat='inner in data.td'>
<span ng-repeat='(prop, val) in inner'>{{val | formatHeader}}</span>
</div>
</td>
</tr>
You can take a look about these references :
angular functions
filter doc.
angular tutorials

Sorting table rows using AngularJS

I'm just getting started with AngularJS and I'm trying to sort my table so that when a tableheader is clicked the rows are sorted per that table header.
Here is my plnkr link:
http://plnkr.co/edit/mbTq5865KKNzlvpJJy1l
Here is my relevant code:
Controller code:
$scope.setRepoSortOrder = function(order) {
if ($scope.repoSortOrder === order) {
if ($scope.repoSortOrder.charAt(0) === '+') {
order = order.replace('+', '-');
} else {
order = order.replace('-', '+');
}
}
$scope.repoSortOrder = order;
};
Table:
<table>
<thead>
<tr>
<th>Name</th>
<th>Stars</th>
<th>Language</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="repo in repos | orderBy:repoSortOrder">
<td>{{repo.name}}</td>
<td>{{repo.stargazers_count | number}}</td>
<td>{{repo.language}}</td>
</tr>
</tbody>
</table>
So when the name th is clicked the rows should be sorted by the names - same with stargazers_count and language. If a th is clicked again it should be sorted in the opposite order (if I click name first it's sorted by names in asc order - if I click it again it's sorted in desc order).
Finally: name and language should initially sort in asc order while stargazers_count should sort in desc order initially.
I've done this myself but I don't know if I'm doing it the best way possible. Since I'm not used to the "angular style" I would like to hear how people familiar with AngularJS would handle this. Please check out the plnkr link to see if you could improve it.
Any replies are appreciated!
One thing that can improve is to use a reverse flag of the orderBy filter like this:
$scope.repoSortOrder = "-stargazers_count";
$scope.isReverse = false;
$scope.setRepoSortOrder = function(order) {
$scope.isReverse = ($scope.repoSortOrder === order) ? !$scope.isReverse : false;
$scope.repoSortOrder = order;
};
Example Plunker: http://plnkr.co/edit/CM1BGkQc0AYbrraAPq8r?p=preview

Angular-JS table sorting not working when delimiter change from ng: to ng-

I've created an angular application for sorting of html tables based on ascii values. The application works fine but the problem is when i change the delimiter from 'ng:' to 'ng-' the sorting is not working . If the cause of this is in case of someother reason please pardon me...since im new to angular js
can anyone please tell me some solution for this
angular code with 'ng-' delimiter (Working Demo) - Sorting Not working
<div ng-controller="Main" ng-app="myApp">
<table border="1">
<tr>
<th><a href ng-click="sortBy('name')">Name</a></th>
<th><a href ng-click="sortBy('phone')">Phone Number</a></th>
<th><a href ng-click="sortBy('age')">Age</a></th>
<th><a href ng-click="sortBy('date')">Date</a></th>
</tr>
<tr ng-repeat="friend in friends|orderBy:sort:reverse">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
<td>{{friend.date}}</td>
</tr>
</table>
</div>
The issue is how you are defining and using predicate and reverse.
When you are using "this" inside this function they are defined within just the scope of this function and are not accessible outside of it.
$scope.sortBy = function (field) {
if (this.predicate != field) {
this.predicate = field;
this.reverse = false;
} else {
this.reverse = !this.reverse;
}
};
I updated it to use a local predicate variable and a reverse property on the scope, so it can be used in the markup.
var predicate;
$scope.reverse = false;
$scope.sortBy = function (field) {
if (predicate != field) {
predicate = field;
$scope.reverse = false;
} else {
$scope.reverse = !$scope.reverse;
}
};
updated fiddle: http://jsfiddle.net/rvdww/77/

Categories

Resources