Don't work sort in angular-tablesort - angularjs

I try to work with angular-sortable, but maybe I made something wrong because this code doesn't work.Where my mistake? All thead clickable, but it does sorting data in the table, just change css styles on click. Maybe I wrote wrong ts-criteria or wrong work with data?
My table:
<table ts-wrapper>
<thead>
<tr>
<th class="add">Add</th>
<th ts-criteria="population" ng-repeat="year in vm.years" ts-repeat>{{ year }}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="city in vm.cities" ts-repeat>
<td >{{ city.name }}</td>
<td ng-repeat="population in city.population">{{ population }}</td>
</tr>
</tbody>
</table>
This is my controller:
(function () {
'use strict';
var app = angular.module("app",['tableSort']);
app.controller("TableController", TableController);
function TableController () {
var vm = this;
vm.years = ['2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014'];
vm.cities = [
{
"name":"Москва",
'population':{
'2005': '7000000',
'2006':'7300000',
'2007':'7800000',
'2008':'8000000',
'2009':'8400000',
'2010':'8700000',
'2011':'9000000',
'2012':'9400000',
'2013':'9800000',
'2014':'10000000'
}
},
{
"name":"Санкт-Петербург",
'population':{
'2005':'6000000',
'2006':'6300000',
'2007':'6800000',
'2008':'7000000',
'2009':'7400000',
'2010':'7700000',
'2011':'8000000',
'2012':'8400000',
'2013':'8800000',
'2014':'9000000'
}
},
{
"name":"Калининград",
'population':{
'2005':'2000000',
'2006':'2300000',
'2007':'2800000',
'2008':'3000000',
'2009':'3400000',
'2010':'3700000',
'2011':'4000000',
'2012':'4400000',
'2013':'4800000',
'2014':'4900000'
}
},
{
"name":"Архангельск",
'population':{
'2005':'295000',
'2006':'300000',
'2007':'305000',
'2008':'308000',
'2009':'310000',
'2010':'315000',
'2011':'318000',
'2012':'324000',
'2013':'331000',
'2014':'341000'
}
},
{
"name":"Астрахань",
'population':{
'2005':'493000',
'2006':'497000',
'2007':'499000',
'2008':'502000',
'2009':'504000',
'2010':'507000',
'2011':'509000',
'2012':'513000',
'2013':'514000',
'2014':'520000'
}
},
{
"name":"Уфа",
'population':{
'2005':'1028000',
'2006':'1034000',
'2007':'1036000',
'2008':'1038000',
'2009':'1042000',
'2010':'1047000',
'2011':'1051000',
'2012':'1054000',
'2013':'1059000',
'2014':'1062000'
}
},
{
"name":"Белгород",
'population':{
'2005':'318000',
'2006':'321000',
'2007':'330000',
'2008':'333000',
'2009':'339000',
'2010':'342000',
'2011':'345000',
'2012':'350000',
'2013':'354000',
'2014':'356000'
}
},
{
"name":"Брянск",
'population':{
'2005':'381000',
'2006':'384000',
'2007':'390000',
'2008':'394000',
'2009':'397000',
'2010':'400000',
'2011':'402000',
'2012':'404000',
'2013':'413000',
'2014':'415000'
}
},
{
"name":"Улан-Удэ",
'population':{
'2005':'370000',
'2006':'372000',
'2007':'375000',
'2008':'379000',
'2009':'384000',
'2010':'391000',
'2011':'396000',
'2012':'397000',
'2013':'400000',
'2014':'404000'
}
},
{
"name":"Волгоград",
'population':{
'2005':'991000',
'2006':'995000',
'2007':'999000',
'2008':'1001000',
'2009':'1004000',
'2010':'1010000',
'2011':'1012000',
'2012':'1015000',
'2013':'1019000',
'2014':'1021000'
}
},
];
}
}());

