Skip to content

Commit c26b82e

Browse files
committed
Merge branch 'array' of https://github.com/EagerIO/angular-schema-form into EagerIO-array
Conflicts: dist/bootstrap-decorator.min.js
2 parents c7a0983 + 7f74179 commit c26b82e

File tree

8 files changed

+161
-5
lines changed

8 files changed

+161
-5
lines changed

dist/bootstrap-decorator.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/schema-form.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/directives/decorators/bootstrap/bootstrap-decorator.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ angular.module('schemaForm').config(['schemaFormDecoratorsProvider',function(dec
44
decoratorsProvider.createDecorator('bootstrapDecorator',{
55
textarea: base+'textarea.html',
66
fieldset: base+'fieldset.html',
7+
list: base+'list.html',
78
tabs: base+'tabs.html',
89
section: base+'section.html',
910
conditional: base+'section.html',
@@ -54,4 +55,125 @@ angular.module('schemaForm').config(['schemaFormDecoratorsProvider',function(dec
5455
scope.title = scope.$eval(attrs.title);
5556
}
5657
};
58+
}).directive('sfList',function(){
59+
return {
60+
templateUrl: 'directives/decorators/bootstrap/list-body.html',
61+
62+
link: function(scope,element,attrs) {
63+
var key = scope.form.items.key;
64+
var value = getNested(scope.model, key) || [];
65+
setNested(scope.model, key, value);
66+
67+
scope.value = value;
68+
scope.renderedValue = angular.copy(scope.value);
69+
70+
var storedValue = null;
71+
scope.$on('change', function(evt, val){
72+
var index = findElement(element[0], val.element[0]);
73+
74+
if (index == -1){
75+
// The add input
76+
storedValue = val.value;
77+
} else {
78+
scope.value[index] = val.value;
79+
setNested(scope.model, key, scope.value);
80+
}
81+
});
82+
83+
scope.$on('remove', function(evt, val){
84+
var index = findElement(element[0], val.element[0]);
85+
86+
scope.renderedValue.splice(index, 1);
87+
88+
scope.value.splice(index, 1);
89+
setNested(scope.model, key, scope.value);
90+
val.element[0].parentNode.removeChild(val.element[0]);
91+
});
92+
93+
scope.add = function(){
94+
scope.renderedValue.push(storedValue);
95+
96+
scope.value.push(storedValue);
97+
setNested(scope.model, key, scope.value);
98+
99+
scope.$broadcast('add');
100+
};
101+
}
102+
}
103+
}).directive('sfListItem',function(){
104+
return {
105+
scope: {
106+
'form': '=',
107+
'value': '=',
108+
'newEntry': '@'
109+
},
110+
111+
templateUrl: 'directives/decorators/bootstrap/list-item.html',
112+
113+
link: function(scope,element,attrs) {
114+
var initialValue = angular.copy(scope.value);
115+
116+
scope.form.items.key = 'value';
117+
scope.model = {
118+
value: scope.value
119+
};
120+
121+
scope.$watch('model', function(val){
122+
scope.$emit('change', {
123+
value: val.value,
124+
element: element
125+
});
126+
}, true);
127+
128+
129+
scope.$on('add', function(){
130+
if (scope.newEntry){
131+
scope.model.value = initialValue;
132+
}
133+
});
134+
135+
scope.remove = function() {
136+
scope.$emit('remove', {
137+
element: element
138+
});
139+
};
140+
}
141+
}
57142
});
143+
144+
function findElement(parentEl, element){
145+
var els = parentEl.querySelectorAll('[sf-list-item]');
146+
for (var i=0; i < els.length; i++){
147+
if (els[i].isEqualNode(element)){
148+
if (els[i].tagName === 'DIV'){
149+
return -1;
150+
} else {
151+
return i;
152+
}
153+
}
154+
}
155+
}
156+
157+
function setNested(obj, key, value){
158+
var bits = key.split('.');
159+
for (var i=0; i < bits.length - 1; i++){
160+
if (!obj[bits[i]])
161+
obj[bits[i]] = {};
162+
163+
obj = obj[bits[i]];
164+
}
165+
166+
obj[bits[bits.length - 1]] = value;
167+
}
168+
169+
function getNested(obj, key){
170+
var bits = key.split('.');
171+
for (var i=0; i < bits.length; i++){
172+
obj = obj[bits[i]];
173+
174+
if (!obj){
175+
return undefined;
176+
}
177+
}
178+
return obj;
179+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<ul>
2+
<li ng-repeat="val in renderedValue" sf-list-item value="val" form="form"></li>
3+
</ul>
4+
5+
<div sf-list-item form="form" new-entry="true"></div>
6+
<a href ng-click="add()">Add</a>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div>
2+
<sf-decorator form="form.items"></sf-decorator>
3+
<a href ng-click="remove()" ng-if="!newEntry">Remove</a>
4+
</div>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<h3 ng-show="form.title">{{ form.title }}</h3>
2+
<div sf-list></div>

src/directives/schema-form.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ function($compile, schemaForm, schemaFormDecorators){
108108
traverse(schema,function(prop,path){
109109
//This is probably not so fast, but a simple solution.
110110
if (angular.isDefined(prop['default'])) {
111-
scope.$eval('model.'+path+' = model.'+path+' || defaltValue',{ defaltValue: prop['default']});
111+
scope.$eval('model.'+path+' = model.'+path+' || defaultValue',{ defaultValue: prop['default']});
112112
}
113113
});
114114

src/services/schema-form.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,37 @@ angular.module('schemaForm').provider('schemaForm',[function(){
148148

149149
};
150150

151+
var list = function(name,schema,options){
152+
153+
if (schema.type === "array") {
154+
var f = stdFormObj(schema,options);
155+
f.type = 'list';
156+
f.key = options.path;
157+
options.lookup[options.path] = f;
158+
159+
var required = schema.required && schema.required.indexOf(options.path) !== -1;
160+
161+
f.items = defaultFormDefinition(options.path,schema.items,{
162+
path: options.path,
163+
required: required || false,
164+
lookup: options.lookup,
165+
ignore: options.ignore
166+
});
167+
168+
return f
169+
}
170+
171+
};
172+
151173
//First sorted by schema type then a list.
152174
//Order has importance. First handler returning an form snippet will be used.
153175
var defaults = {
154176
string: [ select, text ],
155-
object: [ fieldset],
177+
object: [ fieldset ],
156178
number: [ number ],
157179
integer: [ integer ],
158180
boolean: [ checkbox ],
159-
array: [ checkboxes ]
181+
array: [ checkboxes, list ]
160182
};
161183

162184
var postProcessFn = function(form) { return form; };

0 commit comments

Comments
 (0)