0

I have an admin form created via an XML component which inserts a listing via the insertListing component. This listing takes data from a custom table I created for this module. The listing works: I can see the records from my custom table.

My custom table has a column that stores an array of data in a JSON format. Currently, my inserted listing shows the column with the JSON data. What I'd like to achieve is having a separate column for all the values in the JSON. The difficulty is that these JSON data can have different keys, so I cannot have the column declared statically in the XML and filled the column in with the values via dataProvider as I would normally do with UI components.

Example:

  • record A has a json of {X:1, Y:2}
  • record B has a json of {Y:1, Z:3}

What I currently see in the grid:

  • first row with column "jsondata" e value {X:1, Y:2}
  • second row with column "jsondata" e value {Y:1, Z:3}

What I'd like to achieve:

  • first row with 3 columns: column X with value 1, column Y with value 2 and column Z with value 0
  • second row with 3 columns: column X with value 0, column Y with value 1 and column Z with value 3

So what I'd need is a way to dynamically add columns to the XML. Is there a way to do it?

1

if you look at the function \Magento\Catalog\Ui\Component\Listing\Columns::prepare in the core, this does create dynamically the columns for the catalog listing.

Also, in the file vendor/magento/module-catalog/view/adminhtml/ui_component/product_listing.xml, you can see the line <columns name="product_columns" class="Magento\Catalog\Ui\Component\Listing\Columns"> is the one ensuring the columns provider takes over the default Magento Ui column provider..

So, in your module, you may perform the same setup and then you can parse your data in the prepare function to auto-create some columns.

I add below a link to a module I have built: https://bitbucket.org/magstaging/backendscreen/src/master/

This module is only here to show you some code that implements the above and below is a picture of my backend screen with a column that has some json info and then just next 2 columns dynamically created and showing the data from the json in several columns

enter image description here

In this module, there are only 2 classes that you will need to take a look at:

\Mbs\BackendScreen\Ui\Component\Listing\Columns

and \Mbs\BackendScreen\Ui\Component\DataProvider

| improve this answer | |
  • thank you, this is exactly what I needed! Just one other question, if you don't mind: by following your code I can add the rows but I have to statically assign a label/name. Is there a way to get the name of the column from the content of the column? I'll explain: the JSON containing the data (the customer name column in your screenshot) has a key and the value: is there a way to get the key from the JSON data and use that key as the name of the column we add via prepare() (eg: the column "firstname" is created by getting the JSON key "firstname")? – Lou Nik Jun 29 at 9:39
  • oops, I did take a look and it is not obvious at all. grid structure is built before the data are gathered. But since each row will have the same number of column, I imagine there is way to know how the json structure is before reading the data and if somewhere you can read this, then you'd be able to build your column parsing this json structure info.. difficult to advise more as I don't know your data and situation – Herve Tribouilloy Jun 29 at 14:45
  • thank you for looking it up anyway.. it is a very simple JSON {"key":"value"}. The JSON is stored in a column in my database, so I can grab the json via dataProvider and showing it in one column (that's like the column "customer name" in your screenshot). It's basically a set of sizes, but not all records have the same set, that's why I need to take the keys from the JSON. I thought about saving and retrieving the JSON data with the DataPersistorInterface: this works but it doesn't look right, I wouldn't might a better solutions, something that's more magento-standard – Lou Nik Jun 29 at 14:58
  • I'll think again, something might come up.. with a bit of time – Herve Tribouilloy Jun 29 at 15:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.