[Answer updated to match your fiddle]
There are many many problems:
The worst is that the tablesorter does not handle criteria columns
with names that are numeric (such as a year). So they need to be
parseable only as strings. Like "y2010" for example.
The ts-criteria="population['year']" thing doesn't work. There is no such array.
It doesn't seem to like your "track by" directives.
It doesn't like ng-repeats in the data columns either, so I had to take out the population sub-object.
Also you are not specifying a filter for the ts-criteria, which will screw up your sorting since the population numbers will be sorted as Strings ("900" > "10000" for example....).
So basically tablesorter will only work if you follow the example code really close :-). Unless you start fixing those problems. There is a fiddle at http://jsfiddle.net/o15bLvb2/2/ which makes all of this work.
Your body becomes:
<body ng-app="app" ng-controller="TableController as vm">
<table cellpadding="10" cellspacing="10" ts-wrapper >
<thead>
<tr>
<th class="add" ts-criteria="add" ts-default>Add</th>
<th ts-criteria="y2005|parseInt">y2005</th>
<th ts-criteria="y2006|parseInt">y2006</th>
<th ts-criteria="y2007|parseInt">y2007</th>
<th ts-criteria="y2008|parseInt">y2008</th>
<th ts-criteria="y2009|parseInt">y2009</th>
<th ts-criteria="y2010|parseInt">y2010</th>
<th ts-criteria="y2011|parseInt">y2011</th>
<th ts-criteria="y2012|parseInt">y2012</th>
<th ts-criteria="y2013|parseInt">y2013</th>
<th ts-criteria="y2014|parseInt">y2014</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="city in vm.cities track by city.name" ts-repeat>
<td>{{ city.name }}</td>
<td>{{ city.y2005 }}</td>
<td>{{ city.y2006 }}</td>
<td>{{ city.y2007 }}</td>
<td>{{ city.y2008 }}</td>
<td>{{ city.y2009 }}</td>
<td>{{ city.y2010 }}</td>
<td>{{ city.y2011 }}</td>
<td>{{ city.y2012 }}</td>
<td>{{ city.y2013 }}</td>
<td>{{ city.y2014 }}</td>
</tr>
</tbody>
</table>
</body>

Related

Angular execute get service based on array returned by antoher get with ForkJoin

Problem:
Trying to populate a table with information from 2 services:
The first service returns a lista of fabric plans that contain an array with machine operations. The second service is a get that returns a specific operation by id, that is used to get the information about the operation.
The problem is that the service can only receive one id.
How can I populate the table with the operation information knowing that a fabric plan as one or more operations.
The Fabric Plan Model
export class Fabricplan{
Id: number;
Description: string;
operationsIds: Array<Number> = [];
DateStart: Date;
}
The service responsible for the post request:
getOperation(Id):Observable<Operation[]>{
return this.http.get<Operation[]>(`${this.operations}${Id}`, httpOptions);
}
The html table is the following:
<table class="table table-hover">
<thead class="thead-dark">
<tr>
<th scope="col">Number</th>
<th scope="col">Description</th>
<th scope="col">Operations</th>
<th scope="col">DateStart</th>
</tr>
</thead>
<tbody>
<tr scope="row" id="table" *ngFor="let fabricplan of fabricplans let i = index" (click)="open(content, fabricplan.id)">
<td>{{ i+1 }}</td>
<td>{{ fabricplan?.description }}</td>
<td>{{ oper_desc[id] }}</td>
<td>{{ fabricplan?.dateStart }}</td>
</tr>
</tbody>
</table>
In the fabricplan.component.ts file
ngOnInit() {
this.fabricplanservice.getfabricplans().subscribe(fabricplans => {
this.fabricplans = fabricplans;
const opers_desc$ = this.fabricplans.map( element =>
this.operationservice.getOperation(element).pipe(
// map it to the value you want
map((response) => {
this.operation = response;
return this.operation['description'];
}),
// replace 404 responses with the 'No fabric plan'
// if not 404 throw the error again
catchError((error) => {
if(error.status === 404){
return this.empt;
} else {
throwError(error);
}
}
)));
forkJoin(opers_desc$).subscribe((opers_desc) => this.oper_desc = opers_desc);
});
this.operationservice.getOperations().subscribe(operation => {
this.operations = operation;
});
}
}

How to collapse and hide in ng-repeat over table?

