I am into development since 2 years and pretty good with core concepts - however, recently started working on Angular and have a form to create using it. For which, I am using FormBuilder
FormControl
etc. My concern though, is, how to organize components and services.
About the Form
The form has 5 pages in total - each having a bunch of different kind of options and types of form inputs like text, date picking, numbers etc. Putting it in simple words - the user will have to select product A, B, C, D or E. which should then accordingly render the rest of the 4 pages in form. The 4 pages in form will have different questions - where a super set of questions can be created and then each of the question should be toggled on or off.
Design Dilemma
Determining which question to be shown as per the Form type selected. My thought is, we can create a typeDetails.json
(or a Service?) which would look like
`{"A": {Q1 : true, Q2 : false}}`
we can then fetch the boolean and decide whether to show a question or not. Now, talking about the form itself, I started with creating different components for different pages and then working in each of the templates. But I realised, I'd end up using ngIf
blocks inside .html
which would make HTML dirty. Then, I thought of creating a different component for each question and then using those components to create page component and having a single HTML for that. But I feel then, I would have lotsss of components for just a form.
So should I create 5 components, one for each page? or should I create one component for each question and then combine them accordingly? or something else? also, can there be any other approach other than creating a typeDetails.json
?
Any help is appreciated! and any direction towards resources is too!
Love you guys
CodePudding user response:
Before reading out my answer, please keep in mind that this is totally from my point of view and the level of understanding of your scenario. There can be better solutions too.
I would always look into reusing a piece of code so that I adhere to the DRY principles. But it does not have to be this way, some might prefer having 5 different components to make use of the Single Responsibility principle.
Therefore, I would suggest to create one shared component that contains a ng-switch and renders based on the type of the element. Assume that you have 10 questions in your first form and there are different type of questions. For example:
- Q1: Text field
- Q2: Drop Down
- Q3: Multi Text . . .
and so on.
Now all you need to do is create a dynamic form based on the form (page) and the question. Then you will need to loop through the dataset and dynamically render the html for each input type. I found a great blog on this, have a look https://codeburst.io/angular-dynamic-forms-ng-switch-approach-4f267c01d2c6
Using the methodology, you will have one shared component for all the 5 forms. In future, if you need to add another page, you can just re-use this component and do not have to worry about creating another component which will have the same logic as the previous components created.
Do let me know if I can improve in any way. I am all ears to feedbacks :D
CodePudding user response:
Very hard to judge this without a view on the actual code and business logic, but in general for relatively complex forms like this, I would:
- Create 1 general component for the form which encompasses multiple sub-components.
- Group the questions into sub-components based on the business logic. For example, in a checkout flow, this would mean having a separate sub-component for order confirmation, shipping, payment, post-payment ...
- The data that the sub-components rely upon should be passed to them as asynchronous (read: observables combined with the
async
pipe) input values as much as possible. This will help in keeping the different sub-components testable independently from one another, as you can just stub the input values. - Use
EventEmitter
to emit data back to the main component when a particular group of questions inside a sub-component has been completed. This also makes the sub-components testable independently, as you can then just test per sub-component if the expected values are emitted upon completion. - When an event emission from one of the sub-components is observed in the main component, process that data and emit relevant values to the streams which are used as inputs for the other sub-components.
If you can come up with some more details on the code or the business logic itself, we could try to clarify this a bit more if you like.