# Cell Value change problem on table with embedded views

**URL:** <https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488>\
**Category:** Ignition\
**Tags:** scripting, perspective\
**Created:** [October 15, 2025, 8:11pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488 "2025-10-15T20:11:57Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [October 15, 2025, 8:11pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/1 "2025-10-15T20:11:57Z")

</div>

Hello all,

I have an issue while using an embedded view (numeric entry field) in a table, for a few different cells. If I only change one value (Quantity), it's happy, but if I change two values (Quantity and Price), then I get errors.

I am building on Danila Talbot's ( @danieltalbot ) scripting for a table, data transform and embedded views.

Data comes in from a named query, gets passed to a function on the table: SetColumns, then transformed for the table to display.

SetColumns code, Parameter: value (dataset):

```python
true = True
	false = False
	try:
		columns = system.dataset.getColumnHeaders(value)
		columns.append('ExtCost')
	except:
		columns = value[0].keys
	
	# Custom column order
	column_order = ['PartNumber', 
					'Description', 
					'Quantity', 
					'Price', 
					'ExtCost', 
					'UOM', 'ContainerID', 
					'LeadTime', 
					'ReqID',
					'ItemID']
	
	output = []
	container_ds = system.db.runNamedQuery("Purchasing/Dropdowns/Container_CBO")
	uom_options = system.db.runNamedQuery("Inventory/Dropdowns/UOM_CBO")
	
	for col in columns:
		colObject = {"field": col, "visible": true, "editable": false, "render": "auto", "justify": "auto", "align": "center", "resizable": true,
					 "sortable": false, "sort": "none", "filter": { "enabled": false, "visible": "on-hover", "string": { "condition": "", "value": ""},
					 "number": {"condition": "", "value": ""},
					 "boolean": {"condition": ""},
					 "date": {"condition": "", "value": ""} },
  					 "viewPath": "", "viewParams": {}, "boolean": "checkbox", "number": "value", 
  					 "progressBar": {"max": 100, "min": 0, "bar": {"color": "", "style": {"classes": ""} }, 
  					 "track": {"color": "", "style": {"classes": ""} }, "value": {"enabled": true, "format": "0,0.##", "justify": "center", 
  					 "style": {"classes": ""}}}, "toggleSwitch": {"color": {"selected": "", "unselected": ""}},
  					 "nullFormat": {"includeNullStrings": false, "strict": false, "nullFormatValue": ""},
					 "numberFormat": "0,0.##", "dateFormat": "MM/DD/YYYY", "width": "", "strictWidth": false,
					 "style": {"classes": ""},
  					 "header": {"title": "", "justify": "center", "align": "center", "style": {"classes": ""}},
  					 "footer": {"title": "", "justify": "left", "align": "center", "style": {"classes": ""}}}
  		if col == 'ReqID':
  			colObject['visible'] = false
  		elif col == 'ItemID':
  			colObject['visible'] = false
  		elif col == 'Description':
  			colObject['visible'] = true
  			colObject['width'] = 300
  			colObject['render'] = 'view'
  			colObject['viewPath'] = 'Purchasing/Objects/Txt Line Item'
  			colObject['viewParams']['source'] = self.custom.table_id
  		elif col == 'PartNumber':
  			colObject['visible'] = true
  			colObject['width'] = 160
  			colObject['header']['title'] = 'Part #'
  			colObject['render'] = 'view'
  			colObject['viewPath'] = 'Purchasing/Objects/Txt Line Item'
  			colObject['viewParams']['source'] = self.custom.table_id
  		elif col == 'Quantity':
  			colObject['visible'] = true
  			colObject['width'] = 75
  			colObject['render'] = 'view'
  			colObject['viewPath'] = 'Purchasing/Objects/Num Line Item'
  			colObject['viewParams']['source'] = self.custom.table_id
  		elif col == 'Price':
  			colObject['visible'] = true
  			colObject['width'] = 75
  			colObject['render'] = 'view'
  			colObject['viewPath'] = 'Purchasing/Objects/Num Line Item'
  			colObject['viewParams']['source'] = self.custom.table_id
  		elif col == 'ExtCost':
  			colObject['visible'] = true
  			colObject['width'] = 75
  			colObject['render'] = 'view'
  			colObject['viewPath'] = 'Purchasing/Objects/Num Line Item'
  			colObject['viewParams']['source'] = self.custom.table_id
  		elif col == 'LeadTime':
  			colObject['visible'] = true
  			colObject['width'] = 80
  			colObject['header']['title'] = 'Lead Time'
  			colObject['render'] = 'view'
  			colObject['viewPath'] = 'Purchasing/Objects/Num Line Item'
  			colObject['viewParams']['source'] = self.custom.table_id
  		elif col == 'UOM':
  			colObject['visible'] = true
  			colObject['width'] = 80
  			colObject['render'] = 'view'
  			colObject['viewPath'] = 'Purchasing/Objects/Drop Line Items'
  			colObject['viewParams']['source'] = self.custom.table_id
  			colObject['viewParams']['options'] = uom_options
  			colObject['viewParams']['placeHolder'] = 'UOM...'
  		elif col == 'ContainerID':
  			colObject['visible'] = true
  			colObject['width'] = 100
  			colObject['render'] = 'view'
  			colObject['viewPath'] = 'Purchasing/Objects/Drop Line Items'
  			colObject['viewParams']['source'] = self.custom.table_id
  			colObject['viewParams']['options'] = container_ds
  			colObject['viewParams']['placeHolder'] = 'Container...'
  			
  		output.append(colObject)
  	output_sorted = []
  	for col_name in column_order:
  		for col_obj in output:
  			if col_obj['field'] == col_name:
  				output_sorted.append(col_obj)
  				break
  	self.props.columns = output_sorted
  	return output_sorted

```

The script transform code on `table.custom.data`, to which the `table.props.data` is bound:

```python
	columns = self.SetColumns(value) # value is a dataset
	output = []
	
	# for each row in the dataset
	for row in range(value.getRowCount()):
		row_value = {'updateMe':False, 'deleteMe':False}
		
		price = 0
		qty = 0
		
		# for each column in the column list:
		for col in columns:
			colName = col['field']
			if colName == 'Price':
				price = value.getValueAt(row, colName)
			if colName == 'Quantity':
				qty = value.getValueAt(row, colName)
			if colName != 'ExtCost':
				cellValue = value.getValueAt(row, colName)
				row_value[colName] = {'value':cellValue, 'action':'update'
					, 'enabled':True, 'display':True, 'style':{}}
			ext_cost = round(price * qty, 2)
			row_value['ExtCost'] = {
				'value': ext_cost,
				'action':'update',
				'enabled':False,
				'display':True,
				'style':{}
			}
		output.append(row_value)
	return output

```

Embedded view parameters:  
`column, rowData{}, rowIndex, source (table identifier), value`

`custom.props`:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/8/d/8d06491aedb4e382de99d3b569380a3fa9a45100.png)