So I have a table where I need to show parent deals and on ng-show(clicking parent deal) I want to show child deals.
<table class="table table-hover">
<thead class="thead-dark">
<tr>
<th scope="col">Name</th>
<th scope="col">No_Of_Orders</th>
<th scope="col">Size</th>
<th scope="col">Book_Size</th>
<th scope="col">Remarks</th>
<th scope="col">Price_Guidance</th>
<th scope="col">CONTROL</th>
<th scope="col">Status</th>
<th scope="col">Current_Cut_Off</th>
<th scope="col">Tenor</th>
<th scope="col">Book</th>
<th scope="col">ORDCOLUMN</th>
<th scope="col">PKEY</th>
<th scope="col">Save</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="parentDeal in parentDeals track by $index" ng-click="childShow(parentDeal.PKEY)">
<td>{{parentDeal.Name}}</td>
<td>{{parentDeal.No_Of_Orders}}</td>
<td>{{parentDeal.Size}}</td>
<td>{{parentDeal.Book_Size}}</td>
<td>{{parentDeal.Remarks}}</td>
<td>{{parentDeal.Price_Guidance}}</td>
<td>{{parentDeal.CONTROL}}</td>
<td>{{parentDeal.Status}}</td>
<td>{{parentDeal.Current_Cut_Off}}</td>
<td>{{parentDeal.Tenor}}</td>
<td>{{parentDeal.Book}}</td>
<td>{{parentDeal.ORDCOLUMN}}</td>
<td>{{parentDeal.PKEY}}</td>
<td>{{parentDeal.Save}}</td>
<tr ng-repeat="childDeal in childDeals track by $index" ng-show = "childRowShow_{{childDeal.PKEY}}">
<td>{{childDeal.Name}}</td>
<td>{{childDeal.No_Of_Orders}}</td>
<td>{{childDeal.Size}}</td>
<td>{{childDeal.Book_Size}}</td>
<td>{{childDeal.Remarks}}</td>
<td>{{childDeal.Price_Guidance}}</td>
<td>{{childDeal.CONTROL}}</td>
<td>{{childDeal.Status}}</td>
<td>{{childDeal.Current_Cut_Off}}</td>
<td>{{childDeal.Tenor}}</td>
<td>{{childDeal.Book}}</td>
<td>{{childDeal.ORDCOLUMN}}</td>
<td>{{childDeal.PKEY}}</td>
<td>{{childDeal.Save}}</td>
</tr>
</tr>
</tbody>
</table>
This is the basic data:-
$scope.allDeals = [
{
"ORDCOLUMN":"2017-11-17T05:00:00.000000000Z",
"CONTROL":"N",
"PKEY":"UD0000000000720",
"Name":"rajat10 10:19",
"Tenor":"0Y",
"Size":0,
"Price_Guidance":"43%",
"Remarks":"-",
"Book_Size":20,
"Status":"Open",
"No_Of_Orders":2,
"Current_Cut_Off":2.3,
"Book":"Book#ReOffer",
"Save":"Edit"
},
{
"ORDCOLUMN":"2017-11-17T05:00:00.000000000Z",
"CONTROL":"Y",
"PKEY":"UD0000000000720",
"Name":"rajat10 10:19",
"Tenor":"Multi ...",
"Size":0,
"Price_Guidance":"-",
"Remarks":"-",
"Book_Size":20,
"Status":" Open",
"No_Of_Orders":2,
"Current_Cut_Off":2.3,
"Book":"Book#ReOffer",
"Save":"Edit"
},
{
"ORDCOLUMN":"2017-11-17T05:00:00.000000000Z",
"CONTROL":"N",
"PKEY":"UD0000000000720",
"Name":"rajat10 10:19",
"Tenor":"Perp",
"Size":0,
"Price_Guidance":"19%",
"Remarks":"-",
"Book_Size":0,
"Status":"Open",
"No_Of_Orders":2,
"Current_Cut_Off":2.3,
"Book":"Book#ReOffer",
"Save":"Edit"
}
....and so on
]
So, this data can be grouped by PKEY and parent object has control - "Y", child object has control - "N". Note:- There can be objects where there is only parent deal with no child deals.
In my app.js:-
$scope.parentDeals = $scope.allDeals.filter(function (item,index) {
return item.CONTROL == "Y";
});
$scope.childDeals = [];
$scope.childShow = function (PKEY) {
if($scope["childRowShow_"+PKEY]){
$scope["childRowShow_"+PKEY] = false;
}
else{
$scope.childDeals = $scope.allDeals.filter(function (item,index) {
if(item.PKEY == PKEY && item.CONTROL == "N"){
return item;
}
});
$scope["childRowShow_"+PKEY] = true;
}
};
Here, I am making two arrays:- parentDeals and childDeals.
Right now, I am applying ng-repeat on the separate row so, child deals are showing after all parent deals. Is there any way I can show them below the respective parent deals or can apply a different solution?
Yes, with ng-repeat-start and ng-repeat-end, we can explicitly specify the starting and ending for ng-repeat. So, instead of using the ng-repeat directive on one single DOM element, we can specify the ng-repeat-start and ng-repeat-end on any two DOM elements.
For eg.
<div ng-app="app">
<table ng-controller="TestController">
<tr ng-repeat-start="d in data">
<td><strong>{{d.name}}</strong></td>
</tr>
<tr ng-repeat-end>
<td>{{ d.info }}</td>
</tr>
</table>
</div>
<script>
var app = angular.module('app', []);
app.controller('TestController', function ($scope) {
$scope.data = [{
name: 'ABC',
info: 'Bangalore'
}, {
name: 'XYZ',
info: 'Mumbai'
}];
});
</script>

