I have written a simple widget in Jupyter Notebook which is a checkbox table. Now, I am trying to migrate this widget to Jupyter Lab. However, I am unable to find a way to insert JavaScript in a running notebook to build my widget.
I have read the new ipywidget8 tutorial, but I think creating a code package is too heavy for this small feature. I hope to achieve this functionality without building a package, like the ipywidget7 style.
ipywidget8: https://ipywidgets.readthedocs.io/en/8.0.5/examples/Widget%20Custom.html#front-end-typescript
ipywidget7: https://ipywidgets.readthedocs.io/en/7.x/examples/Widget%20Custom.html#Front-end-(JavaScript)
Here is my front-end code:
require.undef("my_widgets");
define("my_widgets", ["@jupyter-widgets/base"], function(widgets) {
var TableView = widgets.DOMWidgetView.extend({
// Render the view.
render: function() {
this.table_changed();
// Python -> JavaScript update
this.model.on("change:table", this.table_changed, this);
// JavaScript -> Python update
this.el.onchange = this.input_changed.bind(this);
// Script
$(this.el).on("click", ".my-table tbody tr", function (event) {
if (event.target.type != 'checkbox'){
$(this).find(".my-chk")[0].click()
}
});
},
table_changed: function() {
this.el.innerHTML = this.model.get("table");
},
input_changed: function() {
let value = [];
let jcheck = $(this.el).find(".my-chk");
for (let i=0;i<jcheck.length;i++) {
if (jcheck[i].checked) {
value.push(i)
}
};
$(this.el).find(".my-table")[0].setAttribute("date-value", value.join());
this.model.set('value', value);
this.model.save_changes();
},
});
return {
TableView: TableView,
};
});
Here is my back-end code:
import traitlets
from jinja2 import Template
from ipywidgets import Layout, DOMWidget, register
@register
class TaskTable(DOMWidget):
_view_name = traitlets.Unicode('TableView').tag(sync=True)
_view_module = traitlets.Unicode('my_widgets').tag(sync=True)
value = traitlets.List([], help="selected").tag(sync=True)
table = traitlets.Unicode('', help="rendered HTML table").tag(sync=True)
@traitlets.validate('value')
def _valid_value(self, proposal):
proposal['value'] = [int(x) for x in proposal['value']]
return proposal['value']
def render(self, head, body):
thead = ['#'] + head
tbody = body
self.table = template.render(head=thead, body=tbody)
template = Template(STATICS_TaskTable)
STATICS_TaskTable = """
<table class="my-table">
<thead>
<tr>
{%- for th in head -%}
<th>{{ th }}</th>
{%- endfor %}
</tr>
</thead>
<tbody>
{%- for row in body -%}
<tr>
{%- for cell in row -%}
{%- if loop.first -%}
<th><input class="my-chk" type="checkbox"> {{ cell }}</th>
{%- else -%}
<td>{{ cell }}</td>
{%- endif -%}
{%- endfor -%}
</tr>
{%- endfor -%}
</tbody>
</table>
"""
w = TaskTable()
w.render(['foo', 'bar'], [[1, 'A', 'S'], [2, 'D', 'F']])
w
I tried to add jQuery and RequireJS to the page, but only got an error message Error displaying widget: model not found
I could not found a page like "front-end-javascript" in the ipywidget8 tutorial.