Design advice/Best practices for complex dynamic Ajax forms with many sections

Hi,

I was just hoping to get some broad design advice/best practice for a yii2 application I’m building. The application has forms that are huge but that can be split into many logical sections that also get re used in other forms. (e.g a person section gets used in numerous forms).

The frontend wanted by the client is a dynamically style that updates sections using Ajax, rather than a traditional single form that you enter all the fields and the have one Save button at the bottom. They want us to use the Adminlte theme. We want to use Ajax rather than pjax for form submission as pjax has limitations and seems to be getting phased out in yii3.

An example of an average form in the app is a “Job” form:

Job
People Details (create via Modal or lookup existing)

  • Person 1
  • Person 2
  • Person 3
  • Person 4
    any number of people*

Location Details (create via Modal or lookup existing)

  • Location 1
  • Location 2
    any number of locations

Groupings (assigns users to locations)

  • Group 1 (allows users to be assigned to group via some selector)
  • Group 2 (allows users to be assigned to group via some selector)
    any number of groups

Events

  • Event 1 details
  • Event 2 details
    any number of events

I know the above might be a bit vague but Im not looking for advice on database design, normalisation, relationships, etc. I have that sorted e.g there are seperate tables for each logical object e.g job, person, location, group, event, then user_group, etc with appropriate realtionships, keys, indexes, etc. Using gii I have created models, controllers & views for each object you see above. e.g there is a /person, /location, /group each with a create/update/view. All functioning independently.

I have learnt how to use Ajax Modal from some of the wiki entries. For example on the job page I have a “Add Person” button, that pops up a Modal, shows the person form (which is complex in its self, probably 30 fields with many lookups), save it and then the newly created person can be looked up.

I also have got the yii2 dynamic-form widget working so I can dynamically add extra records and submit multiple records if required. e.g I can add or remove Person’s on the job form.

But I keep vasciling on the best approach for an app like this…

First Question
So firstly what I would like to know is what you guys find is the best controller/view structure for something like this.

Option 1 - Single Controller
I’ve seen loads of examples that demonstrate creating multiple model controllers and forms. I understand how to do and started down this path but the controller is getting huge. I like how https://mrphp.com.au/blog/advanced-multi-model-forms-yii2/ creates sepearte models to get the logic out of the controller. But since the client wants each section of the frontend to be dynamic (person/location/group/event all load independant) I dont think this is the best option in my case?

Option 2 - Controllers per section that handle multiple records.
Second option I have been playing with is having a controller for each logical section. Big advantage I see is I can just keep all the controllers nicely seperated out. Something like:

Job
-Person 1
-Person 2
-Person 3
-Person 4
(submits all 4 records via ajax to the controller then somehow refreshes on success)

Do you guys find this a better solution for this style of app?

Option 3 - Controllers per section that handle just single records
Third option I’m been considering is a controleller that handles one logical section but only 1 record. For example I coudl setup a /person controller that just has the ability to save 1 person? Using the exampe above you could have something like https://demos.krajee.com/editable which would enable me to edit each person one at a time. so I send up with essentially a job form that works like:

Job
-Person 1 - Save (submits via ajax)
-Person 2 - Save (submits via ajax)
-Person 3 - Save (submits via ajax)
-Person 4 - Save (submits via ajax)

Issue I see is 4 calls to the controller for the above setup to load. Thoughts?

Second Question
My second question is, is there someting you guys use to do dynamic things on the client side that plays nice with yii2?

For example if I was using option 2 or 3 above, when I save a Person I need it to then update the Groupings section on the job form (so they can now assign the newly added person to group).

I’ve got a few ideas on how to do this from research I’ve done. I’ve had a look at https://github.com/marekpetras/yii2-ajax-box-widget which works nice with adminlte. I’ve been thinking about using a Publish/Subscribe, or, the Observer pattern such as here https://api.jquery.com/jQuery.Callbacks/ (end of page) to trigger reloads. e.g when a person is saved a “Person Saved” message is published and the Groupings section would be listening for this then refresh. I’ve even started looking at Vue,e etc. But I’m sure others have had this senario and came up with something that plays nice with Yii2? Any pointers?

Third Question
Whatever option I go with for the client what is the flow of ajax communication you use to talk between yii2 serverside and client side. In all examples I can find on the forums and web I’ve seen people do things like so:

Click Submit -> catch click in js -> cancel standard submit -> get form data and convert to json -> submit json to controller -> get json response of “succes”->reset form (so they don’t resubmit and get a duplicate record).

But if I go down this path, due to my Job form being quite dynamic I would have to do the above but in addition I would have to pass back some js in a way that triggers a refresh of the People section (to get the id’s of the new records in the form), then trigger a refresh of the Grouping section and any other section that relies on the Person records. Is this what people are doing in situations like this? This would require I roll some custom object I build in php and pass back in json to the client. something like [status=>succes, commands=>refresh_people,refresh_groupings], that then triggers for example by Observer pattern code. Issue I see is it will cause more round trips to the server.

Or are you guys passing back a complex json object that actually has the Html in it of the section that was just submitted? e.g

[
status=>success,
html=>all_the_html_parsed_from_the_people_view_and_passed_back_in_json
]

then have the js handler pass into the People div with the latest html. But I’d still need to have some way for the server to tell the client to refresh the Groupings section.

Issue I see is its getting super messy, passing back js with html in the object, then pasrsing it on the client side.

Thanks for looking over my long email. Look forward to any Yoda like wisdom from the community.

bw