Angular orderBy object possible? - json

I have a JSON object representing calendar dates. These are added through a CMS and I'd like to be able to filter them based on date. My schema set-up has made this more difficult than I thought. Is it possible to orderBy the day value in this JSON object or is there a filter workaround?
Here is my JSON object:
{
"_id" : ObjectId("53f252537d343a9ad862866c"),
"year" : {
"December" : [],
"November" : [],
"October" : [],
"September" : [],
"August" : [],
"July" : [
{
"day" : "21",
"title" : "Event Title",
"summary" : "Event Summary",
"description" : "oEvent Description",
"_id" : ObjectId("53f252537d343a9ad862866d")
}
],
"June" : [],
"May" : [],
"April" : [],
"March" : [],
"February" : [],
"January" : []
},
"__v" : 0
}
Here is my view which already uses a custom filter to filter by month. The orderBy is not functioning but I've left it in as a placeholder to show where I'd like to set the functionality.
<div class="calDynamic" data-ng-repeat="n in [] | range:100">
<div ng-repeat="cal in calendar[n].year | filterKey:month">
<div ng-if="cal != '' ">
<div class="calendar">
<div ng-repeat="item in cal | orderBy: 'key.day' ">
<a href="/events/{{item.day}}">
<article class="eventslist">
<div class="numberedDate">
<h3>{{item.day}}</h3>
</div>
<div class="calInfo">
<h5>{{item.title}}</h5>
<p>{{item.summary}} <a>more</a></p>
</div>
</article>
</div><!-- ng-repeat val,key -->
</div><!-- calendar -->
</div><!-- ng-if cal -->
</div><!-- ng-repeat cal -->
</div><!-- calDynamic -->

You should be able to define a custom sort function that sorts by any item in your object. The key bit is to convert the object to an array in the filter function.
Here's an example:
app.filter('orderByDayNumber', function() {
return function(items, field, reverse) {
var filtered = [];
angular.forEach(items, function(item) {
filtered.push(item);
});
filtered.sort(function (a, b) {
return (a[field] > b[field] ? 1 : -1);
});
if(reverse) filtered.reverse();
return filtered;
};
});
You would then call it like this:
<div ng-repeat="(key, val) in cal | orderByDayNumber: 'day' ">
Note, you shouldn't write val.day as that is assumed.
Look at this great blog post here for more info.
EDIT: In fact, it looks like your structure is actually already an array, so while this technique will still work, it may not be necessary - it might have just been the way you were adding the parameter to orderBy that was causing issues.

Related

XPath separate key and value of group

I'm trying to fetch data from a dd group that is not really well structured. The 'group' does have a DD wrapper but inside it's only p/div without a grouped wrapper around it:
[DD]
[P] Key
[DIV]
[P] Value
[P] Key
[DIV]
[P] Value
Is it possible to collect the data the proper way?
The html code I'm processing:
<dd class="product-specifications-v2__items">
<p class="product-specifications-v2__key">
EAN/UPC - product
</p>
<div class="product-specifications-v2__value">
<p class="product-specifications-v2__value-item">
7912372
</p>
</div>
<p class="product-specifications-v2__key">
Weight
</p>
<div class="product-specifications-v2__value">
<p class="product-specifications-v2__value-item">
2,170
<span>kg</span>
</p>
</div>
</dd>
I currently get the following result as a array:
{
"key": [
"EAN\/UPC - product",
"Weight"
],
"value": [
"7912372",
"2,170 kg",
]
}
And I need to get (without arrays):
{
"key": "EAN/UPC - product",
"value": "7912372"
},
{
"key": "Weight",
"value": "2,170 kg"
}
I'm fetching the data via an API with the following request:
{
"name":"attributes",
"selector":"div.product-specifications-v2__wrapper dl dd",
"targets":[
{
"name":"key",
"selector":"p.product-specifications-v2__key",
"dataType":"title"
},
{
"name":"value",
"selector":"div.product-specifications-v2__value p.product-specifications-v2__value-item",
"dataType":"title"
}
]
}
Using XPath 3.1 (for instance, inside the browser with Saxon-JS (https://www.saxonica.com/saxon-js/documentation2/index.html), also with Node) you can use a path expression that creates an XPath 3.1 XDM map with the key and value:
//dd[#class = 'product-specifications-v2__items']/p[#class = 'product-specifications-v2__key']!map { 'key' : normalize-space(), 'value' : following-sibling::div[#class = 'product-specifications-v2__value'][1]!normalize-space() }
const html = `<dd class="product-specifications-v2__items">
<p class="product-specifications-v2__key">
EAN/UPC - product
</p>
<div class="product-specifications-v2__value">
<p class="product-specifications-v2__value-item">
7912372
</p>
</div>
<p class="product-specifications-v2__key">
Weight
</p>
<div class="product-specifications-v2__value">
<p class="product-specifications-v2__value-item">
2,170
<span>kg</span>
</p>
</div>
</dd>`;
var htmlDoc = new DOMParser().parseFromString(html, 'text/html');
const results = SaxonJS.XPath.evaluate(`//dd[#class = 'product-specifications-v2__items']/p[#class = 'product-specifications-v2__key']!map { 'key' : normalize-space(), 'value' : following-sibling::div[#class = 'product-specifications-v2__value'][1]!normalize-space() }`, htmlDoc, { 'xpathDefaultNamespace' : 'http://www.w3.org/1999/xhtml' });
console.log(results);
<script src="https://www.saxonica.com/saxon-js/documentation2/SaxonJS/SaxonJS2.rt.js"></script>
The JavaScript API of Saxon-JS returns the sequence of XDM maps as an array of JSON objects to JavaScript.

Separate and display multiple json value in different span tag in reactjs

I have a json object called blogData with json data. Inside the json obj the tags key may have multiple tag values. I would like to display the tags values separately in span tag while iterating using map function.
Now multiple tags are displaying in a single span tag ( please see below) How can I fix this ?
const blogData = [
{
"id" : 1,
"title":"Cypress tests",
"images":"/images/image1.jpg",
"description": "Add the E2E cypress UI tests",
"tags": "cypress"
},
{
"id" : 2,
"title":"Jmeter tests",
"images":"/images/image2.jpg",
"description": "Performance test using Jmeter tool",
"tags": ["jmeter", "performance"]
},
{
"id" : 3,
"title":"Basic Unix commands",
"images":"/images/image3.jpg",
"description": "Learn basic unix commands in git bash",
"tags": "unix"
},
{
"id" : 4,
"title":"Postman",
"images":"/images/image4.jpg",
"description": "Api testing using postman",
"tags": ["postman", "api"]
},
]
Home.js
const [searchResults, setSearchResults] = useState([]);
<div className="container">
{
searchResults.map(({ id, title, images, description, tags }) => (
<div key={id} className="column-center">
{/* <img className="blogImage" key={images} src={images} alt="image"></img> */}
<div className="blogtitle">
<span key={title}>{title}</span>
</div>
<section>
<p className="blogdescription" key={description}>{description}</p>
</section>
<section className="col1">
<span key={tags}>{tags}</span>
</section>
<section className="col2">
<a>Read more {'>'}{'>'}</a>
</section>
</div>
))
}
</div>
I think this what you are after.
Sandbox
<section className="col1">
{Array.isArray(tags) ? (
tags.map((tag) => (
<span style={{ marginRight: "10px" }}>{tag}</span>
))
) : (
<span>{tags}</span>
)}
</section>
You could make this code much simpler be having the tags field always be an array even if there is a single element.

iterate elements of a json using *ngFor only if they met a condition

I'm working on an angular 4 project calling a json through a service, everything works very well exept for a single thing, my json has the following simplified structure for understanding the problem:
{
"animals" [
{
"name" : "dog"
"subgroup": "vertebrate"
"class" : "mammal"
},
{
"name" : "pig"
"subgroup": "vertebrate"
"class" : "mammal"
},
{
"name" : "cat"
"subgroup": "vertebrate"
"class" : "mammal"
},
{
"name" : "snake"
"subgroup": "vertebrate"
"class" : "reptile"
},
{
"name" : "lizzard"
"subgroup": "vertebrate"
"class" : "reptile"
},
{
"name" : "crocodile"
"subgroup": "vertebrate"
"class" : "reptile"
},
]
}
and i want to iterate ONLY the objects with the "class" : "reptile"
i made this structure:
<div class="col-12 mb-3" *ngFor="let reptiles of animals">
<div *ngIf = "reptiles.class == reptile">
<div class="row">
<div class="col-12">
<h5 class="py-3 bg-dark text-white pl-3 mx-0 mb-3">{{reptiles.name}}</h5>
<p class="py-3 bg-dark text-white font-weight-light pl-3 m-0">{{reptiles.class}}</p>
</div>
</div>
</div>
</div>
but what happens is that it iterates three empty
<div class="col-12 mb-3" *ngFor="let reptiles of animals">
</div>
corresponding to the mammals, and i want that objects not to iterate at all, i want to iterate only the objects with the class "reptile".
how can i achieve that?
The easy fix is to use ng-container instead of a div to iterate:
<ng-container *ngFor="let reptiles of animals">
<div class="col-12 mb-3" *ngIf="reptiles.class == reptile">
<div>
<!-- ... -->
</div>
</div>
</ng-container>
Of course the template still iterates over these entries now, but it will not create any DOM node for it whatsoever (the magic of ng-container).
Possibly a better fix would be to instead filter in your component and only pass the data you want to display to the template:
// In your controller after receiving the animals data:
this.reptiles = this.animals.filter(a => a.class === "reptile");
// Template
<div *ngFor="let reptile of reptiles">...</div>
You can also write a filterBy pipe or take one from an existing library such as ngx-pipes. But beware that Angular discourages that as it easily becomes a performance pitfall.
I think that you can use this solution
Just filter by class property:
filterItemsOfType(type){
return this.items.filter(x => x.class == type);
}
Cheers,
#carlosrojas_o
you just need to filter your data in component like this:
this.filteredAnimals = this.animals.filter(animal => animal.class === "reptile"); // now use filteredAnimals in html template
Hope it will help

Angular.js view - display a description from a code-description json

I have list of schools each with a code for a school level instead of ES, MS, HM.
[
{
"nameOfInstitution": "Summer Elementary",
"schoolLevel": "01304"
},
{
"nameOfInstitution": "Grady Middle",
"schoolLevel": "02400"
}
]
I am planning to use another JSON to get the description of those codes from:
{
"schoolLevel": [
{"01302": "All levels"},
{"01304": "Elementary"},
{"02400": "Middle"},
{"02402": "High school"}
]
}
What is the proper way to display this in Angular in a view where it would look like?
<div class="item item-text-wrap">
<p ng-repeat="school in schools">{{school.nameOfInstitution}} - {{school.schoolLevel}}</p>
</div>
Should it 1). iterate through the main JSON and insert the description after "schoolLevel" or 2). should I use a look-up method to find out the description each time I display a school?
I would think the first option is the better choice, but can anyone share some snippets of code on how to best achieve that?
Thank you!
You can create a filter for lookup:-
DATA:-
$scope.schools=[
{
"nameOfInstitution": "Summer Elementary",
"schoolLevel": "01304"
},
{
"nameOfInstitution": "Grady Middle",
"schoolLevel": "02400"
}
];
$scope.schoollevel={
"schoolLevel": [
{"01302": "All levels"},
{"01304": "Elementary"},
{"02400": "Middle"},
{"02402": "High school"}
]
}
Filter:-
app.filter('level',function(){
return function(item,filter){
//console.log(item.schoolLevel);
var levelVal;
item.schoolLevel.forEach(function(level){
if(typeof level[filter]!='undefined'){
console.log(level[filter]);
levelVal=level[filter];
}
}
);
return levelVal;
}
});
HTML:-
<p ng-repeat="school in schools">{{school.nameOfInstitution}} -
{{schoollevel|level:school.schoolLevel }}</p>
Plunker
Below code should work
Markup
<div class="item item-text-wrap">
<p ng-repeat="school in schools">{{school.nameOfInstitution}} -
{{level.schoolLevel | filter: school.schoolLevel : true }}</p>
</div>
Code
$scope.level = {
"schoolLevel": [
{"01302": "All levels"},
{"01304": "Elementary"},
{"02400": "Middle"},
{"02402": "High school"}
]
}

how to display multiple images in a single line with Kendo?

I am new in kendo ui. I have a shopping cart system like this http://demos.kendoui.com/sushi/. I want to show multiple images in a single line by creating image array. the code of this demo site at this address. https://github.com/telerik/kendo-mobile-sushi.
If you have modified menu.js and the entries look like:
{
"id" : 1,
"name" : "Sashimi salad",
"price" : 12.00,
"image" : "sashimi-salad.jpg",
"category" : "Cold starters",
"description": "Organic greens topped with market fresh sashimi, wasabi soy vinaigrette.",
"featured" : true
},
{
"id" : 2,
"name" : "Chirashi sushi",
"price" : 21.00,
"image" : [ "chirashi-sushi.jpg", "chirashi-sushi.jpg", "chirashi-sushi.jpg"],
"category" : "Cold starters",
"description": "Sushi bar variety with sushi rice.",
"featured" : false
},
Where you have entries as Sashimi salad that only have one image defined as a string and entries as Chirashi sushi where have multiple images defined in an array.
Then you should modify your templates for checking if image is a string and if not then iterate on the array elements. Something like:
<script id="menuTemplate" type="text/x-kendo-template">
<a data-role="button"
data-click="addToCartFromList"
data-item-id="#:id#"
href="\\#">#:kendo.toString(price, "c")#</a>
<a class="details-link" data-role="listview-link" href="\#details?id=#:id#">
# if (typeof image === 'string') { #
<img src="content/images/75/#= image #"/>
# } else { #
# for (var i = 0; i < image.length; i ++) { #
<img src="content/images/75/#= image[i] #"/>
# } #
# } #
<h2>#:name#</h2>
<span class="added"#= cartDataSource.get(id) ? "" : 'style="display: none"' #>Item added to cart</span>
</a>
</script>