Descending order for list-divider in AngularJs - angularjs

How may I order the <div class="item item-divider"> in descending way, where on the top I would like to have the most recent date?
// index.html
...
<ion-content>
<div ng-repeat="(date,list) in items">
<div class="item item-divider">
{{date}}
</div>
<ul class="list">
<li class="item item-icon-right" ng-repeat="item in list">
<h2>{{item.name}} {{item.surname}}</h2>
</li>
</ul>
</div>
</ion-content>
...
-------------------------------------------------------------------------------------------------
// app.js
angular.module('ionicApp', ['ionic'])
.controller('MyCtrl', function($scope) {
$scope.items = {
'11/12/2014':[
{name:'mark',surname:'john',birth:'11/12/2014'}
],
'12/12/2014':[
{name:'tom',surname:'smith',birth:'12/12/2014'}
{name:'carl',surname:'northon',birth:'12/12/2014'}
]
}
});

Why not sort the object itself, before passing it to angular.
function sortObjectByKeys(object, order) {
var sortedObject = {}, key, tempKeyArray = [];
for (key in object) {
if (object.hasOwnProperty(key)) {
tempKeyArray.push(key);
}
}
// You can also retrieve all the keys using Object.keys() method and then sort them..
tempKeyArray.sort(function(a, b){return b - a});
for (key = 0; key < tempKeyArray.length; key++) {
sortedObject[tempKeyArray[key]] = object[tempKeyArray[key]];
}
return sortedObject;
}

Can you change the data-structure to have two keys, 'date' and 'people'? Then you could do
items | orderBy:'date'

This should work fine:
$scope.mysort = function(obj){
var sortedObject = {}, key, tempKeyArray = [];
for (key in obj) {
if (obj.hasOwnProperty(key)) {
tempKeyArray.push(key);
}
}
tempKeyArray.sort(function(a, b){
var parts = a.split("/");
a = new Date(parts[2], parts[1] - 1, parts[0])
parts = b.split("/");
b = new Date(parts[2], parts[1] - 1, parts[0]);
return b-a;
});
for (key = 0; key < tempKeyArray.length; key++) {
sortedObject[tempKeyArray[key]] = obj[tempKeyArray[key]];
}
return sortedObject;
}

Related

AngularJS: groups of checkboxes inside a loop

There are some categories inside ng-repeat, and each one includes some accounts, If each category is selected then all accounts inside it must be selected and vice versa. Also, if one account is not selected, then the parent category is not selected.
How can I do that?
Here is how the view is:
And the code fiddle:
http://jsfiddle.net/2f6qscrp/208/
Thank you for any help.
Here is the working fiddle for your case,
http://jsfiddle.net/balasuar/2f6qscrp/209/
HTML
<div ng-app='home'>
<!-- App goes here -->
<md-content layout-padding ng-controller="MainCtrl as mainCtrl">
<md-checkbox ng-model="selectedAll"
ng-change="toggleAll()"
class="md-primary">
<span ng-if="selectedAll">Un-</span>Select All
</md-checkbox>
<div ng-repeat="category in naturalAccounts">
<md-checkbox class="md-primary" ng-model="category.selected" ng-change="toggleCategory(category)">
{{ category.name }}
</md-checkbox>
<div ng-repeat="acc in category.accounts">
<md-checkbox class="md-primary" ng-model="acc.selected" ng-change="toggleAccount(category, acc)" >{{acc.name}}</md-checkbox>
</div>
</div>
</md-content>
</div>
JS
angular.module('home', ['ngAria', 'ngAnimate', 'ngMaterial']);
angular.module('home').config(function ($mdThemingProvider) {
$mdThemingProvider.theme('default')
.primaryPalette('pink')
.accentPalette('grey');
});
angular.module('home').controller('MainCtrl', function ($scope) {
$scope.naturalAccounts = [
{"id":0,"name":"category0","accounts":[{"id":0,"name":"acc0"},{"id":1,"name":"acc1"},{"id":2,"name":"acc2"}] },
{"id":1,"name":"category1","accounts":[{"id":0,"name":"acc0"},{"id":1,"name":"acc1"},{"id":2,"name":"acc2"}] },
{"id":2,"name":"category2","accounts":[{"id":0,"name":"acc0"},{"id":1,"name":"acc1"},{"id":2,"name":"acc2"}] }
];
$scope.selectedAll = false;
function setSelectedAll() {
for(var i = 0; i < $scope.naturalAccounts.length; i++) {
var category = $scope.naturalAccounts[i];
$scope.selectedAll = category.selected;
if(!$scope.selectedAll) {
break;
}
}
}
$scope.toggleAll = function() {
for(var i = 0; i < $scope.naturalAccounts.length; i++) {
var category = $scope.naturalAccounts[i];
category.selected = $scope.selectedAll;
for(var j = 0; j < category.accounts.length; j++) {
var account = category.accounts[j];
account.selected = $scope.selectedAll;
}
}
};
$scope.toggleCategory = function(category) {
for(var j = 0; j < category.accounts.length; j++) {
var account = category.accounts[j];
account.selected = category.selected;
}
setSelectedAll();
};
$scope.toggleAccount = function(category, account) {
for(var j = 0; j < category.accounts.length; j++) {
var account = category.accounts[j];
category.selected = account.selected;
if(!category.selected) {
break;
}
}
setSelectedAll();
};
});
<input type="checkbox" ng-model="category.checked" ng-change="checkAllAccountsOfCategoryIfChecked(category)" />
and
<input type="checkbox" ng-model="account.checked" ng-change="checkOrUncheckCategoryBasedOnItsAccounts(category)" />
In your controller:
$scope.checkAllAccountsOfCategoryIfChecked = function(category) {
// TODO if category is checked, then loop over all its accounts and check them
}
$scope.checkOrUncheckParentCategory = function(category) {
// TODO if all the category's accounts are checked,
// then check the category, otherwise uncheck it
}

