Tuesday, 26 August 2025

New color logic

Of course. Let's do a fresh, complete implementation from start to finish. This guide will contain all the corrected code and steps in one place to get the exact result you described.

Your Goal:

  • Selected Node (e.g., APAC): Green

  • Parent Path (e.g., Acme): Light Red

  • Child Sub-tree (e.g., nodes under APAC): Amber

We will first set up Power BI, then modify the Deneb JSON.


Part 1: Power BI Setup

This part ensures that the slicer selection is correctly passed to the Deneb visual without filtering the data.

Step 1.1: Create the Dynamic Slicer Table

This DAX formula creates a single table that will be used for our slicers.

  1. In Power BI, go to the Data view.

  2. Click New table.

  3. Paste this formula. (Remember to replace 'YourMainDataTable' with the name of your actual data table).

    Code snippet
    Dynamic Slicer Table = 
    DISTINCT(
        UNION(
            // Level 1
            FILTER(SELECTCOLUMNS('YourMainDataTable', "Level", "Level 1", "DisplayName", [level1], "NodeID", [level1]), [DisplayName] <> BLANK()),
            // Level 2
            FILTER(SELECTCOLUMNS('YourMainDataTable', "Level", "Level 2", "DisplayName", [level2], "NodeID", [level1] & "|" & [level2]), [DisplayName] <> BLANK()),
            // Level 3
            FILTER(SELECTCOLUMNS('YourMainDataTable', "Level", "Level 3", "DisplayName", [level3], "NodeID", [level1] & "|" & [level2] & "|" & [level3]), [DisplayName] <> BLANK()),
            // Level 4
            FILTER(SELECTCOLUMNS('YourMainDataTable', "Level", "Level 4", "DisplayName", [level4], "NodeID", [level1] & "|" & [level2] & "|" & [level3] & "|" & [level4]), [DisplayName] <> BLANK()),
            // Level 5
            FILTER(SELECTCOLUMNS('YourMainDataTable', "Level", "Level 5", "DisplayName", [level5], "NodeID", [level1] & "|" & [level2] & "|" & [level3] & "|" & [level4] & "|" & [level5]), [DisplayName] <> BLANK())
        )
    )
    

Step 1.2: Create the Slicers on your Report

  1. Add a slicer to your report page and use the Level field from your new Dynamic Slicer Table.

  2. Add a second slicer and use the DisplayName field from the Dynamic Slicer Table.

Step 1.3: Create the DAX Measure

This measure captures the full ID of the item you select.

  1. Click New measure.

  2. Enter this formula:

    Code snippet
    Selected Node ID = SELECTEDVALUE('Dynamic Slicer Table'[NodeID], "")
    

Step 1.4: Configure the Deneb Visual

  1. Select your Deneb visual.

  2. Drag your measure [Selected Node ID] into the "Values" data role.

  3. Rename the measure in the field well to be exactly pbi_selected_node.


Part 2: Deneb JSON Modification

For this part, please start with your original, working Deneb JSON to ensure we have a clean slate.

Step 2.1: Add All Necessary Signals

  1. Open the Deneb editor.

  2. Find the "signals": [...] array.

  3. Add the following complete and corrected block of four signals inside the array.

    JSON
    {
    "name": "slicerSelection",
    "value": null,
    "update": "data('dataset_parametertable') && length(data('dataset_parametertable')) > 0 ? data('dataset_parametertable')[0]['SelectionValue'] : null"
    },
    {
    "name": "slicerHighlightPath",
    "value": [],
    "update": "slicerSelection ? pluck(treeAncestors('treeCalcs', slicerSelection), 'id') : []"
    },
    {
    "name": "slicerParentPath",
    "value": [],
    "update": "slicerSelection ? slice(slicerHighlightPath, 0, -1) : []"
    },
    {
    "name": "slicerDescendantsPath",
    "value": [],
    "update": "slicerSelection ? pluck(data('slicerDescendantsData'), 'id') : []"
    }

Step 2.2: Modify the Node Colors

This step applies the Green/Red/Amber logic to the nodes.

  1. Scroll down to the "marks": [...] array and find the group mark with "name": "node".

  2. Inside its "encode": { "update": { ... } } block, replace the fill and stroke properties with these new ones:

    JSON
              "fill": {
                "signal": "slicerSelection && slicerSelection !== '' ? (datum.id === slicerSelection ? '#d4edda' : indexof(slicerParentPath, datum.id) > -1 ? '#f8d7da' : indexof(slicerDescendantsPath, datum.id) > -1 ? '#fff3cd' : '#ffffff') : merge(hsl(scale('colour', datum.treeParent)), {l:0.94})"
              },
              "stroke": {
                "signal": "slicerSelection && slicerSelection !== '' ? (datum.id === slicerSelection ? '#155724' : indexof(slicerParentPath, datum.id) > -1 ? '#721c24' : indexof(slicerDescendantsPath, datum.id) > -1 ? '#856404' : '#d3d3d3') : merge(hsl(scale('colour', datum.treeParent)), {l:0.79})"
              },
    

Step 2.3: Modify the Link Colors

This makes the connecting lines match the node colors.

  1. In the "marks" array, find the first mark ("type": "path").

  2. Replace its "stroke" property with the following code:

    JSON
              "stroke": {
                "signal": "slicerSelection && slicerSelection !== '' ? (indexof(slicerHighlightPath, datum.target.id) > -1 ? '#721c24' : indexof(slicerDescendantsPath, datum.target.id) > -1 ? '#856404' : '#d3d3d3') : scale('colour', reverse(pluck(treeAncestors('treeCalcs', datum.target.id), 'id'))[1])"
              }
    

Step 2.4: Apply Changes

Click the "Apply" button (the play icon) in the Deneb editor.

After following these steps, your visual should now work exactly as you have described.

No comments:

Post a Comment