flekschas / piling.js

A general framework and library for exploring thousands of small multiples

Home Page:https://piling.js.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Reloading items problem

1226419 opened this issue · comments

Unfortunately, I ran into a problem when using the library:

Observed behavior

We have scatterplots that are automatically clustered and piled accordingly.
That works great until we change data.
If we change the data while all the scatterplots are not in a pile the data and piling are reloaded without problems.
But as soon as we create piles of Scatterplots, be it automatically or by draging and dropping, no piling is created and the following error message occurs:

TypeError: null has no properties
    destroy sprite.es.js:493
    destroy piling.esm.js:13550
    onDestroy piling.esm.js:13781
    destroy piling.esm.js:13681
    clear piling.esm.js:13810
    clear piling.esm.js:13809
    destroy piling.esm.js:25658
    loadData PileTest.vue:266
    VueJS 11
    _callee3$/< App.vue:398
    promise callback*_callee3$ App.vue:368
    tryCatch piling.esm.js:67
    invoke piling.esm.js:287
    method piling.esm.js:120
    Babel 4
    loadAllPlotsComp App.vue:364
    VueJS 4
    onChange form-select.js:89
    VueJS 9
    onChange form-select.js:87
    VueJS 3

The stack trace of the error shows a problem at row 25658 in the piling.esm.js that executes the following function:
badgeFactory.destroy();

This does not happen if we first split all the piles this.piling.splitAll() and then load the data. Alternatively, if I remove the "badgeFactory.destroy();" line in the piling.esm.js the error does again not occur and everythings seems to work fine as far as i can judge.

Additional Information

All the props and setup for the piling:

      this.piling=createPilingJs(document.getElementById('demo'))
      this.piling.set('renderer', scatterplotRenderer.renderer);
      this.piling.set('coverAggregator',coverAggregator);
      this.piling.set('coverRenderer', scatterplotCoverRenderer.renderer);
      this.piling.set('items', this.items);
      this.piling.set('darkMode', false);
      this.piling.set('columns', 6);
      this.piling.set('cellPadding', 9);
      this.piling.set(cellAspectRatio);
      this.piling.set(pileOrderItems);
      this.piling.set('pileLabelTextOpacity',1);
      this.piling.set('pileOpacity',1);
      this.piling.set('zoomScale',(x) => x);
      this.piling.set('pileSizeBadge',true)
      this.piling.set('pileSizeBadgeAlign',['top','left'])
      this.piling.set('pileItemOffset',[0,0])

automatic piling although it also happens with just dragging:

      this.piling.subscribe('itemUpdate', this.pileMaker)
      this.piling.subscribe('pilesPositionEnd', this.pileArranger)
    pileMaker () {
        this.piling.groupBy('category', (item)=> item.cluster);
      },
    pileArranger () {
        this.piling.arrangeBy('data', (item)=> item.cluster);
      },

Expected behavior

  • Reloading the data also should be possible when the scatterplots are within piles.

Thanks for posting the issue here.

Can you do me a favor and try the same thing without the following two settings?

this.piling.set('pileSizeBadge', true)
this.piling.set('pileSizeBadgeAlign', ['top', 'left'])

It sounds like the issue is related to badge class.

Thank you for your quick answer!

I just tested it and without these two settings the problem does not occur.
So yes it is connected to the badge class.

Just to clarify, the issue you're experiencing is related to changing the item's associated data.

So the steps are:

  1. Load some scatterplots
  2. Change the data of the scatterplots. E.g., piling.set('items', newItems)
  3. Pile items

Step 3 leads to the above error. Is that correct?

Edit:
I am asking because I somehow do not run into the issue. To clarify, I'm using the following code to test the issue:

  piling.subscribe(
    'itemUpdate',
    async () => {
      await piling.groupBy('category', (item) => item.id % 5); // Random grouping by index
      await new Promise((resolve) => setTimeout(resolve, 500)); // I found another glitch that can be circumvented with this line
      await piling.arrangeBy('data', (state, id, i) => i); // Reorder by index
      piling.set('items', otherItems); // Replacing the scatterplots
    },
    1
  );

Here's how it looks like for me:

May-17-2021 17-43-27

Thank you for looking into the problem! I now realised that there was one part within our code that was not setting new items to the piling and instead destroying and recreating the piling. I assume this part was causing the problem.

  this.piling.destroy()
  this.items=[]
  this.createScatterplotPiles()

I now changed it to piling.set('items', newItems) and the problem does not occur anymore and the badges are shown.
Thank you again for your help!

Oh great! Thanks a lot for posting the issue. I found a couple of other glitches along the way, that I am hoping to fix.

Just FYI, the destroy() function is final. Meaning that after you have destroyed a piling instance you cannot use it anymore.

Also, please let me know if you run into any other issues. I am happy to help out.

Closing this issue for now as it seems to have been resolved.