angularjs - ngTable not sorting - javascript

im using ngTable. Sorting is not working.
Pagination works nice and it shows all my data as I need. But I can't sort.
I'm using $data (I dont know what is for) but still can't sort.
My html:
<div class="panel-heading">
<table ng-table="vm.tableParams">
<tbody>
<tr ng-repeat="event in $data">
<td data-title="'Nombre'" sortable="'name'"> {{ event.phone ? "Tex1" : Text2 }}</td>
<td data-title="'Dia Entero'" sortable="'entero'">{{ event.allDay ? '√' : 'X' }}</td>
<td data-title="'F. Inicio'" sortable="'inicio'">{{ event.start | date:'dd-MM-yyyy' }}</td>
<td data-title="'F. Fin'" sortable="'fin'"> {{ event.end | date:'dd-MM-yyyy' }}</td>
<td data-title="'Telf.'" sortable="'telf'"> {{ event.phone ? event.phone : '--' }}</td>
</tr>
</tbody>
</table>
</div>
My js:
// My data
[{
"title":"Cerrado",
"start":"2015-12-24T23:00:00.000Z",
"allDay":true,
"backgroundColor":"#f05050",
"borderColor":"#f05050"
},
{
"title":"Abierto",
"start":"2016-04-10T04:00:00.000Z",
"end":"2016-04-10T08:00:00.000Z",
"backgroundColor":"#43d967",
"borderColor":"#43d967"
},
{
"title":"Mi Guardia",
"start":"2015-12-24T01:00:00.000Z",
"end":"2015-12-24T08:00:00.000Z",
"backgroundColor":"#5d9cec",
"borderColor":"#5d9cec"
},
{
"title":"super farmacias",
"phone":"677889966",
"address":"Calle badajoz 200",
"start":"2016-01-06T02:00:00.000Z",
"end":"2016-01-06T09:00:00.000Z",
"backgroundColor":"#dde6e9",
"borderColor":"#dde6e9",
"textColor":"#555"
}]
var data = vm.events;
vm.tableParams = new ngTableParams({
page: 1, // show first page
count: 8, // count per page
sorting: {
name: 'asc'
}
},
{
total: data.length,
counts: [],
getData: function($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ?
$filter('orderBy')(data, params.orderBy()) :
data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
I have been trying for 2 hours with a lot of examples and changing $data for vm.values and creating other variables and stuffs.
Any idea why sort is broken?
Thanks

After checking your data, you have to modified the HTML code sortable = the object key.
Because when you sort some data in the table using ng-table, it is based on what data is displaying in the table. In this case, it will be the data you just posted. And in your data, you don't have a field called name, entero and etc. Therefore, the sort function is not working for you.
<tr ng-repeat="event in $data">
<td data-title="'Nombre'" sortable="'title'"> {{ event.phone ? "Tex1" : Text2 }}</td>
<td data-title="'Dia Entero'" sortable="'allDay'">{{ event.allDay ? '√' : 'X' }}</td>
<td data-title="'F. Inicio'" sortable="'start'">{{ event.start | date:'dd-MM-yyyy' }}</td>
...
</tr>

Usually for sorting, reverseSort feature is handy, Please try this to sort
<th>Field Name</th>

Related

How to sort columns in Vue when the values to sort are the result of calculations

I've found many resources for sorting data that is already in an array but can't find anything on sorting dynamically generated data.
<table>
<thead>
<tr>
<th>Program</th>
<th>Rewards</th>
</tr>
</thead>
<tbody>
<tr v-for="program in programs" :key="program.id">
<td>{{ program.program_name }}</td>
<td>{{ pointValue(program) | percent }}</td>
</tr>
</tbody>
</table>
pointValue() is a method which calculates and returns a value which is displayed as a %. this is the Rewards column. i would like the table to be sortable by Programs and by Rewards. (Program is just a string).
Create computed array for programs using map and sort method and iterate it instead
computed: {
computedPrograms() {
return this.programs
.map(program => {
return {
...program,
value: this.pointValue(program)
}
})
.sort((a, b) => a.value - b.value)
}
}
<tr v-for="program in computedPrograms" :key="program.id">
<td>{{ program.program_name }}</td>
<td>{{ program.value | percent }}</td>
</tr>

nested tables from json object using anguarJS

Im trying to display a json object using angular. the object may have nested object or not, so i need to evaluate in runtime.
The logic is as follows :
for each key-val (k,v):
if v is an object then: for each (k2,v2) add another nested table in the HTML_TD. if not - need to print the value in a HTML_TD
The nested object works.
The problem : when v is an object i expect the expression to evaluates to '' and print nothing (because im going to an inner loop k2,v2) but instead, even if v is an object, it print it out to the HTML_TD
code :
<table border="1">
<tr ng-repeat="(k,v) in json.properties">
<td> {{ k }} </td>
<td> {{ typeof (v) == 'object' ? '' : v }} </td>
<td>
<table>
<tr ng-repeat="(k2,v2) in v">
<td> {{ k2 }} </td>
<td> {{ v2 }} </td>
</tr>
</table>
</td>
</tr>
The typeof function is not defined on angularjs template interpolation, the template syntax is a bit limited in terms of javascript functions but you can declare it on your scope like so:
$scope.typeof = function(obj) {
return typeof(obj);
};
So that a function named typeof will be visible on your scope and your snipet will be able to get working. The bellow snipet is a simple example implementing this solution.
angular.module('myApp', [])
.controller('myController', function($scope) {
$scope.json = {
properties: {
a: 'A',
b: 'B',
c: {
a1: 'A1'
}
}
};
$scope.typeof = function(obj) {
return typeof(obj);
};
});
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.js"></script>
<div ng-controller="myController">
<table border="1">
<tr ng-repeat="(k,v) in json.properties">
<td>{{ k }}</td>
<td>{{ typeof(v) == 'object' ? '' : v }}</td>
<td>
<table border="1">
<tr ng-repeat="(k2,v2) in v">
<td>{{ k2 }}</td>
<td>{{ v2 }}</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
I think angular parser don't allow typeof function in template.
But you can define one method in controller to get typeof.
E.g.:
$scope.getTypeof = function(value) {
return typeof value;
};
Now call this method in template code:
{{ getTypeof(v) === 'object' ? '' : v }}

ng-repeat takes too much time to render data

I know there are many questions already posted for the same issue but none of the solutions work in my case.
On calling a web service I get JSON response. In this JSON, there are around 2000+ objects from which I need to display data on the table. I want to display all (2000+) records in the table and Yes, I cannot limit or paginate, need to display it on a single page (I know it's stupid but it's the business requirement). I don't need sorting or searching.
Data transfer is about 2MB and the request completes in about 2-4 secs approx. but it takes around 10-15 secs to data render on the page.
Now, what I am looking for is either speed ng-repeat binding things up (if possible) or display the data as soon as I receive it and keep on adding it until all rows are displayed.
Check out the code below :
HTML
<table class="table table-bordered table-striped cf">
<thead style="color: #333;">
<tr>
<td>Asset Name</td>
<td>Date/ Time</td>
<td>Location</td>
<td>Ignition</td>
<td>Speed</td>
<td>Heading</td>
<td>Direction</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="cols in tableData">
<td>{{ cols.aN }}</td>
<td>{{ cols.dT }}</td>
<td>{{ cols.Lat }}, {{ cols.Lon }}</td>
<td>{{ cols.I }}</td>
<td>{{ cols.S }}</td>
<td>{{ cols.H }}</td>
<td>{{ cols.D }}</td>
</tr>
</tbody>
</table>
JS
var ignition_text = '';
var lat = '';
var lon = '';
for (var i = 0; i < data.length; i++) {
if (data[i].ignition = 1) {
ignition_text = "On";
} else {
ignition_text = "Off";
}
$scope.$apply(function() {
$scope.tableData.push({
aN: name,
dT: data[i].eventUTCTime,
Lat: data[i].latitudeDegrees,
Lon: data[i].longitudeDegrees,
I: ignition_text,
S: data[i].speedMPH,
H: data[i].longitudeDegrees,
D: data[i].latitudeDegrees
});
});
}
Thanks in advance!
You probably wont need $scope.$apply at all. And even if you need it, you should only use it once you pushed all data to the table. Otherwise, every added entry will force an digest-cycle. Just build your array and assign the finished array to the scope-variable. Then angular will only build the table once.
Depending on the nature of your variable name you may be able to eliminate the array building as well and just use the data you are downloading. Apart from nameyou just use that data anyway.
Here is a plunk that has a similar data size but loads much faster http://plnkr.co/edit/I4rN1ZMaR3e1mbcsJ9Ka. If you were to make a quick plunk I could use your data and edit your code but from the looks you just need the main assignment to the scope without the apply for the data and add a track by to the ng-repeat. SN: You would want to manipulate your data inside the for loop then do the assignment to the scope.
for (var i = 0; i < data.length; i++) {
if (data[i].ignition = 1) {
ignition_text = "On";
} else {
ignition_text = "Off";
}
}
$scope.tableData=data;
JS
$http.get("largeData.json").then(function(response) {
vm.test = response.data;
});
HTML
<tbody>
<tr ng-repeat="(key, value) in main.test track by $index ">
<td>{{ value.ask }}</td>
<td>{{ value.bid }}</td>
<td>{{ value.volume_btc }}, {{ value.volume_percent }}</td>
<td>{{ value.last }}</td>
<td>{{ value.timestamp }}</td>
</tr>
</tbody>

Angular Scope length not working

I have a scope dumping into a table via an ng-repeat. This data is filtered by 3 different things, 2 selects and a text box. All of this works fine, but I need to echo out how many results are in the table. Using {{ sounds.length }} obviously doesn't work because this is a count prior to the filtering and filtering has no effect on that. so i added a variable sound in soundsres = (sounds | filter: filters here) but doing {{ soundsres.length }} echos out nothing with no errors in the console.
Below is a complete set of code. What am I missing here. all indications (i even checked the docs and several older threads here on SO) indicate that this should be working. Thanks in advance.
Code:
<input type="text" ng-model="gearsearch">
<select ng-model="stypesearch"><option>1</option></select>
<select ng-model="stypesearch2"><option>2</option></select>
<span>{{ soundsres.length }}</span>
<table ng-controller="GearController">
<tr ng-repeat="sound in soundsres = (sounds | filter: gearsearch | filter: stypesearch | filter: stypesearch2)">
<td>{{ sound.id }}</td>
<td>{{ sound.model }}</td>
<td>{{ sound.make }}</td>
<td>{{ sound.type }}</td>
<td>{{ sound.class }}</td>
<td>{{ sound.status }}</td>
<td>{{ sound.cost | currency }}</td>
</tr>
</table>
You could use controllerAs syntax and add the soundRes to your MainController or you could use $parent.soundRes to add your filter result to parent scope. I think the controllerAs method is more clear but both will work.
Please have a look at the demo below or in this fiddle.
(Sorry for my poor data model in the demo but I don't have a better one. But it's OK to show that the length is correctly updated.)
angular.module('demoApp', [])
.controller('ViewController', function() {
var vm = this,
sameDate = new Date();
sameDate.setMinutes(sameDate.getMinutes() - 5);
var dateLimit = new Date(sameDate);
var dates = [
{
name: 'test1',
date: new Date(sameDate)
},
{
name: 'test2',
date: new Date(sameDate)
},
{
name: 'test3',
date: new Date()
}];
vm.dates = dates;
})
.controller('MainController', MainController);
function MainController() {
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="MainController as mainCtrl">
<input ng-model="mainCtrl.searchText"/>
<select ng-model="mainCtrl.stypesearch"><option>1</option></select>
<select ng-model="mainCtrl.stypesearch2"><option>2</option></select>
<!--results: {{mainCtrl.filterRes.length}}-->
results: {{filterRes.length}}
<ul ng-controller="ViewController as viewCtrl">
<li ng-repeat="date in $parent.filterRes = ( viewCtrl.dates | filter:mainCtrl.searchText | filter: mainCtrl.stypesearch | filter: mainCtrl.stypesearch2 )">{{date}}</li>
</ul>
</div>

How can I pass date value to WebAPI from Angular Client?

I'm using a dynamic value to pass data from database. I'm not sure how to pass the value from the client to the server to get the expected data result.
Here the WebAPI Ctrl:
[HttpGet]
public IQueryable<getAllDayReps_Result> GetRepsByDate(DateTime datum)
{
//var dayReps = db.getAllDayReps(new DateTime(2014,05,13)).AsQueryable();
var dayReps = db.getAllDayReps(datum).AsQueryable();
return dayReps;
}
When I'm testing the commented static value, then it works fine and I'm getting the data from date 2014-05-13. But with the dynamic value I don't get data from the database.
Angular Ctrl:
//Button Send
$scope.sending = function (sel) {
$scope.selected = new Date(sel);
$scope.repDay = ResourceService.ds021.query({
'datum': $scope.selected
});
};
Service for REST:
return {
ds021: $resource(baseUrl + '/api/qr_ds021/:Id', {
Id: '#Id'
}, {})
};
View:
<div>
<input type="date" ng-model="selected" />
<button type="button" ng-click="sending(selected)">Send</button>
</div>
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>F_1 </th>
<th>F_2 </th>
<th>F_3 </th>
<th>F_4 </th>
<th>F_5 </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="rep in repDay>
<td>{{ rep.datum }}</td>
<td>{{ rep.isin }}</td>
<td>{{ rep.NameId }}</td>
<td>{{ rep.time_quot }}</td>
<td>{{ rep.num_quot }}</td>
</tr>
</tbody>
....
How you can see I'm typing an value in the input field. The ngModel value will sending with the button "send" to the service. But something is wrong in the service and I don't know what..
EDIT:
Here is the method from the Context.tt:
public virtual ObjectResult<getAllDayReps_Result> getAllDayReps(Nullable<System.DateTime> datumOut)
{
var datumOutParameter = datumOut.HasValue ?
new ObjectParameter("DatumOut", datumOut) :
new ObjectParameter("DatumOut", typeof(System.DateTime));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<getAllDayReps_Result>("getAllDayReps", datumOutParameter);
}

Categories