cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
AClerk
Solution Sage
Solution Sage

Auto Scrolling Table

Hey,

I started to explore custom visuals creation.

Is there a way to add an automatic scrolling to a table?
Pseudo:

While(TRUE)

   IF(Table has scrollbar > Start auto scroll down)

      IF(End of table > Start scroll up)

   Else(Do nothing)

 

Any ideas?

 

Ta!

 

 

13 REPLIES 13
amjesquillo
Frequent Visitor

Hi @AClerk ,

 

Did you already found a solution to this?

@amjesquillo 
No.
I found workarounds instead.

I'll be happy to find a solution for my initial request.

Cheers!

Hi guys,

 

Take an example below. It should help.

 

<html>
<head>
    <style>
        div.items {
            height: 100px;
            width: 200px;
            border: 1px solid black;
            overflow-y: scroll;
        }
        div.items div {
            height: 20px;
        }
    </style>
    <script>
        function addNewItem() {
            const itemsElement = document.getElementById("items");
            const newItem = document.createElement("div");
            newItem.innerText = "New item";
            itemsElement.appendChild(newItem);
            itemsElement.scrollTop = (itemsElement.children.length) * 20 - 100;
        }

        function autoScrollDown() {
            const itemsElement = document.getElementById("items");
            itemsElement.scrollTop = 0;
            stopPosition = (itemsElement.children.length) * 20 - 100;
            const timerId = setInterval(function () {
                if (itemsElement.scrollTop >= stopPosition) {
                    clearInterval(timerId);
                }
                itemsElement.scrollTop += 1;
            }, 100);
        }
    </script>
</head>
<body>
    <h1>Scroll positioning example</h1>
    <button onclick="addNewItem()">Add new item</button>
    <button onclick="autoScrollDown()">Auto Scroll Down</button>
    <br /><br />
    <div id="items" class="items">
        <div>Old item 1</div>
        <div>Old item 2</div>
        <div>Old item 3</div>
        <div>Old item 4</div>
        <div>Old item 5</div>
        <div>Old item 6</div>
        <div>Old item 7</div>
        <div>Old item 8</div>
    </div>
</body>
</html>

 

Kind Regards,

 

Evgenii Elkin,
Software Engineer
Microsoft Power BI Custom Visuals
pbicvsupport@microsoft.com

Hi @v-evelk 

Thanks for the info.

Did you try it inside a Power BI report?
While it works fine as a simple HTML page, it is not working for me inside a power BI report page.

+ I am not sure how to trigger the function to automatically start.

 

I have basic knowledge and experience in JS, sorry if I am missing any fundamental stuff here.

 

Cheers!

Hi,

 

Yes, it works perfectly inside a visual.

I checked this with creation of an initial visual by this instruction but I used beta version of tools that supports WebPack.

npm i -g powerbi-visuals-tools@beta

Then I inserted the code that I provided above with little adaption:

"use strict";
import "@babel/polyfill";
import "./../style/visual.less";
import powerbi from "powerbi-visuals-api";
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import IVisual = powerbi.extensibility.visual.IVisual;
import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions;
import VisualObjectInstance = powerbi.VisualObjectInstance;
import DataView = powerbi.DataView;
import VisualObjectInstanceEnumerationObject = powerbi.VisualObjectInstanceEnumerationObject;

import { VisualSettings } from "./settings";

function addNewItem() {
    const itemsElement = document.getElementById("items");
    const newItem = document.createElement("div");
    newItem.innerText = "New item";
    itemsElement.appendChild(newItem);
    itemsElement.scrollTop = (itemsElement.children.length) * 20 - 100;
}

function autoScrollDown() {
    const itemsElement = document.getElementById("items");
    itemsElement.scrollTop = 0;
    const stopPosition = (itemsElement.children.length) * 20 - 100;
    const timerId = setInterval(function () {
        if (itemsElement.scrollTop >= stopPosition) {
            clearInterval(timerId);
        }
        itemsElement.scrollTop += 1;
    }, 100);
}

export class Visual implements IVisual {
    private target: HTMLElement;
    private settings: VisualSettings    

    constructor(options: VisualConstructorOptions) {
        this.target = options.element;
        if (typeof document !== "undefined") {
            const container: HTMLElement = document.createElement("div");
            
            container.innerHTML = `
    <h1>Scroll positioning example</h1>
    <button id="addNewItemButton">Add new item</button>
    <button id="AutoScrollDownButton">Auto Scroll Down</button>
    <br /><br />
    <div id="items" class="items">
        <div>Old item 1</div>
        <div>Old item 2</div>
        <div>Old item 3</div>
        <div>Old item 4</div>
        <div>Old item 5</div>
        <div>Old item 6</div>
        <div>Old item 7</div>
        <div>Old item 8</div>
    </div>
            `;

            this.target.appendChild(container);

            const addBtn = document.getElementById("addNewItemButton");
            addBtn.addEventListener("click", addNewItem);

            const autoscrollBtn = document.getElementById("AutoScrollDownButton");
            autoscrollBtn.addEventListener("click", autoScrollDown);
        }
    }

    public update(options: VisualUpdateOptions) {

    }

    private static parseSettings(dataView: DataView): VisualSettings {
        return VisualSettings.parse(dataView) as VisualSettings;
    }

    /**
     * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the
     * objects and properties you want to expose to the users in the property pane.
     *
     */
    public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
        return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
    }
}

Styles I moved into .less file.

 

And that's it!

 