the `custom.value` elements are expression bound like this, for each one:

```python
try({view.params.value}['action'],{view.params.value})

```

the `custom.payload` elements are property bound like this:

```python
view.params.rowData

```

`newValue` is bound to the Numberic Entry Field's `props.value`.

The `props.value` is expression bound like so:

```python
coalesce({view.custom.value.value}, 0)

```

There is an `onChange` script on the `props.value`:

```python
	if origin != 'Binding':
		if currentValue.value != previousValue.value:
			if self.view.params.source == 'lineItems':
				message = 'recalcExtCost'
				payload = self.view.custom.payload
				scope = 'page'
				system.perspective.sendMessage(message, payload, scope)

```

And finally the message handler code that throws the error:

```python
	rowIndex = int(payload['rowIndex'])
	column = payload['column']
	newValue = payload['newValue']
	
#	message = str(rowIndex) + ': ' + str(column) + ': ' + str(newValue)
	system.perspective.print(column)
	self.custom.table_data[rowIndex][column] = newValue
	if column == 'Quantity':
		price = self.custom.table_data[rowIndex].get('Price',0)
		quantity = newValue
	elif column == 'Price':
		price = newValue
		quantity = self.custom.table_data[rowIndex].get('Quantity',0)
		
#	quantity = self.custom.table_data[rowIndex]['Quantity']['value']
	system.perspective.print(price)
	system.perspective.print(quantity)
	ext_cost = round(price * quantity, 2)
	self.custom.table_data[rowIndex]['ExtCost'] = ext_cost

```

And the error message:

```python
Error running Purchasing/Primary Views/Request Form@D/root/Flx Bottom/Flx Bottom Left/Flx Bottom Table/Table.onMessageReceived(self, payload): Traceback (most recent call last): File "<function:onMessageReceived>", line 20, in onMessageReceived TypeError: unsupported operand type(s) for *: 'com.inductiveautomation.perspective.gateway.script.PropertyTreeScriptWrapper$ObjectWrapper' and 'long'

```

The error message changes a little depending on how I try to extract the actual value, but it all seems to relate to not being able to get just the numbers from both embedded views and multiplying them. I have been using Copilot to help me figure this out, but it's recommending something I don't understand on changing the embedded view's `props.value` expression binding, which caused some other error, and now it's recommending I do something completely different.

Is there a simple fix I can use in the message handler or something else I should do?

Thank you!

---

<div class="post-metadata">

