vega-embed: Missing example of use of RequireJS for vega-embed

Hi, I would like to dynamically load vega-embed and all its dependencies (vega and vega-lite, which themselves depend on d3, etc.) using the RequireJS library. From previous discussions (see https://github.com/vega/vega/issues/171 among else) I know that vega and D3 are AMD-compatible, so this ought to be doable.

What I am missing is an example of use of vega-embed with RequireJS. The code below throws errors, and I’m not sure if it is due to an incompatibility of vega-embed with RequireJS or my incorrect use or the later library:

requirejs.config({
    paths: {
        d3: "https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js?noext",
        d3_geo_projection: "https://cdnjs.cloudflare.com/ajax/libs/d3-geo-projection/0.2.16/d3.geo.projection.min.js?noext",
        d3_layout_cloud: "https://vega.github.io/vega-editor/vendor/d3.layout.cloud.js?noext",
        topojson: "https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.20/topojson.min.js?noext",
        vg: "https://cdnjs.cloudflare.com/ajax/libs/vega/2.5.1/vega.min.js?noext",
        vl: "https://vega.github.io/vega-lite/vega-lite.js?noext",
        vg_embed: "https://vega.github.io/vega-editor/vendor/vega-embed.js?noext"
    },
    shim: {
        vg_embed: {deps: ["vg", "vl"]},
        vl: {deps: ["vg"]},
        vg: {deps: ["d3", "d3_geo_projection", "d3_layout_cloud", "topojson"]},
        d3_geo_projection: {deps: ["d3"]},
        d3_layout_cloud: {deps: ["d3"]}
    }
});

require(["vg", "vl", "vg_embed"], function(vg, vl, vg_embed) {
    var vg_specification = {
        mode: "vega-lite",
        spec: {
            "description": "A simple bar chart with embedded data.",
            "data": {
                "values": [
                    {"a": "A", "b": 28}, {"a": "B", "b": 55}, {"a": "C", "b": 43},
                    {"a": "D", "b": 91}, {"a": "E", "b": 81}, {"a": "F", "b": 53},
                    {"a": "G", "b": 19}, {"a": "H", "b": 87}, {"a": "I", "b": 52}
                ]
            },
            "mark": "bar",
            "encoding": {
                "x": {"field": "a", "type": "ordinal"},
                "y": {"field": "b", "type": "quantitative"}
            }
        }};

    vg.embed("#vis", vg_specification,
        function (error, chart) {
            chart({el:"#vis"}).update();
        });
});

This throws a TypeError: Cannot read property 'util' of undefined and TypeError: Cannot read property 'embed' of undefined.

Best, Aurélien

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 18 (8 by maintainers)

Commits related to this issue

Most upvoted comments

Thank you @tanyaschlusser for posting the code!

Vega-Embed should now be compatible with requirejs. I made some major improvements by switching to rollup. See https://beta.observablehq.com/@domoritz/hello-vega-embed for an example.

I think the paths above are necessary to tell require where to find the libraries.

Awesome. Just to document it here is the solution:

requirejs.config({
    paths: {
        d3: "https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js?noext",
        d3_geo_projection: "https://cdnjs.cloudflare.com/ajax/libs/d3-geo-projection/0.2.16/d3.geo.projection.min.js?noext",
        d3_layout_cloud: "https://vega.github.io/vega-editor/vendor/d3.layout.cloud.js?noext",
        topojson: "https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.20/topojson.min.js?noext",
        vg: "https://cdnjs.cloudflare.com/ajax/libs/vega/2.5.1/vega.min.js?noext",
        vl: "https://vega.github.io/vega-lite/vega-lite.js?noext",
        vg_embed: "https://vega.github.io/vega-editor/vendor/vega-embed.js?noext"
    },
    shim: {
        vg_embed: {deps: ["vg.global", "vl.global"]},
        vl: {deps: ["vg"]},
        vg: {deps: ["d3", "d3_geo_projection", "d3_layout_cloud", "topojson"]},
        d3_geo_projection: {deps: ["d3"]},
        d3_layout_cloud: {deps: ["d3"]}
    }
});

define('vg.global', ['vg'], function(vgGlobal) {
    window.vg = vgGlobal;
});

define('vl.global', ['vl'], function(vlGlobal) {
    window.vl = vlGlobal;
});



require(["vg_embed"], function(vg_embed) {
    var vg_specification = {
        mode: "vega-lite",
        spec: {
            "description": "A simple bar chart with embedded data.",
            "data": {
                "values": [
                    {"a": "A", "b": 28}, {"a": "B", "b": 55}, {"a": "C", "b": 43},
                    {"a": "D", "b": 91}, {"a": "E", "b": 81}, {"a": "F", "b": 53},
                    {"a": "G", "b": 19}, {"a": "H", "b": 87}, {"a": "I", "b": 52}
                ]
            },
            "mark": "bar",
            "encoding": {
                "x": {"field": "a", "type": "ordinal"},
                "y": {"field": "b", "type": "quantitative"}
            }
        }};

    vg_embed("#vis", vg_specification,
        function (error, chart) {
            // do something that requires an update, then...
            chart.view.update();
        });
});

Thanks @peller ! This is exactly the kind of trick it would have taken me ages to come up with. I’ll finally be able to add straightforward Vega grammar-based visualization capabilities to my Jupyter kernels. Thanks again!