Angular filter multiple columns with an array of filters

I am trying to be able to filter multiple columns on multiple values. So far I can filter multiple columns on 1 single value:
myApp.controller('MyCtrl', ['$scope', '$http', function($scope, $http) {
$scope.empList = [];
$http.get('getAllOnline.php')
.success(function(data) {
$scope.empList = data;
});
$scope.column1List = [];
$http.get('getAllSomething.php', {
params: {
wuk: "column1"
}
})
.success(function(data) {
$scope.column1 = data;
});
$scope.column2List = [];
$http.get('getAllSomething.php', {
params: {
wuk: "column2"
}
})
.success(function(data) {
$scope.column2 = data;
});
$scope.column3List = [];
$http.get('getAllSomething.php', {
params: {
wuk: "column3"
}
})
.success(function(data) {
$scope.column3 = data;
});
$scope.setColumn1Value = function(val) {
if ($scope.zelectedColumn1 == val) {
$scope.zelectedColumn1 = undefined;
} else {
$scope.zelectedColumn1 = val;
}
}
$scope.setColumn2Value = function(val) {
if ($scope.zelectedColumn2 == val) {
$scope.zelectedColumn2 = undefined;
} else {
$scope.zelectedColumn2 = val;
}
}
$scope.setColumn3Value = function(val) {
if ($scope.zelectedColumn3 == val) {
$scope.zelectedColumn3 = undefined;
} else {
$scope.zelectedColumn3 = val;
}
}
Then i use this to set my single value filters:
<ul id="Column1" class="collapse">
<li ng-repeat="emp in empList | unique:'Column1'">
<a ng-click="setColumn1Value(emp.Column1);" ng-class="{selected: emp.Column1 === zelectedColumn1}">
<div ng-repeat="someone in Column1List | filter:{Column1_id:emp.Column1}">
{{someone.value}}
</div>
</a>
</li>
</ul>
This works perfect! But now I want to be able to filter on multiple values in 1 column. So I changed my setter functions to:
$scope.zelectedColumn1=[];
$scope.setColumn1Value = function(val) {
var found = jQuery.inArray(val, $scope.zelectedColumn1);
if (found >= 0) {
// Element was found, remove it.
$scope.zelectedColumn1.splice(found, 1);
} else {
// Element was not found, add it.
$scope.zelectedColumn1.push(val);
}
console.log($scope.zelectedColumn1);
}
So now I add or remove indexes to an array instead of storing a single value. This also works, but how do I filter my columns on the contents of an array instead of on a single value as I do now:
<div class='row'>
<div class='col-lg-2 col-md-3 col-sm-6' ng-repeat="emp in empList | filter:{column1:zelectedColumn1,column2:zelectedColumn2,column3:zelectedColumn3} as res">
{{emp.column1}}
{{emp.column2}} <br>
{{emp.column3}} <br>
</div>
</div>
I have been struggling with this al day and hope someone can help me out here!

Get model array values in controller's service

I've been facing an issue since couple of hours. My view template looks like-
<div class="row" ng-repeat="row in CampaignsService.getRows().subItems track by $index">
<div class="col-sm-2">
<select class="form-control dropDownPercent" ng-model="CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]" ng-change="CampaignsService.wow(CampaignsService.dropDownPercent, $index)" ng-options="o as o for o in CampaignsService.showPercentDropDown().values">
</select>
</div>
<div class="col-sm-2" style="line-height: 32px">
of visitors send to
</div>
<div class="col-sm-4">
<select class="form-control" ng-model="campaignSelect" ng-options="campaign.Campaign.id as campaign.Campaign.title for campaign in CampaignsService.getRows().items">
<option value=""> Please select </option>
</select>
</div>
<div class="col-sm-4">
<a class="btn btn-default" target="_blank" href="">Show campaign</a>
</div>
Variable CampaignsService.selectCounter is a counter variable and declared in service but when I'm going to use ng-model="CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]" it gives me error -
Error: [$parse:syntax] Syntax Error: Token '{' invalid key at column 35 of the expression [CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]] starting at [{CampaignsService.selectCounter}}]]
And when I use ng-model="CampaignsService.dropDownPercent['{{CampaignsService.selectCounter}}']" it does not give any error but it takes this variable as string.
My question is how could I create a model array and get model's array values in my service ?? I read many questions in stack community and none of the trick work for me. My service under my script, is
.service('CampaignsService', ['$rootScope', 'AjaxRequests', function ($rootScope, AjaxRequests) {
this.dropDownPercent = [];
this.selectCounter = 0;
var gareeb = [];
this.showPercentDefault = 100;
// this.campaignsData = [];
this.$rowsData = {
items: [], //array of objects
current: [], //array of objects
subItems: [] //array of objects
};
this.getRows = function () {
return this.$rowsData;
}
this.addNewRow = function () {
var wowRow = {}; //add a new object
this.getRows().subItems.push(wowRow);
this.selectCounter++;
gareeb.push(0);
}
this.calculatePercentages = function (index) {
angular.forEach(this.getRows().current, function (data, key) {
if (key == index) {
console.log(data);
}
})
}
this.showPercentDropDown = function ($index) {
var balle = 0;
var start;
angular.forEach(gareeb, function (aha, keywa) {
balle += aha;
})
var last = 100 - balle;
var final = [];
for (start = 0; start <= last; start += 10) {
final.push(start);
}
return this.values = {
values: final,
};
}
this.wow = function (valueWa, keyWa) {
console.log(this.dropDownPercent);
gareeb[keyWa] = valueWa;
this.changePercentDropDown();
}
this.changePercentDropDown = function () {
var angElement = angular.element(document.querySelector('.dropDownPercent'));
angular.forEach(angElement, function (data, key) {
console.log(data);
})
}
}])
Target model structure should be
ng-model="CampaignsService.dropDownPercent[1]"
ng-model="CampaignsService.dropDownPercent[2]"
ng-model="CampaignsService.dropDownPercent[3]"
A big thanks in advance.
Since you are in context of the Angular expression, you don't need interpolation tags {{...}}. So ngModel directive should look like this:
ng-model="CampaignsService.dropDownPercent[CampaignsService.selectCounter]"

