spotfiresoftware / spotfire-mods

Spotfire® Mods
https://spotfiresoftware.github.io/spotfire-mods/
Other
56 stars 41 forks source link

Read full data table #7

Closed MaxDNG closed 3 years ago

MaxDNG commented 3 years ago

Hi all,

I am having a lot of fun with the Mods api, great feature! For one use case I would like to get the content of the whole data table, not only the values of the specified axis. I tried looping over the columns name (which throws an error because axis is not defined) and digged in the documentation but couldn't find a method for that. Is it at all possible?

mrylande commented 3 years ago

Thanks for your feedback on Mods. Your request is reported in https://ideas.tibco.com/ideas/TS-I-8069.

objerke commented 3 years ago

Hi @MaxDNG, Would you mind elaborating why you need the underlying data table? It would be really useful for us to get some context.

MaxDNG commented 3 years ago

Hi @objerke, I cannot go into too much details, but basically we would like to use mods to display the complete data for a single record. We can do that with a workaround by requesting the user to specify all the columns they want to see, but for better user experience, we would like that to be automatic. By the way, is there a way to retrieve the content of a binary column ? They do not appear in the list of axes (which makes sense) but then it means we cannot display them, for example if we have images.

dhategan commented 3 years ago

By the way, is there a way to retrieve the content of a binary column ?

For now binary columns are not supported in the Mods API

objerke commented 3 years ago

@MaxDNG Thank you for the information. If you want to aid the end user, it is possible to programatically set an axis expression. Using multiple measures on a continuous axis allows for many column values to be displayed. The following reduced example shows how all columns can be set on a continuous axis, while the aggregation is split by some unique column. It is still an aggregated dataView but it will show values from each unique record.

Note: This is not very efficient since it will produce many rows to be sent to the mod. This form of displaying information is highly recommended to be limited by marking (e.g as a details visualization).

Spotfire.initialize(async (mod) => {
    const context = mod.getRenderContext();

    // This setup should be in its own read loop listening for changes to the columns and axes.
    const columns = await (await (await mod.visualization.mainTable()).columns()).filter(c => c.dataType.name !== "Binary");
    const nameOfRecordNoColumn = "baserowid()" // E.g [Record No]
    mod.visualization.axis("X").setExpression(`<${nameOfRecordNoColumn} NEST [Axis.Default.Names]>`);
    mod.visualization.axis("Y").setExpression(columns.map((c) => `UniqueConcatenate([${c.name}])`).join(" ,"));

    const reader = mod.createReader(mod.visualization.data());

    /**
     * Initiate the read loop
     */
    reader.subscribe(async function render(dataView) {
        let nodes = (await (await dataView.hierarchy("X")).root()).children;
        let text = "";
        for (const recordNode of nodes) {
            let rows = recordNode.rows();

            for (let index = 0; index < columns.length; index++) {
                text += columns[index].name + ": " + rows[index].continuous("Y").formattedValue() + "\r\n";
            }

            break;
        }

        const container = document.querySelector("#mod-container");
        container.textContent = text;

        context.signalRenderComplete();
    });
});

In manifest:

 "dataViewDefinition": {
        "axes": [
            {
                "name": "X",
                "mode": "categorical",
                "placement": "bottom"
            },
            {
                "name": "Y",
                "mode": "continuous",
                "allowMultipleMeasures": true,
                "dataTypes": { "allowString": true },
                "placement": "left"
            }
        ]
    },
MaxDNG commented 3 years ago

Thank you very much for your detailed solution. We ended up using something similar but I feel yours is more complete.