I have a list sorted by date and I want to reorder it by clicking button. This date is taken from an object, I try this code, but it sorts like a simple number:
// function to order and change button by click
$scope.sortType = "CreationDate";
$scope.sortReverse = false;
$scope.buttonStyle = "icon ion-ios-time-outline";
$scope.buttonPress = false;
$scope.ordina = function() {
if ($scope.sortType == "CreationDate") {
$scope.sortReverse = !$scope.sortReverse;
console.log("riordinate");
}
$scope.buttonPress = !$scope.buttonPress;
if ($scope.buttonPress == true) {
$scope.buttonStyle = "icon ion-ios-time";
} else {
$scope.buttonStyle = "icon ion-ios-time-outline";
}
}
in html:
<ion-item ng-repeat="object in allODA | filter: searchQuery | orderBy : sortType : sortReverse " href="#/app/ODA_Detail/{{object.caseTaskId}}">
any solutions???idea???
I don't know if I understood correctly, but here is an example to sort a table with dates, click on the title of the column to sort it.
https://jsfiddle.net/lisapfisterer/8pvqau4z/
This does not use ionic, you might need to adapt it.
<table class="table table-striped">
<thead>
<td data-ng-click="sortType = name; sortReverse = !sortReverse;">
Date
</td>
<td data-ng-click="sortType = name; sortReverse = !sortReverse;">
Name
</td>
</thead>
<tbody>
<tr ng-repeat="item in allItems | orderBy:sortType:sortReverse">
<td>{{item.date | date:"yyyy-MM-dd"}}</td>
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
Related
I have a simple table with search -
<table>
<thead>
<tr>
<th> Name </th>
<th> Lastname </th>
<th> Job Title </th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="data in ctrl.data | filter : searchQuery">
<td>{{data.name}}</td>
<td>{{data.lastname}}</td>
<td>{{data.jobtitle | translate}}</td>
</tr>
</tbody>
</table>
<input type="text" data-ng-model="searchQuery"/>
Since job title is translated - search works only with original value - so yes with "Developer" but no with any translation of this.
Is there is any possibility to make it work with translations too?
You can create a filter to handle the translation
Filter
app.filter('translateFilter', function($translate) {
return function(input, param) {
if (!param) {
return input;
}
var searchVal = param.toLowerCase();
var result = [];
angular.forEach(input, function(item) {
var translated = $translate.instant(item.jobtitle);
if (translated.toLowerCase().indexOf(searchVal) > -1) {
result.push(item);
}
});
return result;
};
});
And use it like this:
HTML
<tr data-ng-repeat="data in ctrl.data | translateFilter:searchQuery">
I'm really new to Angular and i'm trying to create a list of user transactions that presents the time of the action and the user's name. In my audit API I have an action ID and the User FK which associates with my User API and i'm displaying it as follows:
HTML
<table>
<thead>
<tr>
<th>
Date/Time
</th>
<th>
User
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="audit in audit.data>
<td>{{audit.audit_date_time}}</td>
<td>**{{audit.audit_user_fk}}**</td> **<--I need the name not the ID here**
</tr>
</tbody>
</table>
My Apis are as follows:
AUDIT
[
{
"audit_id": "1",
"audit_date_time": "2016-01-28 12:46:20",
"audit_user_fk": "97"
}
]
USER
[
{
"user_id": "97",
"user_full_name": "Mr.User",
}
]
Controller, which is working fine GETting the data from each API:
app.controller('auditControl', ['$scope','auditService', 'userService', function ($scope, auditService, userService) {
var auditLogs = auditService.query(function () {
$scope.audit.data = auditLogs;
});
var user = userService.query(function () {
$scope.auditUser = user;
});
}]);
So my main issue i'm having is getting the user name in the table instead of the foreign key value. I've stripped out a lot of this just so we can focus on the main problem. Getting the user name from the user API, based on the FK in the Audit API and repeated based on the items in the Audit API.
Any help greatly appreciated and apologies for the noob question!
Create a custom filter.
app.filter("lookupUser", function() {
function lookup (idNum, userList) {
var userName = "UNKNOWN";
angular.forEach(userList, function(user) {
if ( user.user_id == idNum ) {
userName = user.user_full_name;
};
});
return userName;
};
return lookup;
});
Then in your template:
<tr ng-repeat="audit in audit.data>
<td>{{audit.audit_date_time}}</td>
<td>{{audit.audit_user_fk | lookupUser : auditUser }}</td>
</tr>
You could do something like this:
Controller:
app.controller('auditControl', ['$scope','auditService', 'userService', function ($scope, auditService, userService) {
var auditLogs = auditService.query(function () {
$scope.audit.data = auditLogs;
});
var user = userService.query(function () {
$scope.auditUser = user;
});
$scope.getUserName = function (id) {
var result = $scope.users.filter(function( user ) {
return user.user_id == id;
});
if (angular.isDefined(result) && result.length > 0) {
return result[0].user_full_name;
} else {
return "--";
}
}
}]);
HTML
<table>
<thead>
<tr>
<th>
Date/Time
</th>
<th>
User
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="audit in audit.data">
<td>{{audit.audit_date_time}}</td>
<td>**{{getUserName(audit.audit_user_fk)}}**</td> **<--I need the name not the ID here**
</tr>
</tbody>
</table>
I don't know where the users array are, so I called $scope.users.
I'm using angular smart table. Smart table has built in filtering using the st-search directive. However, I need some customized filtering using regular expressions.
I tried applying an angular filter to my data source (via the ng-repeat directive). While this works in regards to filtering, because smart table isn't aware of what i'm doing, it throws my paging off.
I've plunked an example of what is going on. (Try entering 1.8 in the account filter input box. You'll see the filter get applied but then if you click other pages, you'll see that they contain some of the filtered items as well.) I need the behavior to work similar to what happens if you filter by description (where filtered items get narrowed down and re-paged).
Here is my html table:
<table st-table="vm.accounts" class="table table-striped table-hover table-condensed">
<thead>
<tr>
<th st-sort="account">Account</th>
<th st-sort="desc">Description</th>
<th>Current Balance</th>
<th> </th>
<th> </th>
</tr>
<tr class="warning">
<th>
<input placeholder="filter accounts" class="form-control input-sm" type="search" ng-model="vm.accountfilter" />
</th>
<th>
<input placeholder="filter description" class="form-control input-sm" type="search" st-search="desc" />
</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in vm.accounts | filter:vm.myfilter" ng-click="vm.selected = item" ng-class="{info: vm.selected == item}">
<td>{{item.account}}</td>
<td>{{item.desc}}</td>
<td>{{item.runbal | currency}}</td>
<td><button class="btn btn-danger btn-xs"><i class="fa fa-times-circle"></i></button></td>
<td><button class="btn btn-primary btn-xs"><i class="fa fa-pencil"></i></button></td>
</tr>
</tbody>
<tfoot>
<tr class="warning">
<td colspan="5" class="text-center">
<button class="btn btn-success btn-sm"><i class="fa fa-plus-circle"></i> Add new account</button>
</td>
</tr>
<tr>
<td colspan="5" class="text-center">
<div st-pagination="" st-items-by-page="20" st-displayed-pages="10"></div>
</td>
</tr>
</tfoot>
</table>
and here is the filter that I'm trying to apply (from my controller):
(function(){
'use strict';
angular.module("myapp", ["smart-table"])
.controller("mycontroller", MyController);
function MyController(){
var me = this;
me.accounts = [];
me.selected = null;
me.myfilter = myFilter;
me.accountfilter = '';
activate();
function activate(){
for(var x = 0; x < 6000; x++)
{
var build = '';
for(build; build.length < (12 / x.toString().length); build += x.toString()){}
var aclass = Math.floor((1800 - 1100 + 1) * Math.random() + 1100).toString();
var adept = Math.floor((800 - 100 + 1) * Math.random() + 100).toString();
var aincex = Math.floor(1001 * Math.random() + 4000).toString();
var asub = Math.floor(2 * Math.random());
var account = aclass + adept + aincex + (asub ? "AB" + x.toString() : "");
me.accounts.push({account: account, desc: "Text for " + x + " Account", runbal: x * 5, begbal: 5000, newbegbal: 20000, newrunbal: x * 7});
}
}
function myFilter(value, index, array){
if(!me.accountfilter) return true;
var valex = new RegExp("^[*0-9a-zA-Z.]{1,22}$");
if(me.accountfilter.match(valex))
{
var filter = me.accountfilter;
debugger;
filter = filter.replace(/\*/g,'\\w+');
filter = "^" + filter + ".*$";
var regex = new RegExp(filter,'i');
return value.account.match(regex)
}
else
return false;
}
}
})();
How can I "smart table enable" my filter?
My suspicions were correct. I'm not sure if this is the best way to do it, but here is how I accomplished the special filtering.
I made 3 change to my html.
I added st-pipe to my <table> element.
<table st-pipe="vm.pipe" st-table="vm.accounts" ... >
I removed the angular filter from my ng-repeat.
<tr ng-repeat="item in vm.accounts" ... >
I used the smart-table search feature on the account column (in place of the angular filter that I removed).
<input st-search="account" ... />
In my controller I then added the following:
...
var internalList = [];
me.pipe = Pipe;
function Pipe(tableState){
var perpage = tableState.pagination.number;
var start = tableState.pagination.start;
var filtered = internalList;
//If user has entered filter criteria
if(tableState.search.predicateObject)
{
//clone the filter criteria object
var myPred = $.extend({},tableState.search.predicateObject);
//remove the account criteria so I can process that myself
delete myPred["account"];
//perform the default filter function for any other filters
filtered = $filter('filter')(filtered, myPred);
//if user entered account (regex) filter then call my original filter function
if(tableState.search.predicateObject["account"])
{
filtered = $filter('filter')(filtered,myFilter);
}
}
//apply any sorting that needs to be applied
if (tableState.sort.predicate) {
filtered = $filter('orderBy')(filtered, tableState.sort.predicate, tableState.sort.reverse);
}
//set the bound array to the filtered contents
me.accounts = filtered.slice(start, start +perpage);
//clear the selected item if it is not included on the current page
if(me.accounts.indexOf(me.selected) < 0)
me.selected = null;
//Set the proper number of pages for our filtered list
tableState.pagination.numberOfPages = (filtered.length ? Math.floor(filtered.length / perpage) : 0);
}
Lastly, I had to change the activate function of my controller to populate the internalList rather than the display/bound list.
//me.accounts.push({account: account, desc: "Text for " + x + " Account", runbal: x * 5, begbal: 5000, newbegbal: 20000, newrunbal: x * 7});
internalList.push({account: ...});
You can see it in action here.
I have one object like this
$scope.listvalues = [{ name:A, id:101 },
{ name:B, id:102 },
{ name:A, id:103 },
{ name:C, id:101 },
{ name:A, id:102 },
{ name:B, id:103 }];
I need to print this object in following structure
name |101 | 102 |103 |
-----|----|-----|---------
A |YES | YES |YES |
-----|----|-----|------------
B |No | YES |YES |
-----|----|-----|-----------
C |YES | NO |NO |
Here i need to print the Name "A" in unique and also need to indicate the A is available for which Id. Is it possible to do with angularjs ng-repeat?. Any one please suggest...
You can, but you would have to write a filter that changes the structure of your data to the following:
$scope.data = [
{A: {'101': true, '102': true, '103': true}},
{B: {'101': false, ...}},
{C: ...}
]
And then you can write your table like this:
<table>
<tr>
<th>name</th>
<th ng-repeat="(column, value) in data[0]">{{column}}</th>
</tr>
<tr ng-repeat="row in data">
<td ng-repeat="(column, value) in data[0]">{{row[column] ? 'Yes' : 'No'}}</td>
</tr>
</table>
Example filter:
yourModule.filter('makeNgRepeatable', function(){
return function(oldStructure) {
// Add code here to convert oldStructure to newStructure.
return newStructure;
}
});
In your controller, inject makeNgRepeatableFilter and do
$scope.data = makeNgRepeatableFilter([{ name:A, id:101 }, ...]);
You can pack this into a table and then resolve with multiple ng-repeats which cell is YES or NO.
Take a look at this plnkr, it demonstrates how this could be achieved.
http://plnkr.co/edit/QI8ZrsbwYuJUeV4DNWGl?p=preview
First you collect all distinct ids and names.
$scope.names = $scope.listvalues.map(function(d){return d.name}).unique();
$scope.ids = $scope.listvalues.map(function(d){return d.id}).unique();
Note: In the plnkr I defined the functions unique and contains. If you use some other libraries like underscore those functions may already be present.
Then you define a function to determine if a specific cell should be true or false.
$scope.hasValue = function(name, id) {
for(var i = 0; i < $scope.listvalues.length; ++i)
if($scope.listvalues[i].name === name && $scope.listvalues[i].id === id)
return true;
return false;
}
However, it would be simpler if you can convert your listvalues into a reasonable structure. This would prevent some of the overhead.
With your array structure you might need some additional helper array/objects. In your case it could look like this:
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th ng-repeat="th in values">{{th}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="obj in names">
<td>
{{obj.name}}
<div><small>{{obj}}</small></div>
</td>
<td>{{obj.ids.indexOf(values[0]) > -1 ? 'YES' : 'NO'}}</td>
<td>{{obj.ids.indexOf(values[1]) > -1 ? 'YES' : 'NO'}}</td>
<td>{{obj.ids.indexOf(values[2]) > -1 ? 'YES' : 'NO'}}</td>
</tr>
</tbody>
</table>
where helper objects are constructed like:
function initData() {
var map = {values: {}, names: {}},
values = [],
names = [];
$scope.listvalues.forEach(function(obj) {
if (!map.values[obj.id]) {
values.push(obj.id);
map.values[obj.id] = true;
}
if (!map.names[obj.name]) {
names.push(obj);
obj.ids = [obj.id];
map.names[obj.name] = obj;
}
else {
map.names[obj.name].ids.push(obj.id);
}
});
$scope.values = values;
$scope.names = names;
}
initData();
Demo: http://plnkr.co/edit/wWJOjtzstUDKjl9V6hCy?p=preview
I am attempting to use a custom orderBy function. Initially, I want the data to appear in the order it was added to $scope.rows, and only after clicking on a column heading should it order by a specific property. Here's my fiddle:
http://jsfiddle.net/S8M4c/
Here's my view:
<table ng-app ng-controller="ctrl">
<tr>
<th><a ng-click="orderBy = 'id'">ID</a></th>
<th><a ng-click="orderBy = 'name'">Name</a></th>
</tr>
<tr ng-repeat="row in rows | orderBy:mySort">
<td>{{row.object.id}}</td>
<td>{{row.object.name}}</td>
</tr>
</table>
Here's my controller:
function ctrl($scope)
{
// Initially, we don't sort by anything
$scope.orderBy = "";
$scope.rows = [];
// Add some rows
for(var i = 10;i < 30;i++)
{
$scope.rows.push({settings: {foo: true}, object: {id: i, name: "Name " + i}})
};
$scope.mySort = function(row)
{
if($scope.orderBy != "")
{
return row.object[$scope.orderBy];
}
// What do I return here??
return "";
}
}
In the case that $scope.orderBy isn't set and I want to return $scope.rows in it's original order, what do I return in $scope.mySort? I cannot return row.object.id because the rows are not guaranteed to be added in order of their ID. Running my code as is on Chrome 32, the first row that appears has an ID of 20, which is the halfway row.
return $scope.rows.indexOf(row);
(Fiddle.)
You can also do this with out-of-the-box orderBy by providing a function returning that as the default predicate:
Controller:
$scope.mySort = $scope.unsorted = function(row)
{
return $scope.rows.indexOf(row);
}
View:
<div ng-app ng-controller="ctrl">
<table>
<tr>
<th><a ng-click="mySort = 'object.id'">ID</a></th>
<th><a ng-click="mySort = 'object.name'">Name</a></th>
</tr>
<tr ng-repeat="row in rows | orderBy:mySort">
<td>{{row.object.id}}</td>
<td>{{row.object.name}}</td>
</tr>
</table>
<button ng-click="mySort = unsorted;">Original Sort</button>
</div>
Fiddle here. (I've changed the numbers used in the objects so that sort by id, sort by name, and the original sort aren't all the same.)
I think you have to write your own sortby function. The original angulars orderBy is a regular filter that returns the sorted array. Your filter may look something like this:
.filter('mySort', function(){
return function(values, param){
if(param===''){
return values;
}else{
// very important! create a copy of the array - otherwise
// the $wtachCollection function will fire to often!
var arrayCopy = [];
for ( var i = 0; i < values.length; i++) { arrayCopy.push(values[i]); }
return arrayCopy.sort(function(a,b){
var v1 = a.object[param];
var v2 = b.object[param];
// you know best how to sort it!
if (v1 === v2) return 0;
return v1 < v2 ? -1 : 1;
});
}
}
})
You can use this filter in this way:
<table ng-app="myApp" ng-controller="ctrl">
<tr>
<th><a ng-click="orderBy = 'id'">ID</a></th>
<th><a ng-click="orderBy = 'name'">Name</a></th>
</tr>
<tr ng-repeat="row in rows | mySort:orderBy">
<td>{{row.object.id}}</td>
<td>{{row.object.name}}</td>
</tr>
</table>
here is your modified fiddle: http://jsfiddle.net/spRf6/ I have changed the names a little bit so you may see that the sorting works.
Create a copy of the objects array and the ordering then becomes trivial:
Controller:
$scope.objects = [];
angular.forEach($scope.rows, function(row){
$scope.objects.push(row.object);
});
View:
<tr ng-repeat="object in objects | orderBy:orderBy">
<td>{{object.id}}</td>
<td>{{object.name}}</td>
</tr>
No need for the mySort function.