|
@@ -62,14 +62,29 @@ const autoMeta = model => Object.entries(model)
|
|
|
// Combine automatically generated metadata with overrides
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
-const combineMetaForField = (metaF, extraMetaF) => Object.assign(metaF, extraMetaF);
|
|
|
-const combineExtraMeta = (metaG, extraMeta, createFromExtra = false) => {
|
|
|
+// metaGSeed = Metadata from group which seeds all fields contained in the group
|
|
|
+
|
|
|
+const combineMetaForField = (metaF, metaGSeed, extraMetaF) => Object.assign(metaF, metaGSeed, extraMetaF);
|
|
|
+const combineExtraMeta = (metaG, extraMeta, createFromExtra = false, metaGSeed = {}) => {
|
|
|
const combinedMeta = {};
|
|
|
Object.entries(extraMeta).forEach(([key, val]) => {
|
|
|
if (typeof metaG[key] === 'object' || createFromExtra) {
|
|
|
- combinedMeta[key] = metaG[key] && (<any>val).meta ?
|
|
|
- combineMetaForField(metaG[key], { ...val, meta: combineExtraMeta(metaG[key].meta, (<any>val).meta, createFromExtra) }) :
|
|
|
- combineMetaForField(metaG[key] || {}, val);
|
|
|
+ const isCon = isContainer(val);
|
|
|
+ const metaFoG = metaG[key] || {};
|
|
|
+ const seed = isCon ? {} : metaGSeed;
|
|
|
+ const extra = isCon ?
|
|
|
+ {
|
|
|
+ ...val,
|
|
|
+ meta: combineExtraMeta(
|
|
|
+ metaFoG.meta || {},
|
|
|
+ val['meta'],
|
|
|
+ createFromExtra,
|
|
|
+ val['seed'] || metaGSeed // Inherit seeded data if this group's seed isn't set
|
|
|
+ )
|
|
|
+ }
|
|
|
+ :
|
|
|
+ val;
|
|
|
+ combinedMeta[key] = combineMetaForField(metaFoG, seed, extra);
|
|
|
}
|
|
|
});
|
|
|
return { ...metaG, ...combinedMeta };
|
|
@@ -131,7 +146,7 @@ const prependParentPathRecursive = (parentPath: string, obj: StringMap) => {
|
|
|
return Object.entries(obj)
|
|
|
.map( ([key, mapping] ) => {
|
|
|
let mappingRes;
|
|
|
- switch(typeof mapping) {
|
|
|
+ switch (typeof mapping) {
|
|
|
case 'string':
|
|
|
mappingRes = processPath(parentPath, mapping);
|
|
|
break;
|
|
@@ -146,14 +161,14 @@ const prependParentPathRecursive = (parentPath: string, obj: StringMap) => {
|
|
|
mappingRes = [source, ...mapping];
|
|
|
}
|
|
|
} else {
|
|
|
- mappingRes = prependParentPathRecursive(parentPath, mapping)
|
|
|
+ mappingRes = prependParentPathRecursive(parentPath, mapping);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
return [key, mappingRes];
|
|
|
})
|
|
|
.reduce((acc, [key, val]) => addProp(acc, key, val), {});
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
const _extractFieldMapping = ( [key, metaFoG] ) => {
|
|
|
let source;
|
|
@@ -173,14 +188,14 @@ const _extractFieldMapping = ( [key, metaFoG] ) => {
|
|
|
const extractFieldMappings = (metaG, parentPath = '') => Object.entries(metaG)
|
|
|
.map(_extractFieldMapping)
|
|
|
.reduce((res, [key, mapping]) => {
|
|
|
-
|
|
|
+
|
|
|
// Work out the path prefix
|
|
|
let prefix;
|
|
|
if (parentPath) {
|
|
|
if (isRootPath(parentPath) || isAbsPath(metaG[key].source) || Array.isArray(parentPath)) {
|
|
|
- // If the parentPath is the root of the data structure, or the source is an absolute path or functional datasource,
|
|
|
- // then there's no path prefix
|
|
|
- prefix = ''
|
|
|
+ // If the parentPath is the root of the data structure, or the source is an absolute path or functional datasource,
|
|
|
+ // then there's no path prefix
|
|
|
+ prefix = '';
|
|
|
} else {
|
|
|
// Otherwise create a prefix from the parentPath
|
|
|
prefix = parentPath ? (parentPath[0] === '/' ? parentPath.slice(1) : parentPath) : '';
|
|
@@ -231,11 +246,11 @@ const extractFieldMappings = (metaG, parentPath = '') => Object.entries(metaG)
|
|
|
mappingRes = prependParentPathRecursive(prefix, mapping);
|
|
|
|
|
|
} else {
|
|
|
-
|
|
|
+
|
|
|
mappingRes = mapping;
|
|
|
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return addProp(res, key, mappingRes);
|
|
|
}, {});
|
|
|
|
|
@@ -254,7 +269,8 @@ const buildFormGroupFunctionFactory = (fb: FormBuilder): (meta) => FormGroup =>
|
|
|
const buildValidators = (metaF): AbstractControlOptions => ({
|
|
|
validators: metaF.validators,
|
|
|
asyncValidators: metaF.asyncValidators,
|
|
|
- updateOn: metaF.type === 'text' || metaF.type === 'textarea' ? 'blur' : 'change' // blur not working for custom components, so use change for custom and blur for text
|
|
|
+ // blur not working for custom components, so use change for custom and blur for text
|
|
|
+ updateOn: metaF.type === 'text' || metaF.type === 'textarea' ? 'blur' : 'change'
|
|
|
});
|
|
|
const buildFormControl = metaF => new FormControl(buildControlState(metaF), buildValidators(metaF));
|
|
|
|
|
@@ -266,7 +282,9 @@ const buildFormGroupFunctionFactory = (fb: FormBuilder): (meta) => FormGroup =>
|
|
|
(isArray(metaFoG.meta) ? buildFormArray(metaFoG.meta) : _buildFormGroup(metaFoG.meta)) :
|
|
|
buildFormControl(metaFoG);
|
|
|
|
|
|
- const buildFormGroupReducerIteree = (res, metaFoG) => metaFoG.noFormControls ? res : Object.assign(res, { [metaFoG.name]: buildFormGroupMember(metaFoG) });
|
|
|
+ const buildFormGroupReducerIteree = (res, metaFoG) => {
|
|
|
+ return metaFoG.noFormControls ? res : Object.assign(res, { [metaFoG.name]: buildFormGroupMember(metaFoG) });
|
|
|
+ };
|
|
|
const _buildFormGroup = _metaG => fb.group(reduce(buildFormGroupReducerIteree, {}, _metaG));
|
|
|
|
|
|
// The main function - builds FormGroups containing other FormGroups, FormArrays and FormControls
|
|
@@ -300,17 +318,17 @@ const objConcat = (obj, pos, key, val = null) => {
|
|
|
delete start[key];
|
|
|
delete finish[key];
|
|
|
return { ...start, [key]: val, ...finish };
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
const insertBefore = (obj, beforeKey, key, val = null) => {
|
|
|
const targetPosition = Object.keys(obj).indexOf(beforeKey);
|
|
|
return objConcat(obj, targetPosition, key, val);
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
const insertAfter = (obj, afterKey, key, val = null) => {
|
|
|
const targetPosition = Object.keys(obj).indexOf(afterKey) + 1;
|
|
|
return objConcat(obj, targetPosition, key, val);
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
// Process reordeing instructions recursively
|
|
|
const _execMetaReorderingInstructions = (metaG: StringMap) => {
|
|
@@ -326,11 +344,11 @@ const _execMetaReorderingInstructions = (metaG: StringMap) => {
|
|
|
}
|
|
|
});
|
|
|
return reorderedGroup;
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
const execMetaReorderingInstructions = (metaG: StringMap) => {
|
|
|
return _execMetaReorderingInstructions(cloneDeep(metaG));
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
@@ -340,7 +358,7 @@ const execMetaReorderingInstructions = (metaG: StringMap) => {
|
|
|
|
|
|
const generateNewModel = (originalModel, updates) => {
|
|
|
return updateObject(originalModel, updates);
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
const updateObject = (obj, updates, createAdditionalKeys = false) => {
|
|
|
// THIS DOES NOT MUTATE obj, instead returning a new object
|
|
@@ -354,7 +372,7 @@ const safeSet = (obj, key, val, createAdditionalKeys = false) => {
|
|
|
if (!createAdditionalKeys && !obj.hasOwnProperty(key)) {
|
|
|
return;
|
|
|
}
|
|
|
- let currentVal = obj[key];
|
|
|
+ const currentVal = obj[key];
|
|
|
if (val === currentVal) {
|
|
|
return;
|
|
|
}
|
|
@@ -380,13 +398,13 @@ const safeSet = (obj, key, val, createAdditionalKeys = false) => {
|
|
|
Rejected update was ${val}`);
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
const nullOrScaler = val => {
|
|
|
- if (val === null) return true;
|
|
|
+ if (val === null) { return true; }
|
|
|
const t = typeof val;
|
|
|
return t === 'number' || t === 'string' || t === 'boolean';
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
@@ -436,7 +454,7 @@ const addMissingFieldSpecificMeta = metaG => Object.entries(metaG)
|
|
|
// Exports
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
-export {
|
|
|
+export {
|
|
|
autoMeta, combineModelWithMeta, combineExtraMeta, execMetaReorderingInstructions,
|
|
|
buildFieldSpecificMeta, extractFieldMappings, buildFormGroupFunctionFactory,
|
|
|
generateNewModel
|