I'm building a webapp that requires an ever-growing collection of forms. Formly seems to be an excellent tool to do this because it's declarative and reusable. However, placing formly field config files in the same project, even on a separate module, means that for every new form or every small changes to the form, the project has to be build and deployed again, or at least that's what I've been doing so far.
An ideal solution would have these conditions:
- Code separation between the main webapp and the forms, so it can be managed separately. Currently I have separated the forms (configs, components, and custom fields) into a separate angular module, in the same project.
- As close to zero downtime as possible. Updating forms or adding new forms should be very easy and quick. JSON/JSON Schema powered forms might be plausible with some limitations. I've experimented a bit with transpiling and dynamically importing .ts form files with no luck so far.
- Reusable and Nest-able. It's great to have let say an
Addressform (which includes address, postal code, city, state/province, etc), so whenever I need a fullAddressform I can just call and insert into afieldGroupsomewhere.
Possible solutions that I've tried:
- Create a separate server/service that generate a full form FormlyFieldConfig object based on multiple nested forms, for example a
Userform would haveusername,password,Personfields containing personal information, andAddressfields like in condition 3 above. The problem with this approach is that sending functions (such asonInitinhooks) as a string through http response doesn't seem like a good idea. - Storing forms in JSON/JSON Schema. There's 2 problems with this approach. First, I'm not sure how to nest forms from multiple
.jsonfiles. Second, it's not even possible to store functions in JSON so I have to rely entirely on formly'sexpression. - Sending/requesting form
.tsfiles on demand, transpiling and running them when needed. I've researched and triedeval()andimport(). It works when the form files is in the same project, which doesn't satisfy the 2nd condition, so importing files (modules) from remote location doesn't seem to be possible. - Separating the forms to a separate library. But, when I update the library, I'd have to do
npm installandnpm buildon the project, unless I'm missing something.
Question: Is there a better way of doing this? Or do I miss/misunderstood something? Is it possible to do lazy loading, but the module is on for example a CDN?
EDIT:
I found out how to convert functions to string and vice versa
export const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
if(typeof value === "function") {
return value.toString();
}
return value;
};
};
then,
JSON.stringify(formlyFieldConfigs, getCircularReplacer())
and to convert back to object
export const getReviver = (_this, ...params) => {
return (key, value) => {
if(key == "hooks") {
let hooks = {};
Object.keys(value).forEach(hookKey => {
hooks[hookKey] = eval(value[hookKey]);
});
return hooks;
}
if(value.templateOptions != null) {
if(value.templateOptions.optionsFunctionName) {
let functionName = value.templateOptions.optionsFunctionName;
value.templateOptions.options = _this[functionName](params);
}
}
return value;
}
};
basically it's using eval() and this.[functionName](params) pattern, then call,
JSON.parse(string, getReviver(this))
But sending functions over string still doesn't seem like the right approach.