Perspective Table Subview Stops Working when JSON Formatting is Applied to the Table

I am Using Ignition Version 8.1.20. I have created an app that display work order data from a database that I am connected to... essentially I am pulling down about 100 records one time per day and storing them in two tags as dataset data. I configured a table to display the data from the first tag, and then I created a subview that contains a 2nd table connected to a second tag with dataset data... The 2nd tag has some comments in it that the first doesn't ... so I am using the subview to filter these comments and displaying them when someone clicks the subview.

All of this worked great... until I added a script that iterates through the dataset, adds formatting to the rows based on the values (Back ground color essentially) , and then returns that same data merged with formatting as a JSON object and reassigns this to the props.data section of the table as the data source. The script I wrote for this works beautifully to format the table, however while this is active the subview will no longer pass the parameter to child form to display its data. I get an error message when this happens informing me that the filed I am looking up no longer exists.

With the table in this same format, I was able to use the event "OnSubviewExpand" to extract the same data that should be passing to the subform and pass it to a label or other control without a problem... but if I try to pass it to the value of the subview/viewParams I still get the same error message. I can remove my formatting and everything works fine, but the JSON formatted data doesn't want to work with the subview.

I have researched several work arounds...but so far nothing works.
Any suggestions ?

Post your code.

def FormatWOData(value): # this script will merge formatting with the dataset it is used on
	# This list will be used to create a JSON like structure that will insert rows for our styles
		output_json = []
	 
	# Here we can define what styling on our rows will be.
		style_orange = {"backgroundColor": "#F7901D"}
		style_Light_Green = {"backgroundColor": "#00AA00"}
		style_Dark_Green = {"backgroundColor": "#00D900"}
		Style_Dark_Red = {"backgroundColor": "#FF4747"}
		style_Light_Red =  {"backgroundColor": "#FF8A8A"}
		style_Dark_Yellow = {"backgroundColor": "#D9D900"}
		style_Light_Yellow = {"backgroundColor": "#FFFF8A"}
	 
	# You could change more than just the background color, for example:
	# style_another_example {"backgroundColor": "#00AA00", "font-weight": "bold"}
	# 	myvalue = self.props.data
	# 	value = system.dataset.toPyDataSet(myvalue)
	 	for row in range(value.getRowCount()):
	    		row_object = {}
	 		row_value = {}
	 		row_style = {}
	  		for col in range(value.getColumnCount()):   
	        		row_value[value.getColumnName(col)] = value.getValueAt(row, col)
	        		row_object['value'] = row_value
	         
	        # Here we're checking the name of the column that we want to base our styling on.
	      			if value.getColumnName(col) == 'Criticality':
	         
	            # Here we're checking for individual values within the column, and applying styling
	            			if value.getValueAt(row, col) >= 3:
	            				if row % 2 == 0:
	            					row_style = style_Dark_Green
	            				else:
	            					row_style = style_Light_Green
	            			elif value.getValueAt(row, col) == 2:
	            				if row % 2 == 0:
	            					row_style = style_Dark_Yellow
	            				else:
	            					row_style = style_Light_Yellow
	                		elif value.getValueAt(row, col) == 1:
	                			if row% 2 == 0:
	                				row_style = style_Dark_Red
	                			else:
	                				row_style = style_Dark_Red
	                 
	        		row_object['style'] = row_style
	    		output_json.append(row_object)
#	    mydata = system.dataset.
		return output_json

This is the code I am using to apply formatting to my table... The code iterates through my dataset and colors the rows based on the "Criticality" value... this works fine, but after using this to format my table, it no longer will work with the subview.
I'll try to post an image of the props of the table here to show you the settings...

Preformatted text

Here is a snapshot of the data layout after formatting. I am passing the WorkOrderNumber parameter to the subview, and before applying the formatting script the subview works well...but after it does not.

image

You need to format your code when posting on the forum. Select the code and click the </> button. There's a pencil icon under your post to get into edit mode. Can you fix them?

  1. Remove the hard-coded viewParams you are supplying in the screenshot, which will allow the table to just pass the info of the row within data. I think supplying them as you have means that WorkOrderNumber will always pass along "value" as its value.
  2. When using a Subview, the subview will always receive all of the data (every key:value pairing) of the row. Using the property editor to specify params is were you would supply values when your intent is for every row to use the same value across all rows.
  3. We also need to see the code from the other side: the View being used for the SubView. I suspect you probably specified the params as all being top-level keys, but I think that you would need to have a top-level object with a key of value. Could you please supply a screenshot of the params as they exist in the View used in the SubView, and please also post whichever code is actually throwing the exception you previously mentioned when trying to access they key (field) which is missing.
1 Like

This might be the problem. Avoid writing to a property that has a binding. You probably need to move the original binding to a custom property, and then process that with your script to produce the object for props.data.

Sure...Give me a moment and I'll be glad to give you that...
I should point out that all of this works fine if I remove the JSON formatting from my data... I am not having any problems displaying the subview data at all until I enable the script that I posted here to format the dataset used to populate this datatable.

