order by two columns in angular js (average, time seconds) - angularjs

I'm trying to sort two columns with angular js, column average and another time in seconds, but the seconds not sorted correctly.
I currently returns this:
I'm doing something as a ranking.
my html:
<tr ng-repeat="user in ranking | orderBy:['-promedio','tiempo']" >
<td >{{ user.usuario }}</td>
<td > {{ user.promedio }} </td>
<td > {{ user.tiempo}} </td>
</tr>
my ctrl:
EncuestApp.controller('ResultadoCtrl', function ($scope) {
$scope.ranking =[
{
"id":"5",
"tiempo":"15.737",
"promedio":"0.4",
"usuario":"rfmartinez"
},
{
"id":"6",
"tiempo":"35.694",
"promedio":"0.8",
"usuario":"mm"
},
{
"id":"7",
"tiempo":"303.328",
"promedio":"0.8",
"usuario":"mn"
},
{
"id":"8",
"tiempo":"40.327",
"promedio":"0.8",
"usuario":"mnn"
}
];
});
which is the best way to solve it?
thanks

You have stored all numbers as strings (e.g. "10.5" instead of just 10.5). Therefore AngularJS sorts your entries by the textual representation of the numbers. Change all numbers to actual numbers in your data model:
EncuestApp.controller('ResultadoCtrl', function ($scope) {
$scope.ranking =[
{
"id": 5,
"tiempo": 15.737,
"promedio": 0.4,
"usuario": "rfmartinez"
},
{
"id": 6,
"tiempo": 35.694,
"promedio": 0.8,
"usuario": "mm"
},
{
"id": 7,
"tiempo": 303.328,
"promedio": 0.8,
"usuario": "mn"
},
{
"id": 8,
"tiempo": 40.327,
"promedio": 0.8,
"usuario": "mnn"
}
];
});

Related

angular: Translate elements of an object array in a template with ngx-translate

I have been searching for hours how I can translate the values of an object array with the module ngx-translate,
Here is an extract of my code but I don’t know how to implement the json file
Template HTML :
<div class="sort-header-container">
<table matSort class="mat-sort">
<tr *ngFor="let item of items" class="row">
<td class="row">{{item.critere}}</td>
<td>{{item.res}}</td>
</tr>
</table>
</div>
The object array in the service :
items: any[] = [
{ critere: "Code-modèle", res: "Mizuno Shadow 4" },
{ critere: "Code Libellé", res: "KR32" },
{ critere: "Stock", res: 10 },
{ critere: "Prix TTC", res: "Bleu" },
{ critere: "Couleur", res: 42 },
{ critere: "Matière", res: 125 },
{ critere: "Zone", res: 100 },
];
I need to translate only the critere column
Thank you
You need to use the TranslatePipe from ngx-translate.
<div class="sort-header-container">
<table matSort class="mat-sort">
<tr *ngFor="let item of items" class="row">
<td class="row">{{item.critere | translate}}</td>
<td>{{item.res}}</td>
</tr>
</table>
</div>
Make sure your critere field have the corresponding translations in the json translation files
example for en english translation:
{
"Prix TTC": "Price",
"Couleur": "Color",
}
As taken from the example in ngx-translate github
You can use the translate pipe in your code, like this:
<td class="row">{{ item.critere | translate }}</td>
For this to work, your critere would need to be keys in your language file, for example:
{
'Stock': 'Stock english translation',
'Couleur': 'Is this color?'
}
Thank you very much for your answers
Finally here's what I did :
<tr *ngFor="let item_translate of ('PRODUCT.PRODUCT' | translate); let i = index " class="row"
[ngStyle]="item_translate.critere == 'Stock' && stock<0 ?{color:'red'}:{color:'#474646'}">
<td class="row">{{item_translate.critere}}</td>
<td>{{items[i].res}}</td>
</tr>
In my json example fr :
"PRODUCT": {
"PRODUCT": [
{
"critere": "Code-modèle"
},
{
"critere": "Code Libellé"
},
{
"critere": "Stock"
},
{
"critere": "Prix TTC"
},
{
"critere": "Couleur"
},
{
"critere": "Matière"
},
{
"critere": "Zone"
}
]
}

Get data id in array object vuejs