ng-repeat pagination looses items

I'm learning AngularJS following the good Pro AngularJS written by Adam Freeman.
I'm stuck on ng-repeat pagination using filters. I know there are bootstrap ui directives for Angular, but i'm following this book in order to learn how angular works.
My code:
<section class="row-fluid" ng-controller="GetAjax">
<div class="col-md-12">
<h2>Repater Caricato in Ajax</h2>
</div>
<div class="row-fluid">
<div class="col-md-6" style="max-height: 350px; overflow-y: auto" ng-controller="PagedData">
<ul class="list-group">
<li class="list-group-item" ng-repeat="item in data.visitors | filter:query | range:selectedPage:pageSize">
<b>{{item.id}}.</b> {{item.first_name}} {{item.last_name}} | <small><i>{{item.email}} - {{item.country}} {{item.ip_address}}</i></small>
</li>
</ul>
<ul class="pagination">
<li ng-repeat="page in data.visitors | pageCount:pageSize"
ng-click="selectPage($index + 1)"
ng-class="pagerClass($index + 1)">
<a>{{$index + 1}}</a>
</li>
</ul>
</div>
</div>
</section>
Angular filters
angular.module("customFilters")
/******* Filters per la paginazione dei dati ******************/
//Genera il range di dati in base alla page size
.filter("range", function ($filter) {
return function (data, page, size) {
if (angular.isArray(data) && angular.isNumber(page) && angular.isNumber(size)) {
var start_index = (page - 1) * size;
console.log(data.length);
if (data.length < start_index) {
return [];
} else {
return $filter("limitTo")(data.splice(start_index), size);
}
} else {
return data;
}
}
})
//Calcola il numero di pagine
.filter("pageCount", function () {
return function (data, size) {
if (angular.isArray(data))
{
var result = [];
for (var i = 0; i < Math.ceil(data.length / size) ; i++) {
result.push(i);
}
return result;
}
else
{
return data;
}
}
});
Angular Controller
.controller("GetAjax", function($scope, $http){
$http.get('data/visitors.json').success(function(data) {
$scope.data = {visitors : data};
});
})
.constant("activeClass", "active")
.constant("perPage", 30)
.controller("PagedData", function($scope, $filter, activeClass, perPage){
$scope.selectedPage = 1;
$scope.pageSize = perPage;
console.log("page"+ $scope.selectedPage);
$scope.selectPage = function (newIndex) {
$scope.selectedPage = newIndex;
console.log( {idx: newIndex});
}
$scope.pagerClass = function (index) {
return (index == $scope.selectedPage) ? activeClass : "";
}
});
The result is that after 3 range filter invocations during the page render, the data array looses all the data.
Strange is that using the example from the book this code works perfectly.
Please, help me to know my error :D
splice function overwrites array
if you have an array
a = [1,2,3,4];
a.splice(2,1);
// a = [1,2,4]
results is a = [1,2,4]
use slice instead

