Closed matkuki closed 4 years ago
Weird observation: if I add a print statement of the returned value, then is works:
def insert_data(self):
result = self.table.addData([ {} ], True)
print(result)
... and the error disappears. This example has been directly copy&pasted from my code, the table
object is now initialized in the __init__
method. But without the print
statement, the error is same as in the previous example.
@almarklein Could you take a look at this issue please? I have no idea what's going on here.
P.S.:
The assignment makes it work result = ...
!
Why does
result = self.table.addData([ {} ], True)
work, but not
self.table.addData([ {} ], True)
?
So the TabulatorTableBaseStandard
is a Flexx wrapper around the native Tabulator
class? Is it a JSComponent
or PyComponent
? And what about the code that had the insert_data
method?
Hi @almarklein
This is the rough structure of the wrapper:
flx.assets.associate_asset(__name__, "tabulator.js", get_file_content("tabulator/js/tabulator.js"))
flx.assets.associate_asset(__name__, "tabulator.css", get_file_content("tabulator/css/tabulator.css"))
class CustomTabulator(flx.PyWidget):
def init(self):
...
self.tabulator = TabulatorTableBaseStandard(...)
self.tabulator.reaction("row_added_base", self.row_added) # <-- IF THIS IS COMENTED OUT, THEN THE 'addData' METHOD CALL INSIDE 'row_insert' WORKS!!!
...
def row_added(self, *events):
pass
# More code ...
class TabulatorTableBaseStandard(flx.Widget):
def init(self, name):
global Tabulator
options = {
"height": "100%",
...
}
self.table = Tabulator(name, options)
...
@flx.emitter
def row_added_base(self, row_data, row_number):
return {
"row_data": row_data,
"row_number": row_number,
}
def row_insert(self, row_number, row_data, before):
new_data = {}
for k,v in row_data.items():
new_data[k] = v
self.table.addData([ new_data ], before, row_number)
self.row_added_base(row_data, row_number)
@flx.action
def row_insert_before(self, row_number):
row = self.table.getRows()[row_number]
self.row_insert(row_number, row.getData(), True)
# More code ...
After further trial and error I found that when I connect the row_added_base
reaction in the python CustomTabulator
's init
method to the ˙TabulatorTableBaseStandard˙ emitter, then the error happens everytime the row_insert_before
action is called. But if the connection to the reaction is commented out, then it works!
I apologize, but I have no idea what's going on. If you need any more information, just let me know.
Thanks
What if you instead do this?
@flx.reaction("tabulator .row_added_base")
def row_added(self, *events):
...
Tried it, same error:
JS: Command that failed to encode:
JS: INVOKE,TabulatorTableBaseStandard_34,_emit_at_proxy,[object Object]
Hey @almarklein , I managed to create a self contained example that produces the error. Here it is: tabulator_raw_flexx.zip
Pressing the button shows the error in the console, then if you comment out line 127 in tabs.py
, it works (the row actually gets inserted without error).
The problem is that in my actual production code I need to propagate the row_added_base
event from the CustomTabulator
to it's parent through an emmiter.
If you need any extra information, please let me know.
@almarklein
If there are any other ways of propagating an event from a flx.Widget
to a flx.PyWidget
, please let me know.
I'm a bit stuck at this point and don't know of how to solve this.
Thanks
I think what's going on is that you're adding data to the emitted event that can't be serialized. In the browser console, below the to lines that you reported, it mentions the actual error: TypeError: cannot encode object of type RowComponent.
Since you're listening for the event in Python, Flexx will transfer it over the websocket, and must thus serialize the data, and it does not know what a RowComponent
is. The best solution is probably to extract the necessary data (into e.g. a dict) and send that over instead. Also mind that undefined
cannot be serialized (but null
. None
can).
(It is technically also possible to define a serialization for custom objects, but there is not a proper public API for this yet, and I suspect it is overkill in this use-case.)
Ahhhh, you are absolutely right! I forgot that the Tabulator
rowAdded
callback uses a RowComponent
as a parameter.
Excellent, that's an easy fix. As you recomended, I'll just repackage the RowComponent
into a dictionary.
Thanks again!
🎆
Hi,
I'm trying to wrap Tabulator (http://tabulator.info) into Flexx. The problem I'm facing is this: Tabulator has a method
addData
with a JS example usage:Now I'm trying to call this method from Flexx with this example:
... but this throws the following exception at the second line:
I also tried some dummy data in place of the empty
dict
, but no difference. Any ideas?