Nested ngrepeats with inconsistent data structures - html

I am creating a set of divs from a JSON object using ng-repeat that construct "note" cards. The number of cards is determined by the number of JSON objects in the array. "Type" designates the header of the card, and "Content" designates the body. However, the contents of "Content" is not consistent. In some examples, the content is merely a sentence or paragraph. In others, the content is an array. When the content is a sentence, the formatting is handled fine. When the content is an array, I end up with the actual array in text format [{"year":"2009", "operation":"caesarean"},{"year":"2010", "operation":"torn meniscus"}] as the body of the card. Any ideas of how to implement this without scripting each card individually?
HTML
<section name="patientinfo">
<div align="center" ng-controller="HistoryCtrl">
<div class="grid-container" ng-repeat="record in historyItems">
<div class="row" row>
<div class="col-2" ng-repeat="history in record.History">
<div class="note" draggable="true">
<div class="row" id="rowhead3">
<div class="col-6" >
<span class="note-header">{{history.type}}</span>
</div>
</div>
<div class="row">
<div class="col-6" style="overflow: auto; height:250px;">
<div>
<span class="note-content">
{{history.content}}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
JSON Example (the actual JSON is huge). There are many other entries besides "history". Also, these notes are not from a real person, so don't worry.
"History": [
{
"type": "medical",
"content": [
{
"condition": "IBS"
},
{
"condition": "Torn Meniscus Right Knee"
},
{
"condition": "Seasonal Allergies"
}
]
},
{
"type": "SOCIAL HISTORY",
"content": "Lives with husband and 3 children. No history of violence, domestic violence, or rape. Feels safe at home and in relationship. ETOH on weekends (socially 4 drinks in one weekend occasionally) and occasionally smokes cigarettes and marijuana. Admits to very rare marijuana on special occasions."
}]
Example of what I'm ending up with:
http://i.stack.imgur.com/MtuBN.png

You should transform or augment the data into a new format where you have the following structure for each note:
{
type: "string",
contentType: "(text|list)",
content: "string" // OR array of strings
}
To do this, you will need to have custom logic to transform each object in the array to a single string.
Then just use an ng-switch on the contentType attribute to decide which markup to use (e.g. a <ul> if contentType is list).

Related

How to format JSON data fetch from API

Am getting data from API and trying to display it in my angular application I can able to fetch and display the data but it's not in a good format.
{
"countryCode": "BS",
"countryName": "BAHAMAS",
"publishedDate": "2020-03-30T00:00:00.000Z",
"alertMessage": "\nAll international flights to Uganda are suspended until 24 April 2020.|\n- This does not apply to:|\n1. Aircraft in a state of emergency.||\n2. Operations related to humanitarian aid, medical and relief flights.||\n3. Technical landings where passengers do not disembark.||\n4. Any other flight that may be so approved by the appropriate authority.||\n"
},
{
"countryCode": "FJ",
"countryName": "FIJI",
"publishedDate": "2020-03-30T00:00:00.000Z",
"alertMessage": "\n1. Passengers and airline crew are not allowed to enter Fiji.|\n- This does not apply to nationals of Fiji.||\n2. Nationals of Fiji must go into quarantine for a period of 14 days.||\n"
}
JSON data which I get from API.
The output which is expecting is
but the output which am getting is
my code as follows
<div class="card" style="width: 69rem;" *ngFor="let alert of jsonValue">
<div class="card-body" #{{alert.countryName}}>
<div class="container">
<div class="row">
<div class="col">
<span> <p class="card-title h2" style="float: left">{{alert.countryName}}</p></span>
</div>
<div class="col">
<span><img src="../../../assets/flags/{{alert.countryCode | lowercase}}.svg" style="width: 40px; height: 28px;"></span>
</div>
</div>
</div>
<p class="card-text">{{alert.alertMessage}}</p>
<p class="card-footer" style="float: right">{{alert.publishedDate | date:'short'}}</p>
</div>
</div>
The text is unusually formatted. One way to use it is to split the string as per your requirement and iterate it using *ngFor.
var alertMessage = '\nAll international flights to Uganda are suspended until 24 April 2020.|\n- This does not apply to:|\n1. Aircraft in a state of emergency.||\n2. Operations related to humanitarian aid, medical and relief flights.||\n3. Technical landings where passengers do not disembark.||\n4. Any other flight that may be so approved by the appropriate authority.||\n';
console.log(alertMessage.split(/[||\n]+/).filter(Boolean)) // <-- `filter(Boolean)` to remove empty strings
You could then use it in the component like following
Service fetching data from API
#Injectable()
export class ApiService {
...
getData() {
this.http.getData().pipe(
.map(data =>
data.forEach(item => {
item.alertMessage = item.alertMessage.split(/[||\n]+/).filter(Boolean)
})
)
);
}
}
Component template
<div class="card" style="width: 69rem;" *ngFor="let alert of jsonValue">
<div class="card-body" #{{alert.countryName}}>
<div class="container">
<div class="row">
<div class="col">
<span> <p class="card-title h2" style="float: left">{{alert.countryName}}</p></span>
</div>
<div class="col">
<span><img src="../../../assets/flags/{{alert.countryCode | lowercase}}.svg" style="width: 40px; height: 28px;"></span>
</div>
</div>
</div>
<p class="card-text">
<ul [ngStyle]="{'list-style': 'none', 'padding-left': '0'}">
<li *ngFor="let message of alert.alertMessage">{{ message }}</li>
</ul>
</p>
<p class="card-footer" style="float: right">{{alert.publishedDate | date:'short'}}</p>
</div>
</div>
May be you want to do some formatting to your data before using it in the template.
The string contains \n and | which has a special meaning. You can use them to format your data.
for Example let say you are getting this data from service inside a method someMethod() . After getting the data loop over the result array elements
and create a new Array for all the response items containing the formatted values.
someMethod(){
.... other lines to fetch the data
let data = {
"countryCode": "BS",
"countryName": "BAHAMAS",
"publishedDate": "2020-03-30T00:00:00.000Z",
"alertMessage": "\nAll international flights to Uganda are suspended until 24 April 2020.|\n- This does not apply to:|\n1. Aircraft in a state of emergency.||\n2. Operations related to humanitarian aid, medical and relief flights.||\n3. Technical landings where passengers do not disembark.||\n4. Any other flight that may be so approved by the appropriate authority.||\n"
}
let arr = str.split('|').filter((el)=>{ return el!== ""}); // splits the string and removes empty element
let newArr = arr.map((el)=>{ return el.replace("\n" ,"")}) // removes \n from string
// of course you can minimise/reduce the logic , this is just to make you understand how the formatting happened
let formattedValues = {
title : newArr[0], // first element is title
subtitle : newArr[1], // second is subtitle
options : newArr.slice(2) // rest is option
}
data['alertMessage'] = formattedValues; // assign the formatted value
}
then in HTML you can use the JSON as below :
<p class="card-text">{{alert.messageData.title}}</p>
<p class="card-text">{{alert.messageData.subtitle}}</p>
<p *ngFor="let it of alert.messageData.options">{{it}}</p>
Here is the working example : Demo

Is this proper Schema.org/Microdata markup for a building?

