Can someone point out to me what I may be doing wrong here? I have a controller pulling data from a JSON file on my server using the $http service, and passing it through an attribute to a directive. The problem is that even though I only see 4 objects in my JSON looping through it gives me 325. Further more none of the attributes are accessible to me.
My JSON
[{
"name": "Cute Shirt",
"Type": "Shirt",
"Size": "S,M,L,XL",
"Color": "R,G,B",
"SRC": "img/shirt.png"
}
,
{
"name": "Cute Shirt",
"Type": "Shirt",
"Size": "S,M,L,XL",
"Color": "R,G,B",
"SRC": "img/shirt.png"
}
,
{
"name": "Cute Shirt",
"Type": "Shirt",
"Size": "S,M,L,XL",
"Color": "R,G,B",
"SRC": "img/shirt.png"
}
,
{
"name": "Cute Shirt",
"Type": "Shirt",
"Size": "S,M,L,XL",
"Color": "R,G,B",
"SRC": "img/shirt.png"
}
]
My Controller
"use strict";
function itemControl ($http,$scope) {
$http.get('doc/products.json' ).success(function(prodata){$scope.data = prodata;});
}
My Directive
app.directive("showcase", function() {
return {
restrict: "A",
template: '{{stuff.length}}',
scope: {
stuff: "#"
}
};
});
And Finally the HTML
<div ng-controller="itemControl">
<div showcase stuff="{{data}}"></div>
</div>
From the AngularJS documentation:
# or #attr - bind a local scope property to the value of DOM attribute. The result is always a string since DOM attributes are strings.
Using the = will help
= or =attr - set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of the attr attribute.
You will want to change your <div showcase stuff="{{data}}"></div> to <div showcase stuff="data"></div>
Change # to =
# means it will interpolate the object to string.
Related
In Azure Data Factory, I'm attempting to add params to the body of a copy task (connected to a REST API post request as the source). I'm wanting to use dynamic content to do so, but I'm struggling trying to find the real solution for the proper nomenclature. Here's what I have so far.
copy task
dynamic content
{
"datatable":
{
"start":0,
"length": 10000,
"filters": [
{
"name": "Arrival Dates",
"start": "pipeline().parameters.pDate1",
"end": "pipeline().parameters.pDate2"
}
],
"sort": [
{
"name": "start_date",
"order": "ASC"
}
]
}
}
You'll notice that I've added params for dates. Is this the correct nomenclature for trying to add dynamic content? The autocorrect tried to add the # sign in the beginning of the code block, which will cause the entire thing to error out. I've tried adding it before each parameter, but that isn't actually reading the dynamic values either.
This is not correct. You need to use concat to concatenate the different variables. Something like this :
#concat('{ "datatable": { "start":0, "length": 10000, "filters": [ { "name": "Arrival Dates", "start": "',pipeline().parameters.pDate1,'", "end": "',pipeline().parameters.pDate2,'" } ], "sort": [ { "name": "start_date", "order": "ASC" } ] } }')
This is also documented in the SO question.
Im trying to make a system monitor, which is highly customisable by user. This customization is achieved by using JSON file for modeling look of system monitor. The JSON could look like this.
{
"_": "WINDOW",
"name": "myWindow",
"children": [
{
"_": "CPU",
"name": "cpuMonitor",
"freq_Unit": "MHZ"
},
{
"_": "NETWORK",
"name": "network",
"unit": "Kb/s"
},
{
"_": "DISK",
"name": "disk"
}
],
"background": "red"
}
As you can see, each object coresponds to this schema.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"name":"Component",
"type": "object",
"properties":{
"_": {
"type": "string"
},
"name":{
"type":"string"
},
"childern":{
"type":"array"
}
},
"required": ["_","name"]
}
But each component has also its own schema definition. I'd like to parse whole JSON and validate each node for different schema (first if its component and then to its corresponding schema).
I had look at rapidJson and other libraries, but I didnt find solution for validating nodes for different schema. Do you know any library which could do that? Or is it even possible to validate JSON in this way?
All feedback on how to solve this will be appreciated.
Edit: Corrected schema :(
There's a simple approach involved with that, use the oneOf pattern declaration to specify the layout of the array elements. Inside these nested declarations, you specify the fixed identifier (probably the content of your _ field) as a constant, so that there is only one nested schema matching each of your panel types.
Notes:
I had to specify the constant type identifier using the enum specifier because the regular constant specifier didn't work with the library I was using. This may also have been an oversight in the revision of the specification that it was based on.
A different approach is to split the the validation steps. You simply verify that the elements of the array are objects and that they have a string field _ containing one of the supported types. When iterating over the array, you then validate each field individually according to its _ field.
In addition to Ulrich's answer, here's an example of what I'd do:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Component",
"type": "object",
"definitions": {
"base": {
"properties": {
"name": { "type": "string" },
"children": {
"type": "array",
"items": { "$ref": "#" }
}
},
"required": [ "_", "name" ]
},
"cpu": {
"properties": {
"_": { "const": "CPU" },
"freq_Unit": "MHZ"
}
},
"network": {
"properties": {
"_": { "const": "NETWORK" },
"unit": "Kb/s"
}
},
"disk": {
"properties": {
"_": { "const": "DISK" }
}
},
"window": {
"properties": {
"_": { "const": "WINDOW" },
"background": { "enum": [ "red", "orange", "yellow", ... ] }
}
}
},
"allOf": [
{ "$ref": "#/definitions/base" },
{
"oneOf": [
{ "$ref": "#/definitions/cpu" },
{ "$ref": "#/definitions/network" },
{ "$ref": "#/definitions/disk" },
{ "$ref": "#/definitions/window" }
]
}
]
}
First, we require that any instance MUST adhere to base which declares _ and name as required properties. Additionally, we declare a children array property that requires all items also match this schema (giving us a recursive behavior). This doesn't really do much except that it allows us to declare these things in one place instead of having to declare them in the other three definitions.
(Note that we don't declare _ in the properties list. This means that any value will pass for this portion of the schema. We clean it up in the next part. If you want to ensure that future components are declared with strings, then you can add a "type": "string" requirement to that property, but I don't feel it's necessary unless others are authoring those components.)
Second, we declare each of our specific types as separate definitions, using the const keyword to isolate the one we want. This construct is analogous to a switch (or case) statement. If the instance doesn't match one of these explicit options, it fails. If it's missing one of the required base properties, it fails.
This will get you where you want to be.
To take it further, there are two more things you can do:
Add required to the other definitions to say that the specific properties are also required (e.g. freq_Unit for the cpu definition).
Declare each of the definitions in separate files. This would allow you to add a new definition by simply adding a new file and referencing it in the main schema. In my opinion, it's a bit cleaner. Some people prefer to have it all in one file, though.
I'm having no trouble accessing the initial child of the parent object in a json, however, I cannot seem to figure out what the format for accessing the child of a child is. I'm currently using dot notation as described in the handlebars.js documentation.
My html with handlebars.js implemented (the 'Fees' aren't showing correctly, they show up as [object Object]):
{{#options}}
{{#company_base}}
<div>
<h1>{{name_full}}</h1><b>AM Best Rating</b>: {{ambest_rating}}
<p><b>Type</b>: {{business_type}}</p>
<p><b>Fees</b>:
<ol>
<li><b>Type</b>: {{../..options.fees.type}}</li>
<li><b>Name</b>: {{../..options.fees.name}}</li>
</ol>
</p>
</div>
{{/company_base}}
{{/options}}
My mock JSON:
{
"options": [{
"company_base": {
"business_type": "Life, Accident, and Health",
"established_year": 1998,
"med_supp_state_market_data": [{
"market_share": 0.63490064689900005,
"state": "AK",
"lives": 8041,
"premiums": 14714825,
"claims": 11649263
}, {
"market_share": 0.34445359987700003,
"state": "WY",
"lives": 14916,
"premiums": 30178554,
"claims": 24281001
}],
"underwriting_data": [],
"med_supp_national_market_data": {
"market_share": 0.315510079562,
"state": null,
"lives": 3723184,
"premiums": 8276072271,
"claims": 6436017316
},
"customer_complaint_ratio": 0.0013368044250809999,
"ambest_outlook": "Stable",
"name_full": "Major Health Partners of the Wind",
"ambest_rating": "A",
"parent_company": "aghzfmNzZ2sdfZWRfc3VwcA",
"last_modified": "2017-01-16T12:28:17.591830",
"customer_satisfaction_ratio": 0.83666666666699996,
"default_resources": {
"final-expense-life": {
"e_app_link": ""
},
"medicare-advantage": {
"e_app_link": ""
},
"medicare-supplement": {
"e_app_link": "sdf"
},
"hospital-indemnity": {
"e_app_link": ""
},
"dental": {
"e_app_link": ""
}
},
"key": "assdfsdfVwcA",
"parent_company_base": {
"established_year": 1998,
"code": "707",
"name": "Space Insurance",
"key": "asfdf",
"last_modified": "2016-11-11T16:42:52.240940"
},
"sp_rating": "AA-",
"naic": "79413",
"type": "STOCK",
"name": "Spacewomen Insurance"
},
"has_pdf_app": true,
"rate": {
"quarter": 23841,
"annual": 92964,
"semi_annual": 47682,
"month": 7747
},
"rating_class": "Standard",
"fees": [{
"name": "corgi discount",
"type": "buddy"
}]}
Here is a live example of my issue.
It is not the "child of a child" that you are having trouble accessing, but a sibling property that is of the array type.
There are two problems with your example. First, fees is on the same level as company_base. When you are within the {{#company_base}} {{/company_base}} tags you are within the context of the company_base object, so must step-up one level in order to access its siblings. The correct path would be: {{../fees}}.
Your second issue is that fees is an array. You might want to {{#each}} over this array, but if you want only the first object, then you can access it like: {{fees.0.type}}.
This means that your template should be updated with the following:
<li><b>Type</b>: {{../fees.0.type}}</li>
<li><b>Name</b>: {{../fees.0.name}}</li>
That should do the trick. However, I would like to recommend an alternative way of writing your template. I would eliminate the need to step-up a level to get the fees object by removing the {{#company_base}} {{/company_base}} tags. This will mean that you are at the level of the current object in the options array and you can use dot notation to access its descendant properties. The updated template would look like the following:
{{#each options}}
<div>
<h1>{{company_base.name_full}}</h1>
<b>AM Best Rating</b>: {{company_base.ambest_rating}}
<p><b>Type</b>: {{company_base.business_type}}</p>
<p>
<b>Fees</b>:
<ol>
<li><b>Type</b>: {{fees.0.type}}</li>
<li><b>Name</b>: {{fees.0.name}}</li>
</ol>
</p>
</div>
{{/each}}
Note: I am opting for the more explicit {{#each options}} over {{#options}}.
I have created an example fiddle here.
I'm trying to conditionally provide resource property values through translation of runtime resource properties within a copyIndex loop..
Upon deploying the following ARM template, I receive the error:
Unable to process template language expressions for resource '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vm-name}/extensions/Microsoft.EnterpriseCloud.Monitoring' at line '30' and column '10'. 'The template resource '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vm-name}' is not found.' (Code: InvalidTemplate)
"type": "[variables('extensionType')[reference(concat('Microsoft.Compute/virtualMachines/', parameters('virtualMachines')[copyIndex()].name)).storageProfile.osDisk.osType]]",
However, the VM exists with the ID it provides, so it doesn't make sense that the engine cannot find it. If I hard-code the Extension Type, there are no errors and the Extension is installed on the VM with the same ID.
Unfortunately, I don't know if this is a bug within ARM or if I'm just doing something wrong..
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspaceResourceId": { "type": "string" },
"virtualMachines": { "type": "array" }
},
"variables": {
"extensionType": {
"Windows": "MicrosoftMonitoringAgent",
"Linux": "OmsAgentForLinux"
}
},
"resources": [
{
"copy": {
"name": "VMMonitoringExtensionsCopy",
"count": "[length(parameters('virtualMachines'))]"
},
"type": "Microsoft.Compute/virtualMachines/extensions",
"apiVersion": "2015-05-01-preview",
"location": "[parameters('virtualMachines')[copyIndex()].location]",
"name": "[concat(parameters('virtualMachines')[copyIndex()].name, '/Microsoft.EnterpriseCloud.Monitoring')]",
"properties": {
"publisher": "Microsoft.EnterpriseCloud.Monitoring",
"type": "[variables('extensionType')[reference(concat('Microsoft.Compute/virtualMachines/', parameters('virtualMachines')[copyIndex()].name)).storageProfile.osDisk.osType]]",
"typeHandlerVersion": "1.0",
"autoUpgradeMinorVersion": true,
"settings": {
"workspaceId": "[reference(parameters('workspaceResourceId'), '2015-11-01-preview').customerId]"
},
"protectedSettings": {
"workspaceKey": "[listKeys(parameters('workspaceResourceId'), '2015-11-01-preview').primarySharedKey]"
}
}
}
]
}
The object array being passed in for virtualMachines looks like this:
[
{ "name": "vm-name", "location": "azure-region" }
]
A couple things you can try:
1) Assuming the VM is not defined in the same template try using the "full" resourceId in the reference function. See the last example in this doc:
https://azure.microsoft.com/en-us/documentation/articles/resource-group-template-functions/#reference - it seems like the error already knows the full resourceId, but it's worth trying
2) the other thought is that the reference function is evaluated at runtime and the resource provider doesn't like the expression but that's a swag.
I will do some more poking and see if we can't nail this down.
I'm trying to pass list parameters from master to child template, however I'm running into two errors.. These are my current parameters on the master template.
"Parameters": {
"ELBSubnets": {
"Default": "subnet-5d8fea67,subnet-3e35cf15",
"Type": "CommaDelimitedList"
},
"LCKeyPair": {
"Default": "key-master",
"Type": "String"
},
"LCSecurityGroups": {
"Default": "sg-10a15c74,sg-880e5fec",
"Type": "CommaDelimitedList"
}
},
They are being referenced in this method on the same template when passing on to the child template.
"ChildTempate1": {
"Properties": {
"Parameters": {
"ELBSubnets": {
"Ref": "ELBSubnets"
},
"KeyPair": {
"Ref": "LCKeyPair"
},
"LCSecurityGroups": {
"Ref": "LCSecurityGroups"
}
},
On the child template, they are declared exactly the same.
"Parameters": {
"ELBSubnets": {
"Type": "CommaDelimitedList"
},
"LCKeyPair": {
"Type": "String"
},
"LCSecurityGroups": {
"Type": "CommaDelimitedList"
}
},
And they're being referenced in this method in the child template.
"KeyName": {
"Ref": "LCKeyPair"
},
"SecurityGroups": {
"Fn::Join": [
",",
[
{
"Ref": "LCSecurityGroups"
}
]
]
}
},
This is another part of the template.
"Subnets": {
"Fn::Join": [
",",
[
{
"Ref": "ELBSubnets"
}
]
]
}
},
When I attempt to use the fn::join on the master template, it says
"Template validation error: Template error: every Fn::Join object requires two parameters, (1) a string delimiter and (2) a list of strings to be joined or a function that returns a list of strings (such as Fn::GetAZs) to be joined."
When I don't use fn::join on the master template the error is
Value of property Parameters must be an object with String (or simple type) properties
Regardless of whether I have fn::join on the same parameters in the child template.
Both templates can be found here: https://github.com/slimg00dy/Troposphere-CloudformationTests
The issue is that when using Ref on a CommaDelimitedList, you pass a list, so it passes "[a,b,c]" rather than "a,b,c"
So on the master template I've used Join(",") to pass lists, and Join(" ") to pass strings. This way they're Referenced as "a,b,c" and " String"
On the child template I've set the parameters as CommaDelimitedLists for the lists and String from the String. This is because of the way they're being passed from the master template.
I then used Ref on the Child template without the use of Join() on the child template. This created the CommaDelimitedLists into Lists and the Strings that were joined with Join(" ") passed as strings.
Here is my parameter declaration on the master Template.
"Parameters": {
"ELBSubnets": {
"Default": "subnet-5d8fea67,subnet-3e35cf15",
"Type": "CommaDelimitedList"
},
"LCKeyPair": {
"Default": "key-master",
"Type": "CommaDelimitedList"
},
"LCSecurityGroups": {
"Default": "sg-10a15c74,sg-880e5fec",
"Type": "CommaDelimitedList"
}
},
Here is how I used Join(","), Join(" ") and Ref. Since Ref converts the CommaDelimitedLists into Lists, I used Join(",") to keep them as CommaDelimitedLists and pass them on to the child template.
As for the KeyPair String, I made sure that it was declared as a CommaDelimitedList on the parent template and joined with Join(" "), this effectively made it into a string when referencing to the child template.
"Parameters": {
"ELBSubnets": {
"Fn::Join": [
",",
{
"Ref": "ELBSubnets"
}
]
},
"LCKeyPair": {
"Fn::Join": [
" ",
{
"Ref": "LCKeyPair"
}
]
},
"LCSecurityGroups": {
"Fn::Join": [
",",
{
"Ref": "LCSecurityGroups"
}
]
}
},
On the child template, they're declared like so.
"Parameters": {
"ELBSubnets": {
"Type": "CommaDelimitedList"
},
"LCKeyPair": {
"Type": "String"
},
"LCSecurityGroups": {
"Type": "CommaDelimitedList"
}
},
And they are all referenced normally without the use of Join on the child template.
Subnets": {
"Ref": "ELBSubnets"
}
There could have been many different ways to do this. I could have had the joins on the child template rather than the parent template. However I prefer to keep one template complicated and the rest as clean as possible. Hope this helps others down the line.
I also should have been able to pass the list as a list on the child template, however then I received the error "Unknown parameter type: List"
CommaDelimtedList can only be parsed once, so in the parent template, you need to set the type as "String", then in the child template, keep it as CommaDelimitedList, as before.
The problem is happening, because CloudFormation is parsing the CommaDelimitedList in the parent template, and then it's trying to parse it again in the child template.
So my previous answer was a little confusing - but I think the basics still stand. In the end you shouldn't have to Join() a CommaDelimitedList when it is used in an argument that expects a list. I just looked at your most recent updates to the repo you shared, and I think you're on the right track. If you need more help, let me know!