Angular formly :

storing fields model into database
 14 June 2015

Before going further, be sure to have a minimum knowledge of this nice and powerful angular formly. If you are a newcomer to angular formly world, I suggest you take at least a bit of time on official website : here Angular formly official website link with tons of examples.

I will here mainly share my experience on how I overcomed an issue on which I did not find any answser.

I'm currently developing a personal project where, as one of functionalities, I want user to be able to design fonctional and stunning forms without development requirement. Here comes angular formly. Depites it does not come with a form builder it is by far the most flexible (my point of view based on my long researches). In my case, I use formly boostrap template and I wanted to be able to generate N columns forms (advanced layout). If you have a look on other equivalent librairies you will see that you won't be able to create N columns template forms.

If you are in a hurry and want to skip angular presentation (click/tap here)


angular formly overview :

If you don't already know angular formly you ask yourself this simple question :

 What is angular formly? 

Let me illustrate with the example from angular formly official website.

Regular Bootstrap html :

Exactly the same as above but formly way :

Magic comes from an angular model :

 Your form will be defined in model : userFields

 All input value will be bound into model : user

 Isn't it nice? 

Now an example of my own implementation :

Previous example used basic stuffs available with formly but with not so much efforts you can define your own template. For instance, you want to integrate this nice textAngular in your formly model. In fact, there are infinite possbilities you will just be limited by your own imagination (so your margin is wide enough).

 

 

Here is my userFields model that did the magic :

 This model was generated by my own form generator. I won't discuss it now. It is just a functionality of my personal project I talked about in the introduction. I plan to give an overview of it later. Right now I have to focus the entire project and finish it.

I fastly created this tip page (and interrupt briefly my project) since I discovered I was not alone to struggle in finding a nice way to be able to save formly model to database. I hope I will save time to others who may encounter same difficulties.

By the way, thank you Kent C. Dodds (who maintains angular formly) for being so active and replying so fast. It gives even more value to use angular formly.


That being said, let's go deeper in the main subject :

You may notice that until now we did not talk about the main subject : saving model to mongoDB or any database.

In fact, we introduced or refreshed (if you already know it well) angular formly concepts so that you will better understand where is the problem when saving to database.

 

 Ok, angular formly seems nice but what's the problem saving fields model? 

If you have a fixed predefine form (so userField model) or an amount of fixed predefine forms

 You could create a database model related to your fixed form or forms...

 But I strongly warn you not to go (whenever possible) that (fake) easy way since you may have more troubles later and it may be painful to maintain.

You may develop your own form generator or plan to create dynamic forms (so userField model)

 You can't rely on finite models to save to database.

 Solution will be to store the model as a string

Before sending model to serveur for storing it, you can simply JSON.stringify it.

BUT...

you may soon face this error : TypeError: Converting circular structure to JSON


Don't give up solution is just nearby

Solution will be to JSON.stringify fields model. So storing will be easy task in any database and reading from database will just need a JSON.parse.

But like that you can't JSON.stringify.

 Wait! JSON.stringify should work look at the upper models. What is wrong? 

If you have a look on my model vm.myCustomFields above you can't see why converting circular structure occurs. In fact this model is the one I initiated in my angular controller and after it is bound in formly it will be a little changed (don't forget angular js is double data binding).

 

Before illustrating I give you the trick to make it :

 separate presentation model (here will be called "myCustomFields") from data or backgroundModel (here will be called "userFieldBackData") 

Now suppose you already did the trick, time for illustration!

Compare at least first item array between userFieldBackData and myCustomFields :

fields model changed by formly directive

 

 My first item in model array is template where I defined some html to make it rendered as an header.

$scope.userFieldBackData :

This model is the one angular controller works with (add, edit, save database after JSON.stringify, read database after JSON.parse...).

Angular formly directive does not even know this model exists, so it has no impact on it.

This model contains only needed properties.

Asynchronous operations on this model will not impact the page presentation.

$scope.vm.myCustomFields :

This model is bound to formly directive in the view (or html).

This model is refreshed by angular.copy($scope.userFieldBackData) when needed.

Angular formly directive add a lot of properties (we don't need and that can make JSON.stringify error) to this model. Even if we had no error, we would waste bytes by storing this model with so much no use (for us not for anglar formly) properties.

 Now you see clearer that JSON.stringify error comes from formly directive added properties (for itself behaviours and rendering).

 It is not a bug, formly needs them to do its job. It is just up to us to save only what we really need rather all fields model.


On conclusion let's sum up all of this :

 First and most important : separate you presentation fields model from the one you work with in your controller.

 to save to database, JSON.stringify(__YOUR WORKING FIELDS MODEL__) only your working fields model (not the one that is bound to formly directive).

 to read from database, JSON.parse(__YOUR WORKING FIELDS MODEL__) and refresh your presentation model with __YOUR PRESENTATION FIELDS MODEL__ = angular.copy(__YOUR WORKING FIELDS MODEL__).

 Concerning data model, you may have no difficulties to manage it. Data model properties are fully related to your fields model that you defined.