Angular js table with dynamic columns and values

I have a data structure as follow;
[
{
"a1": 941,
"b1": "abc",
"c1": "aaa",
"a2": 27103,
"b2": "ttt",
"c2": "zzz"
},
{
"a1": 456,
"b1": "xxx",
"c1": "yyy",
"a2": 7632,
"b2": "mmm",
"c2": "nnn"
}
]
I use angular js table with dynamic column names which are different from keys in the structure. Since there are many of them, I do not want to write key names like;
<table st-table="table_data_raw" style="" class="table table-striped forms-list-table">
<tr>
<th ng-repeat="dateColumnName in dateColumnNames ">{{ dateColumnName }}
</th>
</tr>
<tbody>
<tr ng-repeat="row in data">
<td>{{row.a1 }}</td>
<td>{{row.b1 }}</td>
<td>{{row.a2 }}</td>
<td>{{row.b2 }}</td>
<td>{{row.c2 }}</td>
</tr>
</tbody>
</table>
How can I get table values dynamically without specifying their names in that structure from "data"?
Try using $index to refer to the ng-repeat item you wish to access (in your example it would be index 0 or 1). Here is code/fiddle (click items in the table to get their value dynamically):
https://jsfiddle.net/AdamKMorris/ox89o7L0/
using $Index:
<tr ng-repeat="row in data">
<td ng-click="chosenValueA1($index);">{{row.a1 }}</td>
...
</tr>
Then the angularJs:
$scope.chosenValueA1 = function(i)
{
$scope.myValue = $scope.data[i].a1;
}
If you want to access a1,a2,b1,b2, etc. then you will need to nest ng-repeat and use $index for each to refer to the value.

Pass value to another controller in angularjs

