In order to try to illustrate what I am inquiring about, the code below shows the number of outputs for a CodeCell. In the first console.log I am not using the model
and in the second console.log I am using the model
in order to get this length. I am trying to understand the model
concept.
What is a model
? I realize this might be an obtuse question. However, I am struggling to understand this concept, so I thought perhaps someone could shed light on it for me.
const extension: JupyterFrontEndPlugin<object> = {
id: "etc-jupyterlab-telemetry:plugin",
autoStart: true,
requires: [INotebookTracker],
activate: (app: JupyterFrontEnd, nbTracker: INotebookTracker) => {
window.nbApp = app;
console.log("JupyterLab extension etc-jupyterlab-telemetry is activated!");
nbTracker.widgetAdded.connect(async (tracker: INotebookTracker, nbPanel: NotebookPanel) => {
await nbPanel.revealed;
nbPanel.content.widgets.forEach((cell: Cell<ICellModel>) => {
if (cell.model.type === "code") {
console.log((cell as CodeCell).outputArea.widgets.length); // Not Model output
console.log((cell as CodeCell).model.outputs.length); // Model output
}
});
});
return {
};
}
};
It appears that what distinguishes a Cell
from a CellModel
is that the Cell
seems to represent the DOM node, or its visual representation, and the CellModel
seems to represent the “data” contained by the cell.
Right. This model layer (aping, but not entirely implementing the MVC pattern) was added (vs just slamming stuff into the DOM with jQuery in notebook
) so that a single thing (whether it’s a single output, or a whole notebook) could be rendered in multiple places on the page and stay in sync. This is how Create new View for Output and Create New View for Notebook works.
Lumino doesn’t have a The One Model, so in Lab you’ll see a number of models, either MimeModel
, DocumentModel
, or VDomModel
, or written whole-cloth with no super
implementing signals themselves. Notebook and (its children) are always special!
Zooming in a bit, the VDomModel
is used heavily in the React-derived widgets, and kinda fudges over that in classical React, the “model” is split into props, immutable, one-way content that a component must abide, and state, which the component can change. But then that community rapidly bifurcates into redux
, mobx
, etc. which encourage a single global “store” object, for which Lab doesn’t have an equivalent, for better or for worse.
1 Like
I don’t know if I missed it somewhere, but I think it would be incredibly helpful for people developing extensions to provide a document that describes the Widget
-model
pattern. It seems this is the de-facto way to synchronise data between widgets but as far as I can tell is not mentioned in any of the examples/ docs.
It’s touched on in Documents — JupyterLab 3.0.14 documentation, but this is written in a way that implies that models are particular to Documents and it doesn’t talk about them in more general terms.
If the Widget example (extension-examples/index.ts at 8bc09d2839efed8078c9fbc43da0fd39a0b7d0a3 · jupyterlab/extension-examples · GitHub) was modified to include a model - and even better extended to demonstrate syncing between multiple widgets, I think this would be incredibly instructive.
It seems to me that hooking into pre-existing JLab functionality is quite well supported/ documented, but re-using and extending it is quite challenging at present.
I’ve been taking quite a deep dive into the source for a cool extension I’m trying to make. Very happy to discuss all things further!
2 Likes