The ViewParams shown here wasn't actually hard coded... it automatically populated when I selected a subview ViewPath...

Here is a screen shot of the subview without the table formatting being used... as you can see it works fine until I add the row colorization script.

After I add the formatting, this is what happens:

Right, because your formatting has changed the actual structure of the data being supplied as params to the subview. Previously, your Subview expected WorkOrderNumber to be a top-level key. After your JSON restructuring to allow for styling you have a structure of

"value": {
    "WorkOrderNumber": "Something",
    "SiteName": "etc"
}

So I think your SubView has to change to accommodate the new structure.

I don't need to see the actual error - I need to see the line of code in the Subview which references WorkOrderNumber; line 3 in some script of the SubView references WorkOrderNumber.

2 Likes

And here is the param value that this is referencing:

I see what you mean... You are exactly right.
I changed the target parameter to add an extra value layer.. so that its now param.value.value.workordernumber and now it works!

Thank you so much.. !

image

1 Like

Ok, same question, same project, same field.- but a different control. This time I am using a column view, and passing the columns value to a button control that I am displaying on in place of a cell on the table. The same solution did not work with regard to this, and I am sure it is because my starting place is slightly different (Instead of starting with the row ID or whatever on the basic level of the datarow, I am starting on a row /column ...

I tried just adding another level to the target view param but that didn't work...

Here is the button (in Red) before I changed it.

image

with the column view configuration data

image

How should I change this one after the fact to make it work with the JSON data? Would I need to change the parent and the child on this ? or just the Child?

Here are the changes just to the child form (The button), and their result...

image

image

As you can see I just added a 2nd layer of value to the target as before...in this case the button... but obviously it doesn't work quite the same from the column control... but I am not sure what to do differently

image

Views rendered as a cell do not receive params in the same manner.

Subviews (rows) need all of the information of the row entry within data.
Cells need only the piece of information from that row where the key within data matches columns[x].field.

Tat content is then passed along and will be received within the value object. See this post.

So in the View being used for the cell, you should have just WorkOrderNumber as a child of value, without the extra value object in between.

It did not work....
I reviewed the link you sent, and I went over everything that we have done when solving the previous solution... but so far to no avail. Before adding the formatting, the column value passes right through to the control easily, but I can't quite put my finger on what the difference is with regard to the column itself.

Ah, I was slightly wrong. Provided the following structure (from the demo/default data of the Table component):

{
  "city": {
    "value": "Folsom",
    "editable": true,
    "style": {
      "backgroundColor": "#F7901D",
      "classes": "some-class"
    },
    "align": "center",
    "justify": "left"
  },
  "country": "United States",
  "population": 77271
}

Now, assuming you want to access the underlying value of the column (WorkOrderNumber in your scenario) you would actually want the View being rendered for the cell to access value.value (view.params.value.value).

You can test this yourself by placing a Label in the View to be used in the cell and binding the text of a Label component against view.params.value. This exposes the structure of the incoming param data as the View receives it, where the relevant property is exposed as simply "value".

{
  "editable":true,
  "justify":"left",
  "style":{
    "backgroundColor":"#F7901D",
    "classes":"some-class"
  },
  "align":"center",
  "value":"Folsom"
}

ok... I did this... and its very close, but I am running into some kind of caveat. I found a work around for it, but... let me explain.

So I created a label control and used it to read the referenced output so that I could better understand what data was being passed, and then experimented with these items... I found a reference for table column values to go by... and I tried using these as a starting place, along with what you have already shared with me.
When I setup the param "value.row" I get the row ID of the row form the table... when I setup value.column I get the name of the column... and according to everything I have read here if I setup value.value I should get the direct value of the cell from that column at that intersection (WorkOrderNumber in this case) but I get a blank...

on the columns entry I leave the viewParams blank, but on the view that I am selecting is where I am setting these values I mentioned above... The row is giving me the row ID without fail. I was able to create a WorkOrderNumber lookup script and passing the row (ID) to it, and it works fine... but i can't get a direct reference to the workOrderNumber itself for some reason... Which makes no sense to me. If I can get the correct row ID (row), or the correct column name ...I should be able to get the data. If I don't select a view the value is passed to the cell without a hitch, as it normally would be.

this is from the user guide... as you can see value:value should give me what I need...
row:value does give me the row ID, and column: value does give me the name...but not value:value .

Here are my references when I try value:value
image
I left row there and added value, and as you can see here I am referencing value here

Here are the results of value:value
image

Here I am referencing row:value

Here is the result: as you can see this works fine...

Since its not the value I need...here is my work around (A lookup script using the row)

And here is the result of that

Its a weird issue... When I try to return the entire row the data is in there, but I can't figure out why its not working directly ... now this only happens after the formatting change, so It has something to do with that, and the way its handing the workOrderNumber data... but at this point I don't know where to go next. My work around works fine, however since I am using the button to change the underlying data, I had to find a way to refresh my data smoothly to keep the wrong number from being shown on the button before the controls are refreshed. (I did get this working to my satisfaction : but I will eventually revisit this, and should I figure out what's going on here I'll be happy to share it with you guys)