I want to have a group of text inputs with an input bound to each string in an array of strings. I have my template set up like this.
<div ng-repeat="field in rule.groupFields">
<div>
<label for="groupFields">Field:</label>
<input ng-model="field" id="groupFields" type="text">
</div>
</div>
My model is an array of rules that looks like this.
{
"rules": [
{
"name": "Rule1",
"groupFields": [
"field1", "field2", "field3"
]
}.
... more rules ...
]
}
The problem I'm having is the values of the fields show up in the text inputs, but when changes are made in the inputs the model is not updated. In other words, if I change the first text input from "field1" to "hello", what shows up in the model is still "field1" not "hello".
Am I specifying the binding incorrectly?
The previous owner of this code had the template specified like this:
<div ng-repeat="field in rule.groupFields">
<div>
<label for="groupFields">Field:</label>
<input ng-model="field.value" id="groupFields" type="text">
</div>
</div>
Note the is binding to "field.value" rather than "field". The previous model was specified like this.
{
"rules": [
{
"name": "Rule1",
"groupFields": [
{ "value": "field1" },
{ "value": "field2" },
{ "value": "field3" }
]
}.
... more rules ...
]
}
This works but it is a pain in the back end because in the domain object and in the database "groupFields" is an array of strings not an array of objects. I would rather not have to translate between two models of the same information.
Related
JSON
{
"SubQuestion": "A question",
"AnswerValue": "2",
"EnumValue": {
"Name": "name",
"SomeEnum": {"1": "option1", "2": "option2", "3": "option3"}
}
"SubQuestion": "A second question",
"AnswerValue": "3",
"EnumValue": {
"Name": "name",
"SomeEnum": {"1": "option1", "2": "option2", "3": "option3"}
}
}
In the JSON I have some questions with answers.
The stucture of the JSON cannot be changed.
In my frontend there are checkboxes with the questions and answers (checked if AnswerValue == SomeEnum )
All enum values must be shown on the front end.
The checkbox must be checked if AnswerValue == SomeEnum
The problem is if you use a repeat to loop trough the answers the enum list wil be dublicated if you have multiple answers (see below)
[ ] option1<br>
[x] option2<br>
[ ] option3<br>
[ ] option1<br>
[ ] option2<br>
[x] option3<br>
What I need is this:
[ ] option1<br>
[x] option2<br>
[X] option3<br>
HTML:
<div ng-repeat="(key, answer) in somevalue.EnumValue.SomeEnum">
<div ng-if="key==somevalue.AnswerValue">
<input type="checkbox" ng-checked="true">{{answer}}<br>
</div>
<div ng-if="key!=somevalue.AnswerValue">
<input type="checkbox">{{answer}}<br>
</div>
</div>
What I need is a generic solution because the questions have different sets of enums values the sub questions (within one question) have the same set of enum values
When using ng-repeat, you can use the unique filter to avoid duplicates:
<div ng-repeat="(key, answer) in somevalue.EnumValue.SomeEnum | unique: 'answer'">
...
</div>
so what I want to accomplish is populating a select element with a recurisve json, like so:
[{
"siteId": 1,
"name": "Test 1",
"siteTypeId": 2,
"childSites": [
{
"siteId": 3,
"name": "Test 3",
"siteTypeId": 2,
"childSites": [
{
"siteId": 2,
"name": "Test 2",
"siteTypeId": 2,
"childSites": []
}
]
},
{
"siteId": 4,
"name": "Test 4",
"siteTypeId": 2,
"childSites": []
}
]
}]
I found two ways I could approach this, either converting the structred object into a flat array, and then using ngOptions, or using the following code (which include ng-repeat with a custom template)
<script type="text/ng-template" id="sites-template">
<!--The object itself-->
<option>{{item.name}}</option>
<!--child items (if any), recursive call -->
<div ng-if="item.childSites && item.childSites.length > 0"
ng-repeat="item in item.childSites"
ng-include="sites-template">
</div>
</script>
<select class="selectpicker" data-live-search="true">
<div ng-repeat="site in sites" ng-include="sites-template"></div>
</select>
But when I run it with the json supplied above, it result with an empty select, can anyone explain why does it happen? I guess the correct solution would be to flattend the structured object, but I'm curious...
It seems that applying ng-repeat on an element inside a select tag, the child of the element would not recieve the value (when I removed the select tag it worked, as well of removing the wrapper and applying the ng-repeat straight on the option element, without the template), why is that?
Thanks.
The Json structure,
[
{
"name": "module1",
"categories": [
{
"name": "cat1"
},
{
"name": "cat4"
}
]
},
{
"name": "module2",
"categories": [
{
"name": "cat3"
},
{
"name": "cat4"
}
]
},
{
"name": "module3",
"categories": [
{
"name": "cat1"
},
{
"name": "cat2"
},
{
"name": "cat4"
}
]
}
]
Using this Json structure, I need to display a grid of checkboxes as follows,
On click of any checkbox, I should be able to alert the corresponding category & module name. If each module has all four categories then I can easily use nested ng-repeat and display the structure (You can check it here. ). But here the number of categories differs for each module. Could you please suggest a way to implement this functionality?
Need to find the number of categories first and display it as the headers in the table
Display checkbox exactly at the right place
It is possible to have an ng-repeat iterate over the result of a function - in contrast to an array field in the scope - like this:
<tr ng-repeat="module in getAllModules()">
<td ng-repeat="cat in getAllCategories()">
<!-- display checkbox here if required -->
</td>
</tr>
I think it should be clear how to implement the two methods. However, you have to consider the performance overhead involved because the total set of modules and categories is calculated over and over again.
I think lex answer is corrrect. If I understood his solution right,the getAllCategories method is the interesting part. It has to return ALL categories, while getAllModules can still return your modules Array.
<tr ng-repeat="module in modules">
<td ng-repeat="cat in getAllCategories()">
<input type="check" ng-if="module.containsCat(cat)">
</td>
</tr>
with the containsCat method being something like
$scope.containsCat = function(module, cat){
for each(var moduleCat in module.categories ){
if(moduleCat.name === cat) return true;
}
return false;
}
I am back with new question and looking for expert help once again!
In my Polymer 0.5 project I had a JSON array passed to a property like this:
<horizontal-barset max="3320000" data='[
{"title": "Annuals", "prevord": "1-15-2015",
"ds": [
{"subhead": "Last Year Sales", "value": "2960000", "className" : "last-year"},
{"subhead": "YTD", "value": "1956000", "className" : "ytd"},
{"subhead": "Previous Order", "value": "480000", "className" : "prev-order"}
]
},
{"title": "Perennials", "prevord": "1-15-2015",
"ds": [
{"subhead": "Last Year", "value": "540000", "className" : "last-year"},
{"subhead": "YTD", "value": "2140000", "className" : "ytd"},
{"subhead": "Previous Order", "value": "320000", "className" : "prev-order"}
]
},
{"title": "Totals", "prevord": "1-15-2015",
"ds": [
{"subhead": "Last Year", "value": "3320000", "className" : "last-year"},
{"subhead": "YTD", "value": "1350000", "className" : "ytd"},
{"subhead": "Previous Order", "value": "1700000", "className" : "prev-order"}
]
}
]'>
</horizontal-barset>
and in the element I initialized the empty array inside created like this:
created: function(){
this.data=[];
}
With Polymer 1.0 the properties are now written in a different approach:
properties: {
max: {type: String},
data: [] //(not sure this is the corrent approach! I also tried data: Object)
}
Then like 0.5 I tried initialize the empty object in the similar fashion, but getting data is undefined (please see the attached screenshot) error in JavaScript console.
Here is the snippet I am using to initialize the JSON array:
created: function(){
this.data = [];
}
The iteration is written inside the element like this:
<template is="dom-repeat" items="{{data}}">
<div class="rack-container">
<p>{{item.title}}</p>
<template is="dom-repeat" items="{{item.ds}}">
<div class="rack">
<div class="rack-bar">
<div class="rack-head">
{{item.subhead}}
</div>
<!--<span style="width:{{ (row.value / max) * 100}}%;line-height:2em;" class="{{row.className}} rack-fill"> </span>-->
<div class="clear"></div>
</div>
<div class="rack-value">{{item.value}}</div>
<div class="clear"></div>
</div>
</template>
</div>
</template>
How can I accomplish this?
You're actually on the right track! Here's how you can declare an array property:
properties: {
max: {type: String},
data: {
type: Array, // Available property types are String, Number, Boolean, Array, and Object
value: function () { return []; } // Default value
}
}
On your data-binding template however, you have to make sure that there are no whitespace inside the tag. Basically, you'll have to rewrite this lines
<div class="rack-head">
{{item.subhead}}
</div>
to this
<div class="rack-head">{{item.subhead}}</div>
Sources:
https://www.polymer-project.org/1.0/docs/devguide/properties.html#attribute-serialization
https://www.polymer-project.org/1.0/docs/devguide/data-binding.html#binding-to-text-content
I have a simple JSON object in my models
whitelist = [
{
"name": "Whitelist #1",
"permissions": [
"production_sdk",
"source_sdk",
"service"
],
},
{
"name": "Whitelist #2",
"permissions": [
"production_sdk",
"service"
],
},
{
"name": "Whitelist #3",
"permissions": [
"production_sdk",
"source_sdk"
],
}
]
In my html I have {{ whitelist.permissions }}, but the HTML displays the values with brackets - ['production_sdk', 'source_sdk'].
How can I display the HTML so that there are no brackets?
whitelist.permissions is an array, how do you want that to be displayed in your html? You should probably create a simple filter that takes an array and outputs what you want, but you could just change your html to do this to get a comma-separated list:
{{ whitelist.permissions.join(', ') }}
Another option, especially if you want to style each permission, is to use ng-repeat and html elements:
<span ng-repeat="permission in whitelist.permissions"><span ng-if="$index != 0">, </span>{{ permission }}</span>