**Author:** ![danieltalbot](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/danieltalbot/32/11201_2.png) [@danieltalbot](https://forum.inductiveautomation.com/u/danieltalbot)\
**Post date:** [October 15, 2025, 8:59pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/2 "2025-10-15T20:59:57Z")

</div>

From your error message, it appears that newValue is a PropertyTreeScriptWrapper$ObjectWrapper type, when you’re expecting it to be numeric. I would try defining the payload inside of the change script on your embedded view instead of sending the view.custom.payload property directly. Otherwise, look into why that newValue is coming in as the wrong datatype.

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [October 15, 2025, 11:07pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/3 "2025-10-15T23:07:43Z")

</div>

I don't think it's the `newValue` that throws the error. It's the getting the new value from the other embedded view for the calculation.

---

<div class="post-metadata">

**Author:** ![danieltalbot](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/danieltalbot/32/11201_2.png) [@danieltalbot](https://forum.inductiveautomation.com/u/danieltalbot)\
**Post date:** [October 15, 2025, 11:21pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/4 "2025-10-15T23:21:35Z")

</div>

On line 20 in your message received script it is trying to multiply an ObjectWrapper with a long. You are printing the values for both price and quantity - is it printing the correct values?

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [October 16, 2025, 1:02am UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/5 "2025-10-16T01:02:02Z")

</div>

What I see, when I change the Quantity, the error lists the wrapper then the long objects.  
If I change the Price first, it lists the long then the wrapper objects.  
Ah, just noticed this in the console:

```python
17:09:51.739 [Browser Thread: a812c4f4-d4a5-4b62-b4b9-44294b9ffc30] INFO Perspective.Designer.Workspace -- Quantity
17:09:51.743 [Browser Thread: a812c4f4-d4a5-4b62-b4b9-44294b9ffc30] INFO Perspective.Designer.Workspace -- <ObjectWrapper>: {u'display': True, u'action': u'update', u'style': {}, u'value': 40.0, u'enabled': True}

```

So this:

```python
price = self.custom.table_data[rowIndex].get('Price',0)

```

is the wrapper object, and vice versa if I change the Price first.

But, if I change it to this:

```python
price = self.custom.table_data[rowIndex]['Price']['value']

```

Then, if I change only the Quantity cells, it's OK, or if I change only the Price cells it's OK. But if I change one then the other, I get:

```python
File "<function:onMessageReceived>", line 11, in onMessageReceived TypeError: 'long' object is unsubscriptable

```

  
In this instance, line 15 is:

```python
quantity = self.custom.table_data[rowIndex]['Quantity']['value']

```

I discovered why that is happening. The message handler (`recalcExtCost`) is changing the table row object into a `long`. So, I thought I could set the `value` key (marked with number 10):

```python
	rowIndex = int(payload['rowIndex'])
	column = payload['column']
	newValue = payload['newValue']
	rowValue = payload['rowValue']

#	system.perspective.print(column)
	system.perspective.print(newValue)
10	rowValue['value'] = newValue
#	system.perspective.print(rowValue['value'])
	self.custom.table_data[rowIndex][column] = rowValue
	if column == 'Quantity':
		price = self.custom.table_data[rowIndex]['Price']
		quantity = newValue
	elif column == 'Price':
		price = newValue
		quantity = self.custom.table_data[rowIndex]['Quantity']

```

But, no dice. I am not sure what the next step is.

---

<div class="post-metadata">

**Author:** ![danieltalbot](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/danieltalbot/32/11201_2.png) [@danieltalbot](https://forum.inductiveautomation.com/u/danieltalbot)\
**Post date:** [October 16, 2025, 1:35am UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/6 "2025-10-16T01:35:20Z")

</div>

Can you share a screenshot of what a row in your data looks like before updating any columns, then after updating one, then after updating the other? So 3 screenshots of the data in total? (by row in your data, I mean the row object in the property editor)

I think what’s happening is that the data is originally nested, but when you’re writing it back it isn’t nested in the same way.

From `{u'display': True, u'action': u'update', u'style': {}, u'value': 40.0, u'enabled': True}`

Probably to whatever value you’re entering, like `1`

So when you write to your data, make sure you write to the [“value”] key instead of the entire column object.

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [October 16, 2025, 6:06pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/7 "2025-10-16T18:06:46Z")

</div>

Here is the code for the screenshots demo:

```python
	rowIndex = int(payload['rowIndex'])
	column = payload['column']
	newValue = payload['newValue']
	rowValue = payload['rowValue']

	system.perspective.print(newValue)

	self.custom.table_data[rowIndex][column] = newValue
	if column == 'Quantity':
		price = self.custom.table_data[rowIndex]['Price']
		quantity = newValue
	elif column == 'Price':
		price = newValue
		quantity = self.custom.table_data[rowIndex]['Quantity']

	extCost = round(price * quantity, 2)
	self.custom.table_data[rowIndex]['ExtCost'] = extCost

```

Before changing either cell value:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/2/02614e10a778e63c792478e91a1f0acf44dfd90e.png)

After changing Quantity:

```python
File "<function:onMessageReceived>", line 23, in onMessageReceived TypeError: unsupported operand type(s) for *: 'com.inductiveautomation.perspective.gateway.script.PropertyTreeScriptWrapper$ObjectWrapper' and 'long'

```

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/d/ed966b398674bb988b2b0f2628e729a47f029e99.png)

After changing Price:  
No error.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/9/3/936640e87fa02facfbf935e1cb032f9a7863dfbe.png)

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [October 16, 2025, 6:11pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/8 "2025-10-16T18:11:26Z")

