configureEditor Script Behavior Questions/Concerns

Hello all!

I have a power table that displays a view with our recipes and ingredients tied to the recipe. I have followed some helpful articles form the forum regarding the configureEditor to allow for a dropdown when selecting into a cell, then updating the power table with the new value.

All of this is working as intended, but when I go to update this within the database by running a Named Query, it does not update with the respective value. I added quite a few print statements to try a better understand why this is the case. It seems to be running the script as soon as I enter preview mode.

Is there a way to invoke the update named query after the user select the new value within this function? Or would this update named query be better ran in another function? Do let me know if you need any more information, thank you!

configureEditor Script:

	# Print the raw value of colName for debugging
	print("Raw Column Name:", repr(colName))
	
	if colName.strip() == "Ingredient":
	    print("Entering the if block.")  # Add this line for debugging
	    try:
	        pt = system.db.runNamedQuery("select ingredient")
	
	        # Construct the list of options using data from each row
	        options = [(pt.getValueAt(row, "Ingredient_ID"), pt.getValueAt(row, "Ingredient")) for row in range(pt.rowCount)]
	
	        # Print the options for debugging purposes
	        print("Options:", options)
	
	        # Additional print statements within the try block
	        print("Before update recipe name query.")
	
	        system.db.runNamedQuery("update recipe name", {"IID": options[0][0], "ID": self.data.getValueAt(0, "ID")})
	
	
	        print("After update recipe name query. Database update successful.")
	
	        # Return the options
	        return {'options': options}
	
	    except Exception as e:
	        print("Exception type:", type(e))
	        print("Error getting ingredients:", e)
	
	# Print a message if the if block is not entered
	print("Did not enter the if block.")

isCellEditable:

return True

onCellEdited:

self.data = system.dataset.setValue(self.data, rowIndex, colIndex, newValue)

You seem to misunderstand this extension function's purpose. It is called once for each column in the table when the table is populated. It is not called for each row/column combination that gets edited.

This means, if you need certain kinds of dynamic behavior, you need to supply an editor object that includes the necessary methods. That custom editor will be called for actual editing activity. (Some examples here.)

Most importantly, that editor is not supposed to deliver the result anywhere, except back to the table's internal code. Which then dispatches it to the onCellEdited extension function.

2 Likes

I do believe I am misunderstanding, thank you for the clarification! I will look into some of the articles and see if I can bring some of the functionality over!

Do note that whatever else your editor object does, it must not run database queries or otherwise make gateway calls. You can dynamically generate options, but you need to preload the possibilities, as shown in Paul's linked topic.

1 Like

Thank you. I already had that linked within my question above though!

1 Like

So, would my SELECT statement within the cofigureEditor not be advised? I have made some progress with the script(s) by also using the propertyChange to update the database once it is ran.

Although, i am now running into the issue of the propertyChange running on initialization of the screen. I was thinking of adding in invokeLater to combat this, although I think this is more of a band aid rather than a fix.

configureEditor:

	if colName.strip() == "Ingredient":
		print("Entering the if block.")
		try:
	        # Assuming "select ingredient" is a valid named query
			pt = system.db.runNamedQuery("select ingredient")

	        # Construct the list of options using data from each row
			options = [(pt.getValueAt(row, "Ingredient_ID"), pt.getValueAt(row, "Ingredient")) for row in range(pt.rowCount)]

	        # Set the editor options for the "Ingredient" column
			return {'options': options}
		except Exception as e:
			print("Error configuring editor:", e)

propertyChange:

print("prefire")
if event.propertyName == "selectedColumn" or event.propertyName == "selectedRow":
        # Check if the property change event is related to cell selection
        if event.propertyName == "selectedColumn" and hasattr(event.source, 'selectedColumn') and hasattr(event.source, 'selectedRow'):
            selectedColumn = event.source.selectedColumn
            selectedRow = event.source.selectedRow

            # Check if the selected cell is valid
            if selectedColumn >= 0 and selectedRow >= 0:
                print("Selcol")
                # Check if the selected cell is in the "Ingredient" column
                if selectedColumn == 4:
                    # Get the selected value from the underlying dataset
                    dataset = event.source.data
                    selectedValue = dataset.getValueAt(selectedRow, selectedColumn)
                    print(selectedValue)
                    print(dataset.getValueAt(selectedRow,0))

                    try:
                        print("Running??")

                        system.db.runNamedQuery("update recipe name", {"IID": selectedValue, "ID":dataset.getValueAt(selectedRow,0)})
                        print("Database updated with selected ingredient:", selectedValue)
                    except Exception as e:
                        print("Error updating database:", e)

EDIT: I should also point out it will update the DB with the new value, granted it runs as soon as I select the cell to update, rather than when I select the new value.

Both of those scripts are running on the main Swing GUI thread, the event dispatch thread or EDT. Any blocking call on that thread (such as running a named query, which implies a minimum of two network hops, in both directions) will be immediately visible to end users, as the UI will "freeze" for as long as those scripts take to run. If it's long enough (e.g. in case of a network interruption) the OS will even kick in and warn about an unresponsive process.

You must perform your queries off the primary thread or train every single user about this possibility.

Thank you. I will admit I am not well versed with the thread usage pertaining to scripts. I will read up on this more to get a better understanding moving forward. In the mean time, do you know what would be the best solution to limit this? I am not sure what my next steps should be, possibly IA support?

Do you have to run the query for each row?

Whether you do or not, you should be using a Named Query binding on a custom property on the table, using bindings to supply its parameters. Reference that custom dataset property in your custom editor.

(Do not run a select query in configureEditor, nor in the editor instance's code.)

You cannot set up different options per row using
return {'options': something} in your configureColumn script. Only a custom editor can do this.

1 Like

I would need to run the query for each row they change, yes.

I didn't even think about a custom property as a dataset for the query! I will play with this and see what I can come up with.

It would have the same options (ingredients) for all rows within the table

Thank you @pturmel !

Contradicts this:

Or is the former the update query? If so, that belongs in onCellEdited.

Apologies for the confusion. yes, the SELECT will have the same dataset given whichever row they select. I have now put this into a dataset custom property on the power table.

I would want the UPDATE query to run when a cell in any row is changed.

Then you can use the {'options': something} return from configureColumn--just generate it from the custom property. No custom dropdown editor required.

The update belongs in onCellEdited.

1 Like

Perfect! I will do this and update the thread if it worked! Thank you again, Phil!

EDIT: That solved the issue! Once again Phil saves the day! :grinning: