Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    TileGrid reload clientOnly DataSource

    I have an application where the TileGrid and clientOnly DataSource components are used.
    When the application starts, everything is loaded and displayed correctly.
    But if I try to install new data in the DataSource using setCacheData, then the data is reloaded and the application freezes.
    The documentation for clientOnly DataSource says that data should be downloaded only once when the data is accessed for the first time.

    I suspect that I forgot to set the parameters for Tile Grid, but I do not know which ones.
    Version SNAPSHOT_v13.1d_2024-03-07 (2024-03-07)

    Below is my application code
    App.js
    Code:
    import React, { Component } from 'react';
    import 'smartclient-lgpl/release';
    import { DataSource, DSField, TileGrid, DVField } from 'smartclient-lgpl/react';
    class App extends Component {
      static typesMap = {
        "jpg": "pic",
        "png": "pic",
        "mp3": "sound",
        "mp4": "video",
        "doc": "doc",
        "xls": "table"
      };
      constructor(param) {
        super(param);
        this.selectedDocument = {};
      }
      transformDocuments(dsResponse, dsRequest, data) {
        let addDocument = {
          title: "add new document"
        };
        data.push(addDocument);
        dsResponse.data = data;
      }
      pictureFormatter(value, record, rowNum, colNum, grid) {
        let url = record.url;
        if (url != null) {
          let i = url.lastIndexOf(".") + 1;
          let n = url.lastIndexOf("?");
          if (n === -1) n = url.length;
          let ext = url.substring(i, n);
          let file = App.typesMap[ext];
          if (!file) {
            file = "doc"
          }
          return file + ".png";
        }
        return "add.png";
      }
      onDocumentClick(viewer, tile, record) {
        let irecord = viewer.getRecordIndex(record);
        if ((irecord + 1) === viewer.tiles.length) {
          let ds = viewer.getDataSource();
          let documents = ds.cacheData;
          let addDocument = documents.pop();
          documents.push({
            title: "new document",
            url: "www.aaa.com/newsound.mp3"
          });
          documents.push(addDocument);
          ds.setCacheData(documents);
        }
      }
      render() {
        return (
          <>
            <DataSource ID="documentsDS" clientOnly="true" dataURL="./api/documents.json"
              transformResponse={this.transformDocuments}
            >
              <fields>
                <DSField name="id" type="sequence" primaryKey="true" />
                <DSField name="picture" type="image" imageURLPrefix="../media/" />
                <DSField name="title" type="text" />
                <DSField name="url" type="text" />
              </fields>
            </DataSource>
            <TileGrid ID="documentsGrid" dataSource="documentsDS" autoFetchData="true"
              width="100%" height="100%" tileWidth="194" tileHeight="200"
              tileProperties={{ redrawOnStateChange: false }} detailViewerProperties={{ rowHeight: 18 }}
              recordClick={this.onDocumentClick.bind(this)}
            >
              <fields>
                <DVField name="picture" imageWidth="120" imageHeight="120" cellStyle="DVField" formatCellValue={this.pictureFormatter.bind(this)} />
                <DVField name="title" />
                <DVField name="url" escapeHTML="false" />
              </fields>
            </TileGrid>
          </>
        );
      }
    }
    export default App;
    documents.json
    Code:
    [
      {
        "title": "First document",
        "url": "manage/documents/api/get/items/downloadprojectfile.php?project=evo3_p0001",
        "isFile": "true"
      },
      {
        "title": "Second document",
        "url": "http://www.aaa.de/url2.png",
        "isFile": "false"
      }
    ]
    Screen by start application
    Click image for larger version  Name:	Screenshot1.png Views:	0 Size:	24.1 KB ID:	271858
    Screen after "add new document" click
    Click image for larger version  Name:	Screenshot2.png Views:	0 Size:	2.2 KB ID:	271859
    Last edited by Hirn; 14 Mar 2024, 22:39.

    #2
    We're looking into the issue causing the "Loading data..." message in the TileGrid to never clear, but trying to call setCacheData() on the DataSource is probably not the right approach here. You should instead just call DS.addData() to add a new record rather than directly tinkering with the cache. If you want your special "add new document" tile to always be last, you can accomplish that with a sort normalizer:
    Code:
    onDocumentClick(viewer, tile, record) {
        if (record.title == "add new document") {
          let ds = viewer.getDataSource();
          ds.addData({
            title: "new document",
            url: "www.aaa.com/newsound.mp3"
          });
          if (!viewer.sortSetup) {
            viewer.setSort([{
              property:"id",
              direction:"ascending",
              normalizer:function(item) {
                if (item.title == "add new document") return Infinity;
                return item.id;
              }
            }]);
            viewer.sortSetup = true;
          }
        }
      }
    Or better yet, you could have a dedicated button in your GUI add a new document. That would avoid the need to control placement of a special "add new document" tile.

    By the way, this issue isn't specific to our React support - it would be present even if you had coded your sample entirely in JavaScript.

    Comment


      #3
      Thank you for the answer and the proposed solution to my problem. It's just a salvation for me.

      Comment

      Working...
      X