Назначение обработчиков событий в a для l oop относится только к последней итерации - PullRequest
0 голосов
/ 18 марта 2020

Я встраиваю контент из Power BI в свое веб-приложение и хотел бы применить обработчики событий к каждому фрагменту. Это моя готовая функция:

$(document).ready(function () {
        var embededTiles = [];

        for (index = 0; index < configs.length; index++) {
            var container = document.getElementsByClassName('powerbi-embed')[index];

            embededTiles.push(powerbi.embed(container, configs[index]));
        }

        for (let i = 0; i < embededTiles.length; i++) {
            var tileEmbed = embededTiles[i];


            tileEmbed.off("tileLoaded");
            tileEmbed.on("tileLoaded", function (event) {
                console.log("tile " + i + " loaded");
            });

            tileEmbed.off("tileClicked");
            tileEmbed.on("tileClicked", function (event) {
                console.log(event);
                location.href = "/powerbi/report?reportId=" + event.detail.openReport.reportId;
            });
        }

    });

Во втором для l oop события "tileLoaded" и "tileClicked" применяются только к последнему элементу в массиве

1 Ответ

0 голосов
/ 19 марта 2020

Я был здесь раньше. Вот 2 дня, когда вы можете решить эту проблему.

Cleanest Way

Используйте .forEach вместо for l oop. Как это:


    embededTiles.forEach( function(tileEmbed, i){

      tileEmbed.off("tileLoaded");
      tileEmbed.on("tileLoaded", function (event) {
        console.log("tile " + i + " loaded");
      });

      tileEmbed.off("tileClicked");
      tileEmbed.on("tileClicked", function (event) {
        console.log(event);
        location.href = "/powerbi/report?reportId=" + event.detail.openReport.reportId;
      });

    })

Пересмотр того, что вы пытались использовать замыкание

Проблема в том, что ваш l oop проходит через все i до обработчик событий сработал. Таким образом, к тому времени, когда плитка embedded запускает событие tileLoaded или tileClicked, ваш l oop уже работает до тех пор, пока i не станет значением длины вашего массива. Вот почему работает только последний. Чтобы это исправить, вам нужно замыкание . Например:


    for (let i = 0; i < embededTiles.length; i++) {

       ((j) => {

         var tileEmbed = embededTiles[j];

         tileEmbed.off("tileLoaded");
         tileEmbed.on("tileLoaded", function (event) {
            console.log("tile " + j + " loaded");
         });

         tileEmbed.off("tileClicked");
         tileEmbed.on("tileClicked", function (event) {
            console.log(event);
            location.href = "/powerbi/report?reportId=" + event.detail.openReport.reportId;
         });

       })(i)  

    }

Это создаст немедленно вызванное функциональное выражение внутри вашего l oop с новой индексной переменной j. Для каждой итерации ваших циклов запускается j со значением i для этой итерации. Но значение i в этот момент закрывается и сохраняется в вашем обработчике событий для каждой итерации. Теперь у каждого элемента вашего массива есть собственный обработчик событий, связанный с его индексом в массиве.

...