Smart table: conditional st-sort attribute in ng-repeat - angularjs

I am using Angular Smart Table and it is pretty good, but i faced with problem related to sorting:
let's assume that i have some columns definition and for each column i have information whether i can sort by this column or not:
$scope.columns = [
{
id: "id",
sortable: true
},
{
id: "type",
sortable: false,
}
];
In my html file i want to declare table headers with ng-repeat to avoid stupid refactoring when something in columns definition is changed. Somethig like that:
<table class="table" st-table="records">
<thead>
<tr>
<th ng-repeat="column in columns"> {{ column.title }} </th>
</tr>
</thead>
....
</table>
So my question is: how can i set attribute "st-sort" only for those columns, for which column.sortable is true?
I tried to use custom directive that adds this attribute depending on column.sortable and it actually adds it, but st-sort not works in this case (may be because this directive compilation is happening after table compilation, i have no idea...)

This should work:
<table st-table="records">
<thead>
<tr>
<th ng-repeat="column in columns" st-sort="{{(column.sortable) ? column.id : null}}">
{{column.id}}
</th>
</tr>
</thead>
...
</table>

Related

ng repeat dynamic with key objet json AngularJS

I have a small problem I would like to set up a ng-repeat dynamic with the values I receive from my JSON object,
First, i made my th from my table with the keys
Secondly, i would like to do my td in dynamic (without putting the name of the key ex: obj.NOM, obj.TYPE ...)
I managed to do something with an Object.keys but logic is not good so I need some help
this is my JSON object ( i show you just the little piece of code that I have a problem )
"HEADER":[
{"NOM":"API-APP","TYPE":"string","DESCRIPTION":"Code application"},
{"NOM":"API-SIGNATURE","TYPE":"string","DESCRIPTION":"Signature de la requete API"},
{"NOM":"API-TIMESTAMP","TYPE":"integer","DESCRIPTION":"Timestamp en microseconde"}]
and this is my ng repeat
<span><b>HEADER</b></span>
<br>
<br>
<table class="table">
<th ng-repeat ="(key, itemHeader) in itemHead.HEADER[0] track by $index">{{key}}</th>
<tr ng-repeat ="(key, itemHeader) in itemHead.HEADER track by $index" >
<td>{{getFirstPropertyValue(itemHeader,$index)}}</td>
</tr>
</table>
I explain i made first a ng-repeat for th with the keys and I would like put my data (3 data per row) in td without put ( .NOM .TYPE .DESCRIPTION)
So I took the function object.key which works very well but that makes me just one element per row but I need 3 elements per row
this is my scope for the function object.key
$scope.getFirstPropertyValue = function(obj,index){
return obj[Object.keys(obj)[index]];
}
and this my result
thanks in advance for your help
<table class="table">
<thead>
<tr>
<th ng-repeat="(key, itemHeader) in itemHead.HEADER[0]">
{{key}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in itemHead.HEADER">
<td ng-repeat="column in row">
{{column}}
</td>
</tr>
</tbody>
</table>

AngularJS: Table with ng-repeat on table row / column

I need to create a table from an array of objects but I don't want to hardcode the table. I can't do this or this for example. I rather need nested ng-repeats like this. But my case is a little bit different because I have columns which contain two values in an array. The data looks like this:
[
{
"foo":"bar",...,
"key1":[
"value1",
"value2"
],
"key2":[
"value1",
"value2"
],...,
"more_foo":"more_bar"
},...
]
I want the values (which are always strings) of all objects (which have always an equal structure) from the array in the table rows where each key should be the column name. Like this:
table,
th,
td {
border: 1px solid black;
text-align: center;
border-spacing: 0;
}
td,
th {
padding: 0.5em;
}
<table>
<thead>
<tr>
<th>foo</th>
<th colspan="2">key1</th>
<th colspan="2">key2</th>
<th>more_foo</th>
</tr>
</thead>
<tbody>
<tr>
<td>bar</td>
<td>value1</td>
<td>value2</td>
<td>value1</td>
<td>value2</td>
<td>more_bar</td>
</tr>
</tbody>
</table>
Here is what I have come up with:
<table>
<thead>
<tr>
<th ng-repeat="(propName, prop) in myArray[0]"
colspan="{{isUpdateable(propName) ? 2 : undefined}}"> {{propName}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="object in myArray | filter: searchFilter">
<td ng-repeat="(propName, prop) in object" double-col>{{prop}}</td>
</tr>
</tbody>
</table>
isUpdatable(propName) will return true if this value is an array and false if it is not. This will make it possible to have two tds in this column.
The double-col directive:
app.directive('double-col', function () {
return {
transclude: true,
template: "<td>{{prop[0]}}</td><td class=\"changedProp\">{{prop[1]}}</td>"
};
});
I want this directive to replace the existing td with two tds if and only if prop is an array and otherwise do nothing to display prop (see td above).
Because you are on https://stackoverflow.com (the place where people post things that dont't work well yet), you can probably guess that my current code doesn't not work really well. I am also new to angularJS and have basically no understanding of custom directives (and probably most other stuff too) so it would be nice if someone could help me with this problem and provide an explanation as well.
What about
<tr ng-repeat="object in myArray | filter: searchFilter">
<td ng-repeat="(propName, prop) in object" colspan="{{isArray(prop) ? prop.length : 1}}">
<span ng-if="!isArray(prop)"> {{prop}}</span>
<table ng-if="isArray(prop)"><tr>
<td ng-repeat="prop1 in prop">
{{prop1}}
</td>
</tr></table>
</td>
</tr>
$scope.isArray=function(prop){
return Array.isArray(prop);
}
Here is working fiddle

Angularjs smart-table not sorting $index table cells

I have a problem withe the Smart Table AngularJS Sorting, I implemented this on my table as:
The initialized app:
angular.module('myproyApp', ['smart-table'])
The controller side:
$scope.dataList = []; //any json collection with: id, name and description
The view side with st-table directive:
<table class="table table-bordered table-striped" st-table="dataRows" st-safe-src="dataList">
<thead>
<tr>
<th><span class="glyphicon"></span>Q</th>
<th st-sort="name">Name</th>
<th st-sort="descripcion">Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in dataRows">
<td class="col-md-1">{{$index + 1}}</td>
<td class="col-md-4">{{row.name}}</td>
<td class="col-md-4">{{row.description}}</td>
<td>Change</td>
</tr>
</tbody>
</table>
On click the sorting header's cells the table is sorting, but the sorting isn't working for the $index cells. Please if you have any think to include the $index cells to sort. I want not to use the indexes on dataList $scope values, I need that this index will be include only on table view.
Track by is used to link your data with the DOM generation made by ng-repeat. When you add track by you tell angular to generate a single DOM element per data object in the given collection. Because $index has to do with the DOM there is no way to have it relate to a particular data entry. Here's a more detailed explanation.
If you really want to do it without touching your dataList, you could call indexOf in your table:
<tbody>
<tr ng-repeat="row in dataList | orderBy:sortField">
<td class="col-md-1">{{dataRows.indexOf(row)}}</td>
<td class="col-md-4">{{row.name}}</td>
<td class="col-md-4">{{row.description}}</td>
<td>Change</td>
</tr>
</tbody>
Where there is a scoped variable called sortField which is a string that is the name of the field you wish to sort by. I implemented a similar thing in this plunker, using the smart-tables module. http://plnkr.co/edit/AF90dQ
I would advise against this because it quickly becomes expensive for large arrays, and runs into problems if your entries aren't unique.

smart-table : Conditional st-sort

Is there any way to have conditional st-sort in smart-table. Example - I have an array which tells me the columns in my table which are sortable. Lets say my table has columns [FirstName, LastName, Age, email] and my sorters array is [firstName, age], which means only firstname and age fields are sortabe. How can I achieve this using smart-talbe. Any help is much appreciated! Thanks!!
The way smart table wants you to specify if a column is sortable or not is by using the st-sort directive in your <thead>, it tells which column should be sortable by what object property, like so:
<thead>
<tr>
<th st-sort="firstName">first name</th> <!-- sortable rows -->
<th st-sort="lastName">last name</th>
<th st-sort="age">age</th>
<th>email</th> <!-- not sortable -->
</tr>
</thead>
what you're saying is that you have an array that tells your table which column is sortable and which is not.
In my opinion is a very awkward way to do things in general and it can't really be done neatly in ST.
You can however write a directive that conditionally adds or removes st-sort from your table using values from an array. but that will just be a mess
I agree it is an awkward way to do but that's how the services are returning data to us. I tried the following code and got it working(It sorts the firstname and age columns. ), although it doesn't seem a very clean approach to me -
In my HTML -
<thead>
<tr>
<th st-ratio="20" ng-attr-st-sort="sorters.getSorter('firstName')">first name</th> <!-- sortable rows -->
<th st-ratio="20" ng-attr-st-sort="sorters.getSorter('lastName')">last name</th>
<th st-ratio="10" ng-attr-st-sort="sorters.getSorter('age')">age</th>
<th st-ratio="30" ng-attr-st-sort="sorters.getSorter('email')">email</th>
<th st-ratio="20" ng-attr-st-sort="sorters.getSorter('balance')">balance</th>
</tr>
</thead>
enter code here
In my js -
$scope.sorters = {
getSorter: function(prop){
return function(value){
var sortables = ['firstName', 'age'];
for(var i=0;i<sortables.length; i++){
if(sortables[i] === prop) {
return value[prop];
};
}
return undefined;
}
}
};
Although this solves my problem, I dont like the approach. Is there any better option to this?
P.S - I will eventually be converting this to a directive if I have no better option.

ng-repeat for an json object which has arrays

I have a JSON object which is data for a chart. This has 2 properties labels and data. Both are arrays. Along with the chart I wish to display a table as well. I am not able to figure out how to use the ng-repeat directive here.
JSON Object
$scope.chartdata={
labels: ["XYZ", "ABC","DEF"],
data: [4286, 38870, 3955]
};
HTML
<table class="table table-striped">
<thead>
<tr>
<th>Labels</th>
<th>Data </th>
</tr>
</thead>
<tr ng-repeat="cht in chartdata">
<td>{{cht.labels}}</td>
<td>{{cht.data}}</td>
</tr>
</table>
Do I need to change the JSON structure? I do not wish to cos it works for my chart directive and I want to resues the same JSON for displaying the table as well.
You need to use $index, because these are 2 separate properties within the chartdata object
<table class="table table-striped">
<thead>
<tr>
<th>Labels</th>
<th>Data </th>
</tr>
</thead>
<tr ng-repeat="label in chartdata.labels">
<td>{{label}}</td>
<td>{{chartdata.data[$index]}}</td>
</tr>
</table>
That said the object structure you have can probably be revised to be more like the model (unless you are using the object structure for something else that expects it in that format)
$scope.chartdata = [
{
label: "XYZ",
data: 4286
},
...
];
In the latter case too, you could use the above structure and set up a method that transforms the object into the dual array structure that you need for the something else.

Resources