I am new to AngularJS.
I have a div assigned controller to controller1. In this div, I am showing EmployeeList with three links for View, Edit,Delete for each employee.
I have another div assigned controller to controller2. By clicking the view link on any employee, I want to show full details in second div. Both divs are in same page.
How do I do that? Below is what I tried.
<div ng-controller="employeeController" style="border:solid black 3px;float:left;padding:5px">
<h3 style="color:#ff6a00">List Of Employees</h3>
<table>
<tr>
<th hidden>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Full Name</th>
<th>Actions</th>
</tr>
<tr ng-repeat="employee in employees">
<td hidden><strong>{{ employee.ID }}</strong></td>
<td>{{ employee.FName }}</td>
<td>{{ employee.LName }}</td>
<td><strong>{{ employee.FName + ' ' + employee.LName }}</strong></td>
<td>
<a data-ng-click="GetEmployeeByID({{employee.ID}})" href="javascript:;">View</a>
</td>
</tr>
</table>
</div>
<div ng-controller="employeeByIDController" style="border:solid black 3px;float:right;padding:5px">
<h3 style="color:#ff6a00">Employee Details</h3>
<table>
<tr>
<th hidden>ID</th>
<th>Full Name</th>
<th>Qualification</th>
<th>Gender</th>
<th>Phone</th>
<th>Email</th>
<th>Address</th>
<th>City</th>
</tr>
<tr>
<td hidden><strong>{{ employeeByID.ID }}</strong></td>
<td>{{ employeeByID.FName + ' ' + employeeByID.LName }}</td>
<td>{{ employeeByID.Qualification }}</td>
<td>{{ employeeByID.Gender }}</td>
<td>{{ employeeByID.Phone }}</td>
<td>{{ employeeByID.Email }}</td>
<td>{{ employeeByID.Address }}</td>
<td>{{ employeeByID.City }}</td>
</tr>
</table>
</div>
The code in factory is as below.
mainApp.factory('EmployeeFactory', function ($http) {
return {
GetEmployeeList: function () {
return $http({
method: 'GET',
url: '/AngularEmployee/EmployeeList'
});
}
}
return {
GetEmployeeByID: function ($id) {
return $http({
method: 'GET',
url: '/AngularEmployee/EmployeeByID',
params: { empID : id }
});
}
}
});
I have added controller as follows.
mainApp.controller("employeeController", ['$scope', 'EmployeeFactory', function ($scope, EmployeeFactory) {
$scope.GetEmployeeList = function () {
EmployeeFactory.GetEmployeeList().success(function (data) {
$scope.employees = data;
}).error(function (data) {
$scope.error = "An Error has occured while Loading users! " + data.ExceptionMessage;
});
};$scope.GetEmployeeList();
}]);
Angular has a pubsub mechanism for this. It's well documented. E.g.:
https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/
if you want to share data between two controllers in angularJs , using a service or factory is a better option as service/factory in angularJs are injectable.But service/factory is a singleton object so be aware of the fact that same object of the service/factory will be shared by all the controllers.
Taking your example ,
you can create another service :
mainApp.service('sharedService',function(){
this.employee={};
this.getter=function(){
return this.employee;
};
this.setter=function(emp){
this.employee=emp;
};
});
Then you can share this service across your controllers to get or set employee.
mainApp.controller("employeeController", ['$scope', 'EmployeeFactory', 'sharedService', function($scope, EmployeeFactory, sharedService) {
$scope.GetEmployeeList = function() {
EmployeeFactory.GetEmployeeList().success(function(data) {
$scope.employees = data;
sharedService.setter($scope.employees);//set in shared service
}).error(function(data) {
$scope.error = "An Error has occured while Loading users! " + data.ExceptionMessage;
});
};
$scope.GetEmployeeList();
}]);
And then in employeeByIDControlle ,
mainApp.controller("employeeByIDController", ['$scope', 'EmployeeFactory', 'sharedService', function($scope, EmployeeFactory, sharedService) {
$scope.employees = sharedService.getter();//get from shared service
}]);

Dynamically setting new ng-model when pushing model to array

