The number of products was in the 200k's and the details needed to decide on a selection was more than just the product names, so building checkboxes/radios/select box would be too unwieldy and an autocomplete could not provide enough information.Also, the desired UX was to use a modal rather than multiple pages.This gets much harder to do when you have multiple fields of the same type, bring in translation, and/or the client decides to change the wording later on in the project.So, my suggestion is to override the button names and base the logic on them.Ideally, every button within the widget should simply cause a rebuild of the same container, regardless of the changes triggered within the nested array.
For most developers, this step is brushed over because the idea of their work being used in an unconventional or altered way is completely out of their purview.
Now, this leaves a weird situation where these other triggers have semantic names, but buttons will simply be named 'op'.
For a simple form, this is no big deal, but for something complex, determining which action to take relies on the comparison of the button values.
And if this widget's array is modified outside of the module, the modifier will just have to double check the for containers (divs) and buttons, respectively.
Like with everything in programming, naming is the initial task that can make development, current and future, a simple walk through the business logic or a spaghetti mess of "oh yeahs".
Because the time to request and receive the new content is indeterminate, screen readers will fail at providing the users with audible descriptions of the new content. If the task is to select something out of a large selection, a multiple page approach or even an entity reference with an autocomplete field could suffice.