Home > Back-end >  Rendering a div node created with d3.js in svelte?
Rendering a div node created with d3.js in svelte?

Time:08-27

I created a table in d3.js and return it as a div.node() and I am trying to render it in svelte. It's created with fetched data so I wrap it inside an sveltes asynchronous await syntax:

<div>
    {#await fetched}
    <p>...waiting</p>
    {:then result}
        {@html result}
    {/await}
</div>

where fetched is the result of the following:

function getData() 
    {
        return fetch("path").then(d => tabulate(d.json(), ['col', 'col2']));
    }
    let fetched = getData();

However, what is returned on the page is [object HTMLDivElement] instead of the actual table. The docs say it needs to be standalone HTML, I rendered it in a file and it worked. Should I create the element first in svelte and then select it instead? It works if I select a pre-existing div.

The accompanying d3.js function full credit to jfreels:

    function tabulate(data, columns) {
        const div = d3.create("div")
        
        let table = div.append('table')
        let thead = table.append('thead')
        let tbody = table.append('tbody');

        // append the header row
        thead.append('tr')
        .selectAll('th')
        .data(columns).enter()
        .append('th')
            .text(function (column) { return column; });

        // create a row for each object in the data
        let rows = tbody.selectAll('tr')
        .data(data)
        .enter()
        .append('tr');

        // create a cell in each row for each column
        let cells = rows.selectAll('td')
        .data(function (row) {
            return columns.map(function (column) {
            return {column: column, value: row[column]};
            });
        })
        .enter()
        .append('td')
            .text(function (d) { return d.value; });

        return div.node();
}

CodePudding user response:

The object is a DOM element, not HTML; but since it is already a fully functional element, it is not necessary to write it as HTML and make the browser re-parse it. As Corrl noted, that would also cause all event listeners to be lost.

You can easily attach the node using e.g. an action:

const append = (node, child) => node.append(child);
<div>
    {#await fetched}
        <p>...waiting</p>
    {:then result}
        <div use:append={result} />
    {/await}
</div>
  • Related