AngularFire add in reverse order

I need to add objects to Firebase in reverse order. Or reverse data when goes data binding. Or sort objects by time of create.
var ref = new Firebase("https://[url].firebaseio.com/");
$scope.messages = $firebase(ref);
$scope.addMessage = function(e) {
$scope.messages.$add({title: $scope.title, body: $scope.msg, time: $scope.getDate() });
}
<div class="well span3 pull-left note" ng-repeat="(key, msg) in messages">
<button type='button' class='close' ng-click="messages.$remove(key)">×</button>
<b>{{msg.time| date: 'medium'}}</b>
<span>{{msg.title}}</span>
<span>{{msg.body}}</span>
<button ng-click="changeMessage(key)" class="btn btn-mini pull-right"><i class="icon-pencil"></i></button>
</div>
I try to use OrderBy atribute for ng-repeat but this is not easy because in messages are stored objects.
Check out the chat example in angularFire-seed. It uses a custom reverse filter
The reverse filter looks like so:
app.filter('reverse', function() {
function toArray(list) {
var k, out = [];
if( list ) {
if( angular.isArray(list) ) {
out = list;
}
else if( typeof(list) === 'object' ) {
for (k in list) {
if (list.hasOwnProperty(k)) { out.push(list[k]); }
}
}
}
return out;
}
return function(items) {
return toArray(items).slice().reverse();
};
});
And the usage is like so:
<ul id="messages" ng-show="messages">
<li ng-repeat="message in messages | reverse">{{message.text}}</li>
</ul>

Resources