</div>

> [@danieltalbot](#):
>
> I think what’s happening is that the data is originally nested, but when you’re writing it back it isn’t nested in the same way.

That's what I was trying to do with the lines:

```python
rowValue['value'] = newValue
self.custom.table_data[rowIndex][column] = rowValue

```

---

<div class="post-metadata">

**Author:** ![danieltalbot](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/danieltalbot/32/11201_2.png) [@danieltalbot](https://forum.inductiveautomation.com/u/danieltalbot)\
**Post date:** [October 16, 2025, 6:23pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/9 "2025-10-16T18:23:47Z")

</div>

try this instead:  
self.custom.table\_data[rowIndex][column][“value”] = rowValue

See how after changing the value for Price or Quantity, the row object in property editor goes from an object {5} to a value?

---

<div class="post-metadata">

**Author:** ![danieltalbot](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/danieltalbot/32/11201_2.png) [@danieltalbot](https://forum.inductiveautomation.com/u/danieltalbot)\
**Post date:** [October 16, 2025, 6:51pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/10 "2025-10-16T18:51:44Z")

</div>

In your message handler script, the line

```python
self.custom.table_data[rowIndex][column] = newValue

```

try this instead:

```python
self.custom.table_data[rowIndex][column]["value"] = newValue

```

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [October 17, 2025, 4:37pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/11 "2025-10-17T16:37:51Z")

</div>

After changing that, I had to go back and make sure to grab the `['value']` from the un-changed cell object.  
So, this, then, became the solution that seems to work:

```python
	rowIndex = int(payload['rowIndex'])
	column = payload['column']
	newValue = payload['newValue']
	rowValue = payload['rowValue']

	system.perspective.print(newValue)

	self.custom.table_data[rowIndex][column]['value'] = newValue
	if column == 'Quantity':
		price = float(self.custom.table_data[rowIndex]['Price']['value'])
		quantity = newValue
	elif column == 'Price':
		price = newValue
		quantity = float(self.custom.table_data[rowIndex]['Quantity']['value'])
		
	extCost = round(price * quantity, 2)
	self.custom.table_data[rowIndex]['ExtCost'] = extCost

```

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [October 20, 2025, 9:51pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/12 "2025-10-20T21:51:53Z")

</div>

Quick follow up question:  
I have built several tables using this scripting method, and am using them in a Tab Container (for different purposes). I noticed that the background color reverts to normal if I switch tabs and come back without saving the changes. But, in the Designer I can see that the background color still has the variable, it just does not display the color.

Any thoughts on why this might be?

---

<div class="post-metadata">

**Author:** ![danieltalbot](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/danieltalbot/32/11201_2.png) [@danieltalbot](https://forum.inductiveautomation.com/u/danieltalbot)\
**Post date:** [October 20, 2025, 10:53pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/13 "2025-10-20T22:53:55Z")

</div>

If the color logic lives on the embedded view, then switching tabs is causing those embedded views to reload and colors to reset. Check for a style or backgroundColor binding in the embedded view to see how that color gets there. If the backgroundColor is assigned to the row/column in a style object, then it shouldn’t matter as long as the data isn’t resetting. Feel free to DM me with more details if you need help.

---

<div class="post-metadata">

**Author:** ![mdemaris](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdemaris/32/54639_2.png) [@mdemaris](https://forum.inductiveautomation.com/u/mdemaris)\
**Post date:** [October 20, 2025, 11:05pm UTC](https://forum.inductiveautomation.com/t/cell-value-change-problem-on-table-with-embedded-views/111488/14 "2025-10-20T23:05:18Z")

</div>

I think I figured that one out. If you don't mind, I have another follow up question, and this is about working with table filters.

Since the embedded view is getting the row index automatically, which changes with every filter, how would I get the `selectedRow` passed as a param instead?

Is there a way to script a binding in the `SetColumns` function?  
Something like `colObject['viewParams']['selectedRow']['binding'] = 'self.props.selection.selectedRow`?

**Edit** : Just found a thread that answers that question with a resolute "NO".

**Edit** : I solved this follow up question.
