Add a button to a table based on column value

Hello,

I am trying to follow the posts Using script to add a button to a table row and Pass parameter into embedded view table to add a button to my table in Perspective. I am using a Named Query for my table data and I have a script transform on that data that converts it into a pyDataSet and appends the rows data (as key/value pairs) to an array which I return. Using the columns property, I have made sure to create a column for each key in the pyDataSet. I have also created an additional column for my button. On that column, I changed the render dropdown from auto to view and configured the viewPath to point to a newly created view that contains the button I would like to display in the table cell of the main view. For each row, I only want this button to be displayed if the text in the status column of the table is equal to "PASS". In the newly created view I have an incoming parameter called status. I am expecting the value to be passed automatically from the table and I have the buttons visibility bound to the incoming status parameter. For that I am using an expression binding: if ({view.params.show_button} = "true", true, false). I think I must be missing something. If I don't have the visibility of the button bound, the button appears for every row in the table regardless of the status column. If I add the visibility binding, the button is removed for every row in the table. Can someone help me out please?

The nested view for a column renderer only gets two automatic parameters:

  • value, the source value for the column containing that view.

  • rowData, the complete row of data.

If I were you, in your transform, I'd populate the column for the nested view with a boolean reflecting PASS or not. Then the view itself can use self.view.params.value to drive the button visibility.

If you really need other items from the row, you must name a parameter rowData to get the row.

Tip: use some free paragraph breaks to avoid a wall of text. It was a tough read!

A bit more reading material to follow on from Phil's answer:

[This section of my answer is irrelevant. See the discussion below.]
Have a look at Displaying a Subview in a Table Row | Ignition User Manual.

When subviews are enabled for each row in a table, the row will implicitly pass some parameters over to the subview. The passed parameters are:

  • row - a number representing the row
  • rowIndex - a number reepresenting the index of the current row
  • value - JSON Object representing the contents of the row. The value of each column in the row will be a value under this object.

Thus, in the image above where our table has a county column, the subview will receive the value of county at params.value.country. So you can create a component binding on the subview's configuration that references a value at params.value.country.

So, if the column you are using to control the visibility is "show_button", then your button visibility expression becomes something like,
{view.params.value.show_button}

Anywhere you have,
if ({view.params.show_button} = "true", true, false)
It can be reduced to
{view.params.show_button}
which will return a true or false itself.

Not subviews. Column views for render mode == view. Not the same thing at all.

Thanks, Phil. I got mixed up and did a trawl through the manual looking for it. I can't remember now, does the row value not get passed to the rendered view as well? (I've successfully used subviews and render mode : view in the past.)

It gets passed as the rowData parameter. Documentation is a bit vague.

2 Likes

That's it. It's on Perspective - Table | Ignition User Manual. Search the page for "rowData".

Thanks.

1 Like

@pturmel Thank you for responding. As you suggested, I've change the data transform for the Table component in my main view to:

def transform(self, value, quality, timestamp):
	pyData = system.dataset.toPyDataSet(value)
	dataAsArray = []
	for row in pyData:
		new_dict = {}
		mold = row[0]
		status = row[1]
		new_dict["status"] = status
		new_dict["mold"] = mold
		
		if status == "PASS":
			show_button = True
		else:
			show_button = False
		new_dict["show_button"] = show_button
		dataAsArray.append(new_dict)
	return dataAsArray

In the view that displays the button, in the PARAMS section, I've added an object called "value" which has 2 key/value pairs:

show_button:value

and

status:value

I've added a binding to the button visibility by using an Expression Binding

if({view.params.value.show_button} = "true",true,false)

I've also added a label right next to the button. I am trying to use the label to display the status as text in the Table column cells. In the Edit Binding preview for the label, I see the word "value" but when I look back at the Table component, all the rows are still missing the button and the label text for the cells is "null". I know for a fact that there is at least one row with status of PASS and the button should be shown for that row.

@Transistor I've taken a look at Displaying a Subview in a Table Row and I've also looked at Perspective - Table | Ignition User Manual. I've made sure that the spelling and case match the column names in the transform and I've unsuccessfully tried using the rowData input parameter by adding a "rowData" key/value pair. I've also tried creating an object named "rowData" and adding key/value pairs to it, but the Designer will not let me name the key/value pairs.

Where am I going wrong?

Your nested view must have one (or both) of these parameters:

  • value, which would get the boolean you've placed in the show_button data key, and just that, the plain boolean value.

  • rowData, which gets the entire row of data in the table, where your parameter's keys match the table row's keys.

The value parameter that you've carefully defined as an object is getting smashed down into just a boolean at runtime.

The table isn't looking down into your view to see what its parameters look like. It just hands off its automatic parameters with the specified names.

(Don't let yourself be confused by the Subview documentation--that is entirely different functionality from the column's view renderer.)

The simplest fix will probably be renaming your view's value parameter to rowData.

Thank you for the feed back @pturmel. In the view that contains the button (I'll call it buttonView), I've renamed the input parameter to rowData. It still has the two key/value pairs (show_button and status).
Just to be clear, I am expecting rowData to be passed automatically, so in the main view (the one with the Table component) on the column that needs to display the button (via embedded view), I do not have any viewParams.
It is my understanding that for whatever column name that is configured for the Table.column.field property, its associated data will be passed as the value parameter to the buttonView and I should be able to access that using an Expression binding such as if({view.params.rowData.status} = "true",true,false), for example. I am still not able to access the parameters values as expected.
I feel like using the rowData parameter instead of value is the way to go. I just need to get over this parameter passing hump.

Your continued help is greatly appreciated!

Couple problems with that:

  • your sample code shows the status as containing "PASS", not "true".

  • You should never return true and false from an if() expression, just use the conditional expression directly.

If you keep a value parameter, your button's visibility should simply be bound to:

{view.params.value}

If you want to do everything with rowData, bind the button visibility to:

{view.params.rowData.show_button}

That's it.

1 Like

@pturmel You are the man!