how to display value data based on index array. here I make a modal edit data, I have a json like the following
[
{
"ID": 3,
"idusers": 3,
"skills": "Go",
"profiency": "Expert",
},
{
"ID": 48,
"skills": "laravel",
"profiency": "laravel",
},
{
"ID": 47,
"skills": "Vue",
"profiency": "Expert",
}
]
table data that I display
<tr v-for="(skill, index) in getSkills" :key="skill.ID">
<td>{{ index + 1 }}</td>
<td>{{ skill.skills }}</td>
<td>{{ skill.profiency }}</td>
<td class="text-xs-center">
<td><div v-if="editBtn == true">
<v-btn class="mr-3" x-small fab v-on:click="handleEdit(item,index)" color="primary"><v-icon>mdi-cancel</v-icon></v-btn>
</td>
</tr>
and this my modal edit
<v-dialog v-model="skillForm" width="500">
<v-container>
<v-text-field outlined dense>
{{profiency}}
</v-text-field>
</v-container>
</v-dialog>
my method
export default {
name: "Skills",
data: function() {
return {
formAddSkills: "",
skillForm: false,
editBtn: "",
skills: {
skills: "",
profiency: "",
},
};
},
computed: {
...mapState({ getSkills: (state) => state.resume.Skills }),
dataSkills() {
return this.skills;
},
},
methods: {
handleEdit(item, index) {
this.skillForm = true;
this.editBtn = true;
this.profiency = item.profiency
// console.log(item)
console.log(index)
},
}
}
the question is how to display data based on ID, when I click the edit button it appears and enters the text field form
Pass skill from your method as a parameter
#click="handleEdit(skill,index)
Then declare a variable, currentObject, and then equate it this.currentObject = skill inside the method.
Then you can access currentObject.id via the v-model binded to your text field.

sorting not working properly angular 4

I have various tables and I'm trying to sort table using https://www.npmjs.com/package/ngx-order-pipe. I followed their documentation and everything works fine except it is not sorting correctly the columns (here in the example, 'Rank' column)
For example I have a response like this:
"collection": [
{
"name": "John",
"age" : "25",
"details": [
{
"final_rank": "150"
}
]
}
{
"name": "Mark",
"age" : "19",
"details": [
{
"final_rank": "254"
}
]
}
Here's my HTML:
<table>
<thead>
<tr>
<th (click)="setOrder('name')">Name</th>
<th (click)="setOrder('age')">Age</th>
<th (click)="setOrder('final_rank')">Rank</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let Data of collection | orderBy: order:reverse:'case-insensitive'">
<td class="text-truncate">{{Data.name}}</td>
<td class="text-truncate">{{Data.age}}</td>
<td class="text-truncate" *ngIf="!isArray(Data.details)">
<tr> {{Data.details.final_rank}} </tr>
</td>
<td class="text-truncate" *ngIf="isArray(Data.details)"><tr *ngFor="let rankData of Data.details"> {{rankData.final_rank}} </tr></td>
</tr>
</tbody>
</table>
component.ts
order;
reverse = false;
isArray(obj: any) {
return Array.isArray(obj)
}
getData() {
this.http.get('**')
.subscribe(data => {
console.log(data);
});
}
setOrder(value) {
if (this.order === value) {
this.reverse = !this.reverse;
}
this.order = value;
console.log(this.order);
}
Your problem seems to be that you try to sort by a field that is inside of an array of the actual object. I suspect that your library doesn't know how to do the sorting (and that probably rightly so). So what you should do is to transform your data in a format, where it can be sorted.
At some point in your application you have the data:
const originalData = [{
'name': 'John',
'age': '25',
'details': [
{
'final_rank': '150'
}
]
},
{
'name': 'Mark',
'age': '19',
'details': [
{
'final_rank': '254'
}
]
}];
Whata you want to do now is to take that data and to convert it to something else. In this example I want to get the max final_rank value of any of the details items. That max value will be used for sorting. You might want to use another way of defining what value to use, but for this example the max value should do fine.
We can use a map function to transform each value of your original data:
const mappedData = originalData.map(item => ({
// This will do a shallow copy of all the fields of the original object
...item,
// With reduce we can easily find the max ```final_rank``` value
maxRank: item.details.reduce(
// +current.final_rank converts the string to a number
(max, current) => +current.final_rank > max ? current.final_rank : max,
0
)
}));
This should yield a new array which should look the same as your original data, except for an additional maxRank field on the root object.
The resulting object would look something like this:
const mappedData = [{
'name': 'John',
'age': '25',
'maxRank': 150,
'details': [
{
'final_rank': '150'
}
]
},
{
'name': 'Mark',
'age': '19',
'maxRank': 254,
'details': [
{
'final_rank': '254'
}
]
}];
Now you should be able to do sorting based on the maxRank field.

Angular access in controller to ng-model in nested ng-repeat

I have problem as in the topic. Using $parent in ng-model didn't help.
What I am trying to achieve is 2 clickable buttons to increase and decrease quantity field value by one and display summary (sum of each price*quantity) on the bottom of site.
var app = angular.module("mainApp", []);
app.controller("mainCtrl", function ($scope) {
$scope.list1 = [
{ "uniqueId": "1", "name": "cat1" },
{ "uniqueId": "2", "name": "cat2" }
];
$scope.list2 = [
{ "uniqueId": "1", "name": "prod1", "price": "10" },
{ "uniqueId": "2", "name": "prod2", "price": "20" },
{ "uniqueId": "3", "name": "prod3", "price": "30" }
];
// this one below doesn't work at all
// $scope.quantity[1] = 1;
$scope.inc = inc;
function inc(id) {
console.log(id); //works fine
// increase of exact quantity
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="mainApp">
<div ng-controller="mainCtrl">
<table ng-repeat="l1 in list1">
<tr>
<td>
{{l1.name}}
</td>
</tr>
<tr ng-repeat="l2 in list2">
<td>name: {{l2.name}},</td>
<td>price: {{l2.price}},</td>
<td>quantity wanted: <input ng-model="quantity[l2.uniqueId]"><button ng-click="inc(l2.uniqueId)" type="button">+</button></td>
</tr>
</table>
{{quantity}}<!-- sum of all quantities * prices -->
</div>
<div>
Keep in mind that there is mulitple way to solve this kind of problem, here is the grand line I see to do it and an example for each step:
Store your quantity somewhere and initialise it, for example in your product object, example in your controller:
{ "uniqueId": "1", "name": "prod1", "price": "10", quantity : 1 },
Create a function to increase and an other to decrease the quantity of a product by his id, example in your controller:
function increaseQuantity(id){
// Get your product in the list with a loop
// If the product exists
// Increase his quantity
}
function decreaseQuantity(id){
// Get your product in the list with a loop
// If the product exists
// Decrease his quantity
}
$scope.increaseQuantity = increaseQuantity;
$scope.decreaseQuantity = decreaseQuantity;
Call the right methods in your buttons, example in your view:
<td>
quantity wanted: {{l2.quantity}}
<button ng-click="increaseQuantity(l2.uniqueId)" type="button">+</button>
<button ng-click="decreaseQuantity(l2.uniqueId)" type="button">-</button>
</td>

Draw a matrix array based in AngularJS

I need to draw a table in AngularJS based on the following array
$scope.list = [
{ "Row":1, "Column": 1, "Value": "11" },
{ "Row":1, "Column": 2, "Value": "12" },
{ "Row":1, "Column": 3, "Value": "13" },
{ "Row":2, "Column": 1, "Value": "21" },
{ "Row":2, "Column": 2, "Value": "22" },
{ "Row":2, "Column": 3, "Value": "23" },
];
So I need to get a table with 2 rows and 3 columns
I understand that I have to use two nested ngRepeat but I couldn't make it work
Please could you help me ??
Regards
I developed the solution I found a filter 'Unique' here
For each unique row number I get the list of columns
<table border="2">
<tr ng-repeat="row in list | unique:'Row'">
<td>Row: {{row.Row}}</td>
<td ng-repeat="col in list | filter:{'Row':row.Row}">{{col.Value}}</td>
</tr>
</table>
You should first transform your array to such one:
$scope.table = [
["11", "12", "13"],
["21", "22", "23"],
];
That way, it will be easier to iterate over the values in your view:
<table>
<tr ng-repeat="row in table">
<td ng-repeat="column in row">
{{column}}
</td>
</tr>
</table>

Resources