Resolve #3508170 "Image in preview"
This required some interesting steps
- The first challenge was even making the FE aware a change had taken place. Each media item is represented by the presence of hidden
media_field_name[selection][NUM][target_id]
element - and there's one of these for each item. When a media library item is removed, the corresponding element is removed not changed. This is quite easy to deal with on a conventional form submit because it's looking at the entire form state at once. For XB, a<Hidden>
component was used to keep track of themedia_field_name[selection][NUM][target_id]
element being removed by using auseMutationObserver
hook I added. When it is removed it triggers a value change and PATCH request to update the store and preview. - For a primitive prop like a string, empty is just a variation of the data type it expects "Hello World" and "" are still both strings. It's different with a media reference - a valid ID has url/height/width/alt value. The absence of a value does not provide a comparable structure, and without some finagling here we run into errors such as
Drupal\experience_builder\PropSource\DefaultRelativeUrlPropSource::isUrlJsonSchema(): Argument #1 ($property_definition) must be of type array, null given...
because it has (reasonable) expectations about a prop existing and being in a certain format. There's nourl
etc property for "lack of an image", so it's replaced with a distinct string that flags that item for removal. - Earlier drafts were very media library targeted - looking for empty strings as the value of ['selection'][0]['target_id'] but the flag approach
- should be able to work with other data structures without having to know what those structures are.
- makes it way more obvious what is happening vs a condition that is
if($something === '')
When APILayoutController
sees the flag it knows it is a value to be removed and does not attempt to render or validate it. For optional fields, it empties the value. For required fields, it reverts to the default value - usually the example. The flag approach provides benefits over the PATCH request sending an "empty" value as it distinguishes a value that is being removed vs a value that hasn't yet been populated.
Edited by Ben Mullins