Can't figure out how to dynamically add a new model whenever a new row is added to the page. For example, the input select box ng-model= infos.rigBonusInfo.rigName is used for all select box I've added to the page. I would like to have a different model attached to a each select inputs. I tried using ng-model= infos.rigBonusInfo.rigName[rigBonus] but it doesn't work for the rates as the same model gets attachedto each rate field.
Pretty much what I want to do is to bind a new model whenever a new row gets pushed into the array.
Currently, I have a nested table which is the following:
<div class="col-lg-5">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Rig</th>
<th>Rig Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="rig in rigs">
<td>{{ $index + 1 }}</td>
<td>{{ rig.name }}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-lg-2"></div>
<div class="col-lg-5">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Bonus Name</th>
<th>Rate</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="bonus in create.rigBonusRates">
<td>{{ bonus.rateName }}</td>
<td>{{ bonus.rate }}</td>
</tr>
</tbody>
</table>
</div>
<table>
<thead>
<tr>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="rigDate in rigDateList track by $index">
<td><input ui-date="datepickerOptions" ng-model="date" /></td>
<td>
<table>
<thead>
<tr>
<th>Rig</th>
<th>Rate1</th>
<th></th>
<th>Rate2</th>
<th></th>
<th>Rate3</th>
<th></th>
<th>Rate4</th>
<th></th>
<th>Comments</th>
</tr>
</thead>
<tr ng-repeat="rigBonus in rigBonusList track by $index">
<td><select ng-options="rig as rigs.indexOf(rig) + 1 for rig in rigs" ng-model="infos.rigBonusInfo.rigName[rigBonus]" ></select></td>
#for (var i = 1; i < 5; i++)
{
<td><select ng-options="rigBonus.rateName for rigBonus in create.rigBonusRates" ng-model="infos.rigBonusInfo.rate#(#i)"></select></td>
<td><input type="text" ng-disabled="infos.rigBonusInfo.rate#(#i).rateName != 'Special' " ng-model=infos.rigBonusInfo.rate#(#i).rate /></td>
}
<td><input ng-model="info.rigBonusInfo.comments" /></td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
<div>
<button type="button" ng-click="add()">Add</button>
<button type="button" ng-click="addDate()">Add Date</button>
</div>
My current controller has the following:
angular.module('RigBonus').controller('rigCreateController', ['$scope', '$http', 'PayPeriodService', 'RigLegendService',
function ($scope, $http, PayPeriodService, RigLegendService, RigBonusRateService) {
$scope.rigs = RigLegendService.getRigLegend();
$scope.datepickerOptions = {
orientation: 'top',
startDate: PayPeriodService.getStartDate(),
endDate: PayPeriodService.getEndDate()
};
$http({ method: 'GET', url: '/Home/CreateData' }).success(function (data) {
$scope.create = data;
$scope.infos = {
rigBonusInfo: {
rigName: $scope.rigs[0],
rate1: $scope.create.rigBonusRates[0],
rate2: $scope.create.rigBonusRates[0],
rate3: $scope.create.rigBonusRates[0],
rate4: $scope.create.rigBonusRates[0],
comment: ""
}
};
$scope.add = function () {
$scope.rigBonusList.push();
};
$scope.addDate = function(){
$scope.rigDateList.push("");
};
});
$scope.rigBonusList = [$scope.rigBonusInfo];
$scope.rigDateList = [];
$scope.submit = function () {
$http.post('/Home/Create', {model: "testing"} );
};
}]);
I figured out my issue. My problem was that I was not sure how to generate a new object when a new row of controls are added. Think I should have put something on fiddleJS to help people visualize it better. As a static model was used ($scope.infos) as ng-model, the same model was used for two different controls which I don't want. I want all my controls to be unique.
The fix was to create the object I had in mind which is the following:
$scope.rigDateList = [{
date: "",
rigBonusList: [{}]
}];
So it is an array of objects where the object contains a date and another array of objects.
When I want to push new objects to the inside array which I didn't know I could just create objects like this at the time. I was trying to figure out a way to dynamically create new models ng-model could by declaring them in the controller. I use the following function:
$scope.rigDateList[$scope.rigListIndex].rigBonusList.push({
rigName: "",
rate1: "",
rate2: "",
rate3: "",
comments: ""
});
I also didn't know that I could use elements inside the array from ng-repeat. In the following case, it is rigBonus that I could have used as a model instead of infos model.
<tr ng-repeat="rigBonus in rigDate.rigBonusList track by $index">
<td><select ng-options="rig as rigs.indexOf(rig) + 1 for rig in rigs" ng-model="rigBonus.rigName"></select></td>
and when I want to push to the outside array I use the following:
$scope.rigDateList.push({
date: "",
rigBonusList: [""]
});
$scope.rigListIndex = $scope.rigListIndex + 1;
I use an index to keep track of which object I'm in.
A more closest question and answer is that:
Ng-repeat with dynamic ng-model on input not working
please, take a look.

Resources