Please pay more attention in question of learning not only fundamental frontend things but modern things too becuse frontend is developing rapidly and without this knowledge it will be quite troubleshooting to develop Power BI visuals.

 

Kind Regards,

 

Evgenii Elkin,
Software Engineer
Microsoft Power BI Custom Visuals
pbicvsupport@microsoft.com

 

Hi guys,

 

Take an example below. It should help.

 

<html>
<head>
    <style>
        div.items {
            height: 100px;
            width: 200px;
            border: 1px solid black;
            overflow-y: scroll;
        }
        div.items div {
            height: 20px;
        }
    </style>
    <script>
        function addNewItem() {
            const itemsElement = document.getElementById("items");
            const newItem = document.createElement("div");
            newItem.innerText = "New item";
            itemsElement.appendChild(newItem);
            itemsElement.scrollTop = (itemsElement.children.length) * 20 - 100;
        }

        function autoScrollDown() {
            const itemsElement = document.getElementById("items");
            itemsElement.scrollTop = 0;
            stopPosition = (itemsElement.children.length) * 20 - 100;
            const timerId = setInterval(function () {
                if (itemsElement.scrollTop >= stopPosition) {
                    clearInterval(timerId);
                }
                itemsElement.scrollTop += 1;
            }, 100);
        }
    </script>
</head>
<body>
    <h1>Scroll positioning example</h1>
    <button onclick="addNewItem()">Add new item</button>
    <button onclick="autoScrollDown()">Auto Scroll Down</button>
    <br /><br />
    <div id="items" class="items">
        <div>Old item 1</div>
        <div>Old item 2</div>
        <div>Old item 3</div>
        <div>Old item 4</div>
        <div>Old item 5</div>
        <div>Old item 6</div>
        <div>Old item 7</div>
        <div>Old item 8</div>
    </div>
</body>
</html>

As you can see, it is not a question of Power BI things or Custom Visuals development at all. It is a question regarding JavaScript and Web Development so, please pay attention to such moments.

 

Kind Regards,

 

Evgenii Elkin,
Software Engineer
Microsoft Power BI Custom Visuals
pbicvsupport@microsoft.com

v-evelk
Microsoft
Microsoft

Hi,

 

We have implemented something similar for our Timeline Slicer visual.

If you use d3 selections, you can try to get HTML node from a selection and set scrolling properties as "scrollLeft" for instance.

 

You can find an example of the code here

https://github.com/Microsoft/powerbi-visuals-timeline/blob/master/src/visual.ts#L1527

 

Kind Regards,

 

Evgenii Elkin,
Software Engineer
Microsoft Power BI Custom Visuals
pbicvsupport@microsoft.com

Hi @v-evelk 
Thanks for the lead.

Any live demo of the project?
Thanks,

A

Hi,

 

You can see how it works here.

Also you can download a standard Timeline Slicer report form the store.

Then you need to reduce visual size, select one of the last granulas and enable option "Scroll position auto adjustment" and save the report. After reload of the report you will see that horizontal scrolling position was shifted to the selected granulas.

 

Evgenii Elkin,
Software Engineer
Microsoft Power BI Custom Visuals
pbicvsupport@microsoft.com

Thank you @v-evelk 

That is nice, but not what I am after.

I want a table to scroll automatically, when the tab/page is opened. No human interaction what so ever.

Cheers!
A

The example that I provided works exactly this way.

It automatically sets horizontal scrolling position to the selected granulas in timeline after timeline is rendered, there isn't any manual interactions except the moment when this feature must be enabled to make it working because this feature is optional.

 

Evgenii Elkin,
Software Engineer
Microsoft Power BI Custom Visuals
pbicvsupport@microsoft.com

Hi @v-evelk ,

The idea is to show the reports on a screen in the office. 

No one will have any interaction with the report.

 

So, if I have a table of 100 rows, I would like to show all records in a time period of 60 seconds, for instance.

I would like the table to scroll automaticcally, and show all the records.

This is an example of something that reminds of what I am after - https://stackblitz.com/github/NagRock/ngx-auto-scroll-example?file=src%2Fapp%2Fapp.component.ts

 

The moment the page loads, the div starts filling up with values.

But instead of a div, I want a Power BI table.

 

Thanks!

Hi,

 

In fact, I don't see a problem. You can subscribe on an event if there is an event that happens after a row adding or anyway you can detect a moment when a row was added and then run the code that I provided.

Or if you want just to scroll down existing records you can use setTimeout or setInterval methods to scroll down step by step for every tick.

Also, there are a bunch of different libraries for changes detection and animation and now it is possible to use them if you use the beta version of PowerBI-visuals-tools that lets you to use WebPack for a package building.

 

Kind Regards,

 

Evgenii Elkin,
Software Engineer
Microsoft Power BI Custom Visuals
pbicvsupport@microsoft.com

Helpful resources

Announcements
MBAS on Demand

2021 Release Wave 2 Plan

Power Platform release plan for the 2021 release wave 2 describes all new features releasing from October 2021 through March 2022.

July 2021 Update 768x460.png

Check it out!

Click here to read more about the July 2021 Updates

Power Query PA Forum 768x460.png

Check it out!

Did you know that you can visit the Power Query Forum in Power BI and now Power Apps

Urdu Hindi D365 Bootcamp 768x460.png

Urdu Hindi D365 Bootcamp

Dont miss our very own April Dunnam’s The Developer Guide to the Galaxy! Find out what the Power Platform has to offer for the traditional developer.

Top Solution Authors