I am trying to add Microdata notation (using Schema.org) to my website which basically talks about buildings. I’ve been reading a lot about it but I’m still having trouble figuring out where to use itemscope, itemtype and itemprop.
Can anybody tell me if this is good Microdata/Schema.org markup or if I’m missing something?
<div class="infobox infobox_building" itemscope itemtype="http://schema.org/LandmarksOrHistoricalBuildings">
<!-- Building Name -->
<h1 class="page_title">Puente Golden Horn Metro</h1>
<!-- Architect -->
<div class="data_row architect" itemscope itemtype="http://schema.org/creator">
<div class="tag cell">Arquitecto</div>
<div class="value cell">
Michel Virlogeux
Hakan Kıran
</div>
</div>
<!-- Height -->
<div class="data_row" itemscope itemtype="http://schema.org/height">
<div class="tag cell">Altura</div>
<div class="value cell" itemprop="QuantitativeValue">65m</div>
</div>
<!-- Width -->
<div class="data_row" itemscope itemtype="http://schema.org/width">
<div class="tag cell">Ancho</div>
<div class="value cell" itemprop="QuantitativeValue">12,6m</div>
</div>
<!-- Location -->
<div class="data_row" itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
<div class="tag cell">Ubicación</div>
<div class="value cell" itemprop="streetAddress">Arap Cami Mahallesi, Beyoğlu/İstanbul, Turquía</div>
</div>
</div> <!-- infobox -->
You seem to confuse properties and types.
In Microdata, properties get specified in the itemprop attribute, while types get specified in the itemtype attribute.
If you only use the vocabulary Schema.org, you’ll use the full URI for types (itemtype="http://schema.org/PostalAddress"), while you use just the slug for properties (itemprop="address").
In Schema.org, it’s easy to see what is what, because they follow the convention that the first letter of properties is lowercase (address), and the first letter of types is uppercase (PostalAddress).
Syntactically, you are doing it correctly with address+PostalAddress, but wrong with creator+Person and height/width+QuantitativeValue.
That said, you are also making some vocabulary errors. The LandmarksOrHistoricalBuildings type can’t have a creator nor a height nor a width property in the first place.
You can see which properties a type can have by visiting the type’s page (LandmarksOrHistoricalBuildings) and checking the first table.
I also had the same problem or question like you. Because my buildings are not even historical (when is a building historical?), I created my own schema:
{
"#context":
{
"Place": "http://schema.org/Place",
"name": "http://purl.org/dc/terms/title",
"alternateName":"http://purl.org/dc/terms/title",
"description": "http://purl.org/dc/terms/description",
"geo": "http://schema.org/geo",
"image":
{
"#id": "http://schema.org/image",
"#type": "#id"
},
"latitude":
{
"#id": "http://www.w3.org/2003/01/geo/wgs84_pos#lat",
"#type": "xsd:decimal"
},
"longitude":
{
"#id": "http://www.w3.org/2003/01/geo/wgs84_pos#long",
"#type": "xsd:decimal"
},
"containedInPlace":"http://schema.org/Place",
"containsPlace":"http://schema.org/Place",
"architect":"http://schema.org/Creator",
"Address": "http://www.w3.org/2006/vcard/ns#Address",
"address": "http://www.w3.org/2006/vcard/ns#address",
"street": "http://www.w3.org/2006/vcard/ns#street-address",
"locality": "http://www.w3.org/2006/vcard/ns#locality",
"region": "http://www.w3.org/2006/vcard/ns#region",
"country": "http://www.w3.org/2006/vcard/ns#country",
"postalCode": "http://www.w3.org/2006/vcard/ns#postal-code",
"meter": "http://purl.org/measurement#meter",
"kilometer": "http://purl.org/measurement#kilometer",
"feet": "http://purl.org/measurement#feet",
"miles": "http://purl.org/measurement#miles",
"xsd": "http://www.w3.org/2001/XMLSchema#"
}
}
But I am not sure whether google or some other search services will get the idea. If you have any improvements or ideas to the schema let me know!

Get nested values from JSON with angularJS

I need to get nested products from JSON to my html in <div ng-repeat="order in orders"></div> I tried many versions of getting products values(name, description etc.) but none of them works. How to do this ?
JSON:
[
{
"id":3,
"date":"00:00:00",
"user":{
"id":1,
},
"orderState":{
"id":1,
},
"products":[
{
"id":1,
"name":"Bosch POF 1200",
"description":"1200W",
"enabled":true,
"price":459,
},
{
"id":9,
"name":"Graphite 58G782",
"description":"a",
"enabled":true,
"price":429,
}
]
}
]
Controller
OrdersService.retrieveAllByCurrentUser().then(function(response) {
$scope.orders = response.data;
console.log(response.data);
}, function(error) {
registerError(error, 'retrieving all orders');
});
The ng-repeat directive creates a new scope, which means that you should be able to loop through the products within it like this:
<div ng-repeat="order in orders">
<div ng-repeat="product in order.products"> e.g. {{product.name}} </div>
</div>
I would also advise to write a directive for dealing with that kind of stuff, because your code can get unreadable really fast. Don't take my word for it though as I am no Angular expert.
Create a nested ng-repeat like this to access the products information:
<div ng-repeat="order in orders">
<div ng-repeat="product in order.products">
<h1 ng-bind="product.name"></h1>
<p ng-bind="product.description"></p>
</div>
</div>
For each order it will go into order.products and loop out the information as product, then you can access the information in product via dot notation, like product.name for example.
You can do nested ng-repeat in html
<div ng-repeat="order in orders">
<div ng-repeat "product in order.products">
<span>{product.name}}</span>
<span>{{product.description}}</span>
</div>
</div>

access certain element of JSON in angular JS

