Skip to content

Commit f5ab943

Browse files
committed
Two way binding for checkboxes
fixes #25, fixes #30
1 parent c6ff6e0 commit f5ab943

File tree

3 files changed

+71
-13
lines changed

3 files changed

+71
-13
lines changed

examples/data/titlemaps.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
2+
"model": {
3+
"select": "a",
4+
"array": ["b"]
5+
},
26
"schema": {
37
"type": "object",
48
"properties": {
@@ -24,6 +28,7 @@
2428
"array2": {
2529
"title": "Array with titleMap",
2630
"type": "array",
31+
"default": ["b","c"],
2732
"items": {
2833
"type": "string",
2934
"enum": ["a","b","c"]

src/directives/array.js

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,17 @@ function(sfSelect, schemaForm) {
3636
}
3737
scope.modelArray = list;
3838

39-
// To be more compatible with JSON Form we support an array of items
40-
// in the form definition of "array" (the schema just a value).
41-
// for the subforms code to work this means we wrap everything in a
42-
// section. Unless there is just one.
43-
var subForm = form.items[0];
44-
if (form.items.length > 1) {
45-
subForm = { type: 'section', items: form.items };
39+
// Arrays with titleMaps, i.e. checkboxes doesn't have items.
40+
if (form.items) {
41+
42+
// To be more compatible with JSON Form we support an array of items
43+
// in the form definition of "array" (the schema just a value).
44+
// for the subforms code to work this means we wrap everything in a
45+
// section. Unless there is just one.
46+
var subForm = form.items[0];
47+
if (form.items.length > 1) {
48+
subForm = { type: 'section', items: form.items };
49+
}
4650
}
4751

4852
// We ceate copies of the form on demand, caching them for
@@ -88,10 +92,60 @@ function(sfSelect, schemaForm) {
8892
};
8993

9094
// Always start with one empty form unless configured otherwise.
91-
if (form.startEmpty !== true && list.length === 0) {
95+
// Special case: don't do it if form has a titleMap
96+
if (!form.titleMap && form.startEmpty !== true && list.length === 0) {
9297
scope.appendToArray();
9398
}
9499

100+
// Title Map handling
101+
// If form has a titleMap configured we'd like to enable looping over
102+
// titleMap instead of modelArray, this is used for intance in
103+
// checkboxes. So instead of variable number of things we like to create
104+
// a array value from a subset of values in the titleMap.
105+
// The problem here is that ng-model on a checkbox doesn't really map to
106+
// a list of values. This is here to fix that.
107+
if (form.titleMap && form.titleMap.length > 0) {
108+
scope.titleMapValues = [];
109+
110+
111+
112+
113+
// We watch the model for changes and the titleMapValues to reflect
114+
// the modelArray
115+
var updateTitleMapValues = function(arr) {
116+
scope.titleMapValues = [];
117+
arr = arr || [];
118+
119+
form.titleMap.forEach(function(item) {
120+
scope.titleMapValues.push( arr.indexOf(item.value) !== -1 );
121+
});
122+
123+
};
124+
//Catch default values
125+
updateTitleMapValues(scope.modelArray);
126+
scope.$watchCollection('modelArray',updateTitleMapValues);
127+
128+
//To get two way binding we also watch our titleMapValues
129+
scope.$watchCollection('titleMapValues', function(vals) {
130+
if (vals) {
131+
var arr = scope.modelArray;
132+
133+
// Apparently the fastest way to clear an array, readable too.
134+
// http://jsperf.com/array-destroy/32
135+
while (arr.length > 0) {
136+
arr.shift();
137+
}
138+
139+
form.titleMap.forEach(function(item,index) {
140+
if (vals[index]) {
141+
arr.push(item.value);
142+
}
143+
});
144+
145+
}
146+
});
147+
}
148+
95149
once();
96150
});
97151
}

src/directives/decorators/bootstrap/checkboxes.html

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
<div class="form-group" ng-class="{'has-error': hasError(), 'has-success': hasSuccess()}" ng-init="checkboxValues = listToCheckboxValues($$value$$)">
1+
<div sf-array="form" class="form-group" ng-class="{'has-error': hasError(), 'has-success': hasSuccess()}">
22
<label ng-show="showTitle()">{{form.title}}</label>
3-
<div class="checkbox" ng-repeat="item in form.titleMap" >
3+
<div class="checkbox" ng-repeat="val in titleMapValues track by $index" >
44
<label>
55
<input type="checkbox"
66
sf-changed="form"
7-
ng-model="checkboxValues[item.value]"
8-
ng-change="$$value$$ = checkboxValuesToList(checkboxValues)" >
9-
<span ng-bind-html="item.name"></span>
7+
ng-model="titleMapValues[$index]">
8+
<span ng-bind-html="form.titleMap[$index].name"></span>
109
</label>
1110

1211
</div>

0 commit comments

Comments
 (0)