manzt / anywidget

jupyter widgets made easy
https://anywidget.dev
MIT License
451 stars 35 forks source link

cytoscape.js based widget not rendering #626

Closed anmolbhatia05 closed 1 month ago

anmolbhatia05 commented 1 month ago

Hello all,

I am trying to create a widget using anywidget and cytoscape.js in a vs code jupter notebook env. My aim is to create a graph visualiser and editor for my thesis.

The following code wont render anything when the cell is executed.

import anywidget
import traitlets

class Widget(anywidget.AnyWidget):
    _esm = """
    import cytoscape from "https://cdn.jsdelivr.net/npm/cytoscape@3.30.1/+esm";

    function render({ model, el }) {
      let cy = cytoscape({
        elements: [ // list of graph elements to start with
          { data: { id: "a" } }, // node a
          { data: { id: "b" } }, // node b
          { data: { id: "ab", source: "a", target: "b" } } // edge ab
        ],
        style: [ // the stylesheet for the graph
          {
            selector: "node",
            style: {
              "background-color": "#666",
              "label": "data(id)"
            }
          },
          {
            selector: "edge",
            style: {
              "width": 3,
              "line-color": "#ccc",
              "target-arrow-color": "#ccc",
              "target-arrow-shape": "triangle",
              "curve-style": "bezier"
            }
          }
        ],
        layout: {
          name: "grid",
          rows: 1
        }
      });
      cy.mount(el);
      console.log(el);
      console.log(cy);
    }

    export default { render };
    """
    _css="""
    """

w = Widget()
w

This is the output of the cell

Screenshot 2024-07-24 at 17 10 38

The dev tools output also seems fine -

Screenshot 2024-07-24 at 17 18 03

Any advice/directions/critique is welcome!

manzt commented 1 month ago

Thanks for sharing your project. It sounds exciting!

Your issue seems related to integrating cytoscape.js rather than anywidget itself. I'd like to avoid adding noise to the anywidget issues with challenges that aren't related to anywidget functionality. For help with this integration, I'd recommend posting in GitHub discussions or our Discord.

That said, a quick glimpse at the documentation has a very distinct disclaimer:

Note that Cytoscape.js uses the dimensions of your HTML DOM element container for layouts and rendering at initialisation. Thus, it is very important to place your CSS stylesheets in the before any Cytoscape.js-related code. Otherwise, dimensions may be sporadically reported incorrectly, resulting in undesired behaviour.

import anywidget
import traitlets

class Widget(anywidget.AnyWidget):
    _esm = """
    import cytoscape from "https://cdn.jsdelivr.net/npm/cytoscape@3.30.1/+esm";

    function render({ model, el }) {
        let container = document.createElement("div");
        container.style.height = "300px";
        el.appendChild(container)

        let cy = cytoscape({
          container: container,
          elements: [ // list of graph elements to start with
            {  data: { id: 'a' } },
            { data: { id: 'b' } },
            { data: { id: 'ab', source: 'a', target: 'b' } }
          ],
          style: [ // the stylesheet for the graph
            {
              selector: 'node',
              style: {
                'background-color': '#666',
                'label': 'data(id)'
              }
            },
            {
              selector: 'edge',
              style: {
                'width': 3,
                'line-color': '#ccc',
                'target-arrow-color': '#ccc',
                'target-arrow-shape': 'triangle',
                'curve-style': 'bezier'
              }
            }
          ],
          layout: { name: 'grid', rows: 1 }
        });
    }

    export default { render };
    """

w = Widget()
w

The issue with your example is that your container (el) doesn't have a height.