Angularjs Display single element from json - json

I have a json file which contains different prices for a service, depending on the day of the week (in the weekend it's more expensive)
I use angular to show these prices using a lines like this:
<div ng-repeat="arr in arrangementen | filter:'_1'" >Mon-Fri: € {{arr.prijs_ma_vr | number :2 }} </div>
<div ng-repeat="arr in arrangementen | filter:'_1'" >Sat: € {{arr.prijs_za | number :2 }} </div>
json:
{
"id": "_1",
"arrangement": "Vriendinnendag",
"prijs_ma_vr": 99.95,
"prijs_za": 103.95,
"prijs_zo": 104.95,
},
{
"id": "_2",
"arrangement": "Vipdag",
"prijs_ma_vr": 199.95,
"prijs_za": 205.95,
"prijs_zo": 209.95,
}
I wonder if there is more smart and easier way to display these prices or other elements from this json. Sometimes I just want to display one element (i.e. one price)
(Example in this site: wellness example

I would rework the json and do it this way:
{
"id": "_1",
"arrangement": "Vriendinnendag",
"prijs":[ 99.95, 103.95, 104.95 ],
“day”:['Mon-Fri','Sat','Sun']
},
{
"id": "_2",
"arrangement": "Vipdag",
"prijs":[ 199.95, 203.95, 204.95 ],
“day”:['Mon-Fri','Sat','Sun']
}
<div ng-repeat="arr in arrangementen | filter:'_1'" >
day[0] € {{arr.prijs[0] | number :2 }}<br>
day[1] € {{arr.prijs[1] | number :2 }}<br>
day[2] € {{arr.prijs[2] | number :2 }}
</div>

I see you already accepted the other answer, but I wanted to give you another option, which is to create your own filter.
angular.module('demo',[])
.controller('MainCtrl', ['$scope', function($scope){
$scope.arr = [{ "id": "_1",
"arrangement": "Vriendinnendag",
"prijs_ma_vr": 99.95,
"prijs_za": 103.95,
"prijs_zo": 104.95, },
{ "id": "_2",
"arrangement": "Vipdag",
"prijs_ma_vr": 199.95,
"prijs_za": 205.95,
"prijs_zo": 209.95, }];
}])
.filter('weekdayPrice', function(){
return function(obj, id) {
var rtnval;
angular.forEach(obj, function(value){
if (value.id === id) {
return rtnval = value.prijs_ma_vr;
};
});
return rtnval;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo" ng-controller="MainCtrl">
<div>Weekday Price: {{arr | weekdayPrice: '_2' | number: 2 | currency: '€'}}</div>
</div>
So this custom filter takes an id and returns just the weekday price from the object whose id matches the id you passed into the filter. You can use it just like any other filter so you can chain them together just like the built in filters, allowing you to add additional filters such as currency or number to the value that is returned by the custom weekday filter.
The benefits are that you can reuse your custom filters throughout your application; you don't have to change your current json format; and more importantly, you don't have to figure out the array index of the item which is definitely prone to errors.

Related

Angular 8 make football match using JSON

i want to create football matches using this JSON:
export const teams: Array<any> = [
{
name: 'A',
teams: [
{
name: 'France',
},
{
name: 'Portugual',
},
{
name: 'india',
},
{
name: 'china',
}
]
},
]
so for example i want to make matches france vs india than france vs china .
so i am using Angular 8 , and i have some issues if anyone can help me in that code .
HTML:
<div class="col-3" *ngFor="let group of group1">
<h5>{{ group }}</h5>
</div>
TypeScript:
this.group1 = this.teams;
this.teams.forEach((item, index) => {
this.groupList.push(item.name);
item.teams.forEach((item, index) => {
this.group1.push(item.name);
});
});
What I believe you want to do is display a list of all possible matches within this JSON, and I assume that since the teams array is in it's own array of objects with a name tag, that there may be separate groups of matches that you wish to display.
I have created a Stackblitz project you can view here to see my implementation of what I believe it is you are looking for.
I will explain my code below.
HTML:
<div class="col-3" *ngFor="let group of groupList">
<h5>{{ group }}</h5>
</div>
I wasn't sure what the difference between 'group1' and 'groupList' were supposed to be in your code, so I have selected groupList as my display value, and use 'group1' as a property in the TS.
TS:
for (let teamGroup of this.group1) {
this.groupList.push("Group: " + teamGroup.name); // show the group
for (let team1 of teamGroup.teams) {
for (let team2 of teamGroup.teams) {
// iterate over every possibility of two teams facing each other
if (
this.groupList.indexOf(
String(team1.name + " vs. " + team2.name)
) === -1 &&
this.groupList.indexOf(
String(team2.name + " vs. " + team1.name)
) === -1
) {
// filter out matchups already pushed to the array
if (team1.name !== team2.name) {
// filter out self-matches
this.groupList.push(team1.name + " vs. " + team2.name);
}
}
}
}
}
In the Stackblitz implementation, I'm using 'teams' as a property of my component, assigned to the JSON you provided, but you can get this JSON dynamically and use this code, just make sure to assign the value to the 'group1' property.
The 'groupList' property is an empty array, which we will .push() the values we wish to display to. By looping over the 'teams' array within the first (and only) entry in your JSON, we can decide on a display format for the string (I have chosen 'Team1 vs. Team2') and compare all possible matchups between two teams within the group against entries in 'groupList'. If the matchup does not exist, we will push the matchup to 'groupList'.
The end result is this:
Results
I hope this was what you were looking for. I would have asked a clarifying question in the comments first, but I'm too new to the website to be able to.

AngularJS Search by display value instead of received data/json value?

I am following the tutorial Codepen example here to do Angularjs search on table:
https://codepen.io/sevilayha/pen/AmFLE
Let's say the tastiness numbers that I am receiving from server are like 255, 65551, 32322 , where the last two digits are supposed to be decimals.
So in order to display them in comprehensive way for user, i did on html:
{{ roll.tastiness/100 | number : 2}}
in the table:
<tr ng-repeat="roll in sushi | orderBy:sortType:sortReverse | filter:searchFish">
<td>{{ roll.name }}</td>
<td>{{ roll.fish }}</td>
<td>{{ roll.tastiness/100 | number : 2}}</td>
Note that I didn't modify the code in codepen because it's not mine, but you can try the modifications there.
and I changed the data value in controller (again, without saving the codepen) to this:
$scope.sushi = [
{ name: 'Cali Roll', fish: 'Crab', tastiness: 255 },
{ name: 'Philly', fish: 'Tuna', tastiness: 466 },
{ name: 'Tiger', fish: 'Eel', tastiness: 7 },
{ name: 'Rainbow', fish: 'Variety', tastiness: 6 }
];
The issue is, that even though the numbers are being displayed like 2.55 and 4.66, in the search i have to put 255 instead of 2.55 in order to find the record.
What should I do in order to make the search detects the values as how they're displayed on page instead of the values as presented in $scope.sushi array of objects?
That is because the filter is filtering on the actual values and the pipe is transforming those values for display only. The values the filter is working on stayed the same, without the decimal places.
You can modify the search filter or modify the values. It depends do you need to keep the same values for some other purposes. If not I would go for modifying the values and removing the pipe.
Lowest level vanilla here compatibile with all JS versions is simple for loop:
for (var i=0; i<sushi.length; i++){
sushi[i].tastiness = sushi[i].tastiness/100;
}
Execute BEFORE displaying. And remove pipe when displaying.
<td>{{ roll.tastiness/100 | number : 2}}</td>
Angular JS with use of PIpe only modifies UI display value but your JSON value is still 255 only that is why it is not searching with 2.55
I think while filter just provide same PIPE logic values so that i t can did search properly

SAPUI5 TreeTable - flat OData

i have an issue or lack of idea how to build TreeTable from flat OData data. The data looks like this (columns):
Document Number,
Year,
Month,
Status,
several more columns
The hierarchy should like like this:
DOCUMENT
`- YEAR
`- Month
`- STATUS 1
- data for status 1 #1
- data for status 1 #2
`- STATUS 2
- data for status 2 #1
- data for status 2 #2
ODATA returns:
DOCUMENT | YEAR | MONTH | STATUS1 | Data for status 1 #1
DOCUMENT | YEAR | MONTH | STATUS1 | Data for status 1 #1
DOCUMENT | YEAR | MONTH | STATUS2 | Data for status 2 #1
DOCUMENT | YEAR | MONTH | STATUS2 | Data for status 2 #2
The question would be - is there any callback function/whatever i could use in order to reorganize the data for example by putting it in JSON format ? Or any other Idea ?
I have a CDS View and generated OData behind, so need to do this in UI5.
Any help would be highly appreciated !
Cheers
Kubas
If as you said there should be an edit possibility for the table, you can use a stanard TreeTable OData binding, but the backend must provide you the hierarchical data (it will cost nothing to implement the editability due to standard two-way binding), in your case the OData structure will look like this:
[
{
ID: "",
NodeID: 1,
type: "document",
title: "",
HierarchyLevel: 1,
ParentNodeID: null
},
{
ID: "",
NodeID: 2,
type: "year",
title: "",
HierarchyLevel: 2,
ParentNodeID: 1
},
{
ID: "",
NodeID: 3,
type: "month",
title: "",
HierarchyLevel: 3,
ParentNodeID: 2
},
{
ID: "",
NodeID: 4,
type: "status",
title: "",
HierarchyLevel: 4,
ParentNodeID: 3
},
{
ID: "",
NodeID: 5,
type: "data for status",
data: {},
title: "",
HierarchyLevel: 5,
ParentNodeID: 4
}
]
If there is no chance for the backend to provide such structure, you can parse your backend response and construct JSON model (the parsing will be just for a grouping reasons, you need to group your flat structure into the hierarchical considering the keys: document ids, years, months, statuses..).
JSON data structure:
[
{
DocumentId: "",
items: [
{
year: "",
items: [
{
month: "",
items: [
{
status: ""
}
]
}
]
}
]
}
]
But this JSON-approach makes harder to track the changes to be send to the backend side. So the task is to find the nodes that were changed by the user and here you can think about making the diff between original parsed data and the data in a state after the changes applied by the user. Or you can keep a kind of a map of the changes user made to the document id's and turn this data into the odata calls once user wants to submit the changes.
UPD 1:
Implementation of "lazy loading" for the tree structure that is defined by the flat one (via backend) will be problematic. Because to my understanding, the lazy loading for the tree will look like the following:
initially UI loads all the items from the 1-st level. Then after clicking on the "expand" button of th 1st level, UI makes a call to fetch the 2nd level and so on.
The lazy loading for the "flat" list works differently, while user scrolling the table down and reaches the very bottom side (based on the "threshold" property), table can request more data via new $skip & $top properties in OData call.
So I'm afraid that it won't be possible to make the lazy loading without property tree structure from backend.
Possible workaround might be providing a kind of a filter to reduce amount of items.
As to your question about "where to put this parsing" - you need to perform the "read" request manually in the controller, then in "success" method call the parsing, then construct JSONModel based on parsed data and finally bind the table to this model.

Angular 2 - Interpolation for NGX-Charts Results within ngFor

I'm trying to show charts based on some json. I made a pipe to access the various parts of the json object but don't know how to use the data, which looks like this:
[ { "name": "Completed", "value": 50 }, { "name": "Remaining", "value": 50 } ]
within the ngFor.
So normally I would do something like this:
<ngx-charts-advanced-pie-chart
mdTooltip="Click to change unit"
[tooltipDisabled] = "true"
[scheme]="colorScheme"
[results]="results" <----this is where the results normally go
[gradient]="gradient"
[view]="view"
(select)="onChartClick()"
>
</ngx-charts-advanced-pie-chart>
And I want to try something like this:
<div *ngFor="let chair of targetChairs | chairDimensions">
<ngx-charts-advanced-pie-chart
mdTooltip="Click to change unit"
[tooltipDisabled] = "true"
[scheme]="colorScheme"
[results]="{{ chair.value.data.height | json }}"
[gradient]="gradient"
[view]="view"
(select)="onChartClick()"
>
</ngx-charts-advanced-pie-chart>
</div>
This doesn't work but is there a way to achieve this?
So I found a similar issue on a git page here which solved my problem, so here is what I used in case someone else has this problem:
<div *ngFor="let chair of targetChairs | chairDimensions">
<ngx-charts-advanced-pie-chart
mdTooltip="Click to change unit"
[tooltipDisabled] = "true"
[scheme]="colorScheme"
[results]="chair.value.data.feet"
[gradient]="gradient"
[view]="view"
(select)="onChartClick()"
>
</ngx-charts-advanced-pie-chart>
</div>

Is there a way to count the number of keys in a json object directly in angular expressions?

I need to show the number of keys in a json object on a web page. So, is there a way to calculate the count directly in the angular expression?
For example,
JSON:
$scope.json = {"key1": "value1", "key2": "value2", key3: "value3"}
For this 'json', there are three keys. I want to get the count of keys directly in an angular expression without calculating it in the controller.
You would have to use a custom filter like this:
template:
{{json | numKeys}}
filter:
app.filter('numKeys', function() {
return function(json) {
var keys = Object.keys(json)
return keys.length;
}
})
Some hacky way would be to do the following:
howManyKeys = {
a: 'Do',
b: 'I',
c: 'have?',
}
If you only want to use it a few times:
This object has {{ (howManyKeys | keyValue).length }} keys
<span *ngIf="(howManyKeys | keyValue).length > 2">That's more than 2!</span>
If you only want to show it on many spots:
<span *ngFor="let howManyKeysLength of [(howManyKeys | keyValue).length]">
This object has {{howManyKeysLength}} keys.
<span *ngIf="howManyKeysLength > 2">That's more than 2!</span>
<span *ngIf="howManyKeysLength < 5">Less than 5!</span>
</span>
This can be useful when you don't want to add a service.