Below is my JSON file:
[
{
"Name":"Peter England Shirt",
"Prodimage":["./images/zoom/zoom1hi.jpg","./images/zoom/zoom2hi.jpg","./images/zoom/zoom3hi.jpg"],
"actualPrice":"90",
"discountedPrice":"70",
"desc":"Cotton",
"Prodcolor":["#f1f40e","#adadad","#4EC67F"],
"quantity":[1,3,4,5,60],
"size":["XL","L","M","S"],
"detail":"Take it away",
"sizeChart":["16 waist","Measurements taken from size 30","Model wears size 31. Model is 6'2"],
"shipping":[
{
"type":"Standard",
"days":"5-6 days",
"cost":"200"
},{
"type":"Next day",
"days":"1 days",
"cost":"500"
}
],
"sellerList":[
{
"sellerName":"ABC",
"price":"566",
"deliveryDay":"4-5 working days"
},{
"sellerName":"SEDF",
"price":"300",
"deliveryDay":"4-5 working days"
},{
"sellerName":"QWER",
"price":"555",
"deliveryDay":"2-5 working days"
}
]
}
]
The JS file is as below:
var pJson="./json/product.json";
$http.get(pJson).success(function(response){
$scope.product=response;});
Now, if I want to access "Name" attribute I can call {{product[0].Name}}.
But I am not able to access Prodimage attribute using ng-repeat. I am trying like this:
<div ng-repeat="image in product.Prodimage">
{{image[0]}}
</div>
is this wrong?>
Yes this is wrong ,, note that you have the product object as array ,, so if you want the first object you should do this
<div ng-repeat="image in product[0].Prodimage">
{{image[0]}}
</div>
or if you want to iterate over all the products ,, you need to make a nested ng-repeat
<div ng-repeat="p in product">
<div ng-repeat="image in p.Prodimage">
{{image[0]}}
</div>
</div>
You could loop over it, becasue the outside is technically an array, and use $first for you example of wanting to only grab the first image. You could also use $index but running it through a function that checks the $index.
Fiddle here http://jsfiddle.net/HB7LU/15324/
I just re worked it to loop twice like so
<div ng-repeat="prod in product">
<div ng-repeat="image in prod.Prodimage">
<div ng-show="$first">
{{image}}
</div>
</div>
</div>
then put a div inside the inner repeat that will only show if it's the first item. Again you could change that logic to show by index, or whatever you want. So if you know the index you could change that same logic to this -
see fiddle - http://jsfiddle.net/HB7LU/15332/
<div ng-show="checkIndex($index)"> << or whatever index you want
{{image}}
</div>
and in the controller
$scope.checkIndex = function(item){
if(item === 0){
return true;
}else{
return false;
}
}
You just pass the index of the current item in the repeat and check it. I would recommend this logic over the Prodimage[0] logic so you are not hardcoding it into the html, so if you have to change the desired index, you change it in the controller, not template. The checkIndex is a quick example, you could change that to do whatever you want.
$scope.product[n].Prodimage is an array. So, you need to loop through your product array first, and then loop through the Prodimage array of each product:
<div ng-repeat="prod in product">
<div ng-repeat="image in prod.Prodimage">
{{ image }}
</div>
</div>
Of course, you could also just access the nth image using something like:
<div ng-repeat="prod in product">
{{ prod.Prodimage[0] }}
</div>
Can you change your json to
"Prodimage":[
{ "loc": "./images/zoom/zoom1hi.jpg"},
{ "loc": "./images/zoom/zoom2hi.jpg"},
{ "loc": "./images/zoom/zoom3hi.jpg"}],
then your loop should work
<div ng-repeat="image in product.Prodimage">
{{image.loc}}
</div>

Looping through json passed through to assemble partial as variable

I'm having trouble trying to loop through my JSON data with an a assemble site setup in the following structure:
-src
--content
---index.hbs
--data
---steps-data.json
--partial
---steps.hbs
The index.hbs in the content calls the partial passing through the object like so:
{{> steps steps-data}}
My steps-data.json file looks like so:
{
"steps":[{
"index": 1,
"title": "Find a product",
"description": "Go to a product page and click on the +PriceTrack short cut to add to your list."
},{
"index": 2,
"title": "Track its price",
"description": "Go to a product page and click on the +PriceTrack short cut to add to your list."
},{
"index": 3,
"title": "Purchase",
"description": "Go to a product page and click on the +PriceTrack short cut to add to your list."
}]
}
In my steps.hbs i've tried looping through the JSON data but its not.
<div class="g-col g-span4">
{{#each steps-data.steps}}
<div class="working-step">
<span class="number"></span><h3>{{title}}</h3>
</div>
<p>{{description}}</p>
{{/each}}
</div>
The problem I have is that its not looping through and not sure what I'm doing wrong.
Since you passed steps-data into the partial as it's context, you can access steps directly or with this.steps:
<div class="g-col g-span4">
{{#each this.steps}}
<div class="working-step">
<span class="number"></span><h3>{{title}}</h3>
</div>
<p>{{description}}</p>
{{/each}}
</div>