-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathauto-formly.js
More file actions
199 lines (170 loc) · 5.94 KB
/
auto-formly.js
File metadata and controls
199 lines (170 loc) · 5.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/* global autoFormlyHelpers */
let {SetModule, Service, Inject} = angular2now;
SetModule('autoFormly');
@Service('autoFormly')
@Inject(['autoFormlyParser'])
/**
* AngularJS Service
* @property autoFormly
* @public
*/
class autoFormly extends autoFormlyHelpers {
// injectables
autoFormlyParser;
constructor(autoFormlyParser) {
super();
this.autoFormlyParser = autoFormlyParser;
}
/**
* Parse Mongo.Collection object
*
* @public
* @method autoFormly.collection
* @param {Collection|AngularMeteorCollection} collection - used directly or with $meteor service
* @param {array|object} options - schema keys you want to use or formly fields configuration (optional)
* @returns {array}
*/
collection(collection, options) {
if (!this.isCollection(collection) && !this.isAngularMeteorCollection(collection)) {
throw this.createError("Collection is not extended by Collection2");
}
let schema = this.getSchema(this.getCollection(collection));
if (!schema) {
throw this.createError("Collection has no schema");
}
return this.schema(schema, options);
}
/**
* Parse SchemaSchema object
*
* @public
* @method autoFormly.schema
* @param {SimpleSchema} schema
* @param {array|object} options - schema keys you want to use or formly fields configuration (optional)
* @returns {array}
*/
schema(schema, options) {
if (!this.isSchema(schema)) {
throw this.createError("Schema has to be instance of SimpleSchema");
}
let sortedSchema;
const schemaCopy = angular.copy(schema);
/**
* @deprecated avoid filtering with fields keys as array, use object configuration instead
*/
// filter and return
if (angular.isArray(options)) {
return this.fields(this.filterSchema(schemaCopy, options));
}
// no options
if (angular.isUndefined(options)) {
return this.fields(schemaCopy.schema());
}
//
// handle options object
//
// pass only object
if (!angular.isObject(options)) {
throw this.createError("Options have to be an array or object");
}
// use filter?
if (options.all === false) {
// pass only with defined fields
if (!angular.isObject(options.fields)) {
throw this.createError("Missing or invalid property fields in options");
}
// skip fields marked as unused ("fieldKey": false)
sortedSchema = this.filterSchema(schemaCopy, Object.keys(_.omit(options.fields, (val) => val === false)));
} else {
sortedSchema = schemaCopy.schema();
}
// check each field
if (options.fields) {
_.each(sortedSchema, (fSchema, fKey) => {
// and skip field if marked as unused
if (options.fields[fKey] === false) {
delete sortedSchema[fKey];
}
// or extend autoformly in schema using defined field extension
if (angular.isObject(options.fields[fKey])) {
sortedSchema[fKey].autoformly = angular.merge({}, fSchema.autoformly, options.fields[fKey]);
}
});
}
return this.fields(sortedSchema);
}
/**
* @param {object} schema
* @param {array} fields - schema keys you want to use (optional)
* @returns {object}
*/
filterSchema(schema, fields) {
if (!angular.isArray(fields)) {
throw this.createError("Fields to filter have to be an array");
}
const sorted = {};
fields.forEach((field) => {
if (!schema.schema(field)) {
throw this.createError(`There is no '${field}' in schema`);
}
sorted[field] = schema.schema(field);
});
return sorted;
}
/**
* @param {object} sortedSchema
* @returns {array}
*/
fields(sortedSchema) {
return this.autoFormlyParser.schema(sortedSchema);
}
/**
* Handle errors and set validity on fields
*
* @public
* @param {Collection|AngularMeteorCollection} collection
* @param {array} fields formly fields
* @param {string} context validation context
*/
errors(collection, fields, context) {
// get things
let col = this.getCollection(collection);
let schema = this.getSchema(collection);
// make sure fields variable is an array
if (!angular.isArray(fields)) {
throw this.createError("Missing or invalid fields");
}
// check collection
if (!col) {
throw this.createError("Collection is not extended by Collection2");
}
// check schema
if (!schema) {
throw this.createError("Collection has no schema");
}
// get keys with error types
const invalidKeys = schema.namedContext(context).invalidKeys();
// transform error type from SimpleSchema to autoFormly
const typeTransform = {
notUnique: "unique",
minString: "minlength",
maxString: "maxlength",
minNumber: "minnumber",
maxNumber: "maxnumber",
regEx: "pattern"
};
// go through errors
invalidKeys.forEach((key) => {
// match error with field object
let field = _.find(fields, (field) => field.key === key.name);
// if found
if (field) {
if (!field.formControl) {
throw this.createError(`Field "${field.key}" has no formControl`);
}
// and has formControl property
field.formControl.$setValidity(typeTransform[key.type] || key.type, false);
}
});
}
}