view/download icons missing when using ViewFileItem

SmartClient Version: v13.1p_2025-11-25/AllModules Development Only (built 2025-11-25)

Hi, I’m trying to use ViewFileItem with the #upload example.
After uploading a file successfully, and selecting the record in the grid, I would expect to see the preview and download icons in the viewForm, but they don’t show up.
Here is the code I’m using:

<DataSource ID="mediaLibrary" serverType="sql" tableName="mediaLibrary">
    <fields>
        <field name="pk" type="sequence" hidden="true" primaryKey="true"/>
        <field name="title"/>
        <field name="image" type="binary" maxFileSize="5242880" required="true"/>
    </fields>
</DataSource>
isc.DynamicForm.create({
    autoDraw: false,
    ID: "uploadForm", width: 300,
    dataSource: mediaLibrary,
    fields: [
        { name: "title", required: true },
        { name: "image", type: "imageFile", multiple:false, hint: "Maximum file size is 5 MiB" },
        { title: "Save", type: "button",
            click: function () {
                this.form.saveData("if(dsResponse.status>=0) uploadForm.editNewRecord()");
            }
        }
    ]
});

isc.DynamicForm.create({
    autoDraw: false,
    ID: "viewForm",
    dataSource: mediaLibrary,
    width: "100%",
    fields: [
        { name: "title", title: "Title", type: "text", width: "*" },
        { name: "image", title: "image", editorType: "ViewFileItem", showFileInline:false,
            startRow: false, endRow: false
        }
    ]
});

isc.ListGrid.create({
    autoDraw: false,
    ID: "mediaListGrid",
    width: "100%",
    height: 224,
    autoFetchData: true,
    recordClick:"viewForm.editRecord(record)",
    dataSource: mediaLibrary
});

isc.VLayout.create({
    autoDraw: false,
    ID:"mainLayout",
    width:500,
    height:250,
    members:[viewForm, mediaListGrid]
});

isc.HStack.create({
    width:"100%",
    membersMargin: 10,
    members:[uploadForm, mainLayout]
});

Is there an issue or am I missing something?

We just tested your sample code from the showcase and both icons are present and functioning correctly. Tested with various skins from the Flat and Enterprise series.

For instance:
Tahoe:

Stratus:

Please retest and let us know if there is anything else in your code that was not included in your post.

Regards
Isomorphic Software

Hi, I wasn’t referring to the icons on the grid records, but to the icons on the ViewFileItem inside the viewForm (above the grid).

The documentation for ViewFileItem explicitly mentions them:

OK. We were able to reproduce the issue and we have fixed it. Please try again with tomorrow’s builds (November 28).

Regards
Isomorphic Software

Thanks, I’ll try it as soon as it’s available.

I also noticed that in the docs for FileItem/ViewFileItem, in the displayCanvas/displayForm/displayItem properties, a “blob” field type is mentioned:

However, I can’t find any documentation for a blob FieldType.

SmartClient Version: v13.1p_2025-11-28/AllModules Development Only (built 2025-11-28)

I see it’s fixed, thank you very much!

SmartClient Version: v13.1p_2025-12-03/AllModules Development Only (built 2025-12-03)

Hi, I think I’ve found another problem.
In a ViewFileItem I’m trying to customize the displayItem that shows the file name, but it doesn’t seem to work.

I modified the customBinaryField example by adding displayItemProperties, but the formatValue defined there is not being called:

isc.DynamicForm.create({
    ID: "formView",
    width: "100%",
    dataSource: customBinaryField,
    fields: [
           {name: "id", width: 150, canEdit:false},
        {name: "file", canEdit:false, editorType:"ViewFileItem",
             displayItemProperties: {
                 formatValue: function (value, record, form, item) {
                     return "foo";
                 }
             }
        }
    ]
});

isc.DynamicForm.create({
    ID: "formEdit",
    width: 100,
    dataSource: customBinaryField,
    fields: [
        {name: "id", width: 150, required: true},
        {name: "file", required: true}
    ]
});

isc.IButton.create({
    ID: "uploadButton",
    title: "Upload",
    width: 100,
    click: function(){
        formEdit.saveData("if(dsResponse.status>=0) formEdit.editNewRecord()");
    }
});

isc.VLayout.create({
    ID: "vLayoutForms",
    width: 100,
    members: [
        isc.Label.create({
            contents: "Editor",
            width: 50,
            height: 25,
            autoDraw: true,
            baseStyle: "exampleSeparator"
        }),
        formEdit,
        uploadButton,
        isc.Label.create({
            contents: "View",
            width: 50,
            height: 25,
            autoDraw: true,
            baseStyle: "exampleSeparator"
        }),
        formView
    ]
});

isc.ListGrid.create({
    ID: "listGrid",
    width:500, height:224,
    dataSource: customBinaryField,
    selectionType: "single",
    autoFetchData: true,
    fields:[
        {name:"id", width:100},
        {name:"file", width:380}
    ],
    recordClick: function(viewer, record, recordNum, field, fieldNum, value, rawValue) {
        formEdit.editSelectedData(listGrid);
        formView.editSelectedData(listGrid);
    }
});

isc.HLayout.create({
    ID: "hLayoutTop",
    width: 700,
    layoutMargin:10,
    membersMargin: 10,
    members:[listGrid, vLayoutForms]
});

isc.Button.create({
    ID: "buttonDownload",
    width:200,
    title: "Download Selected File",
    click: function () {
        var selectedRecord = listGrid.getSelectedRecord();
        if (selectedRecord == null) {
            isc.say("You must select one record");
            return;
        }
        customBinaryField.downloadFile(selectedRecord);
    }
});

isc.Button.create({
    ID: "buttonView",
    width:200,
    title: "View Selected File",
    click: function () {
        var selectedRecord = listGrid.getSelectedRecord();
        if (selectedRecord == null) {
            isc.say("You must select one record");
            return;
        }
        customBinaryField.viewFile(selectedRecord);
    }
});


isc.HLayout.create({
    ID: "hLayoutButtons",
    width: 500,
    layoutMargin: 10,
    membersMargin: 10,
    members: [buttonDownload, buttonView]
});

isc.VLayout.create({
    ID: "vLayout",
    width: 300,
    members: [hLayoutTop, hLayoutButtons]
});

We just fixed this issue. Please try again with tomorrow’s builds (December 5).

Regards
Isomorphic Software

SmartClient Version: v13.1p_2025-12-05/AllModules Development Only (built 2025-12-05)

I see it’s working now, thank you very much!

Hello, I actually noticed that the formatValue gets called 5 times for every formView.editSelectedData(listGrid). Is it normal?

Also, value and record in the formatValue don’t contain the actual values.

SmartClient Version: v13.1p_2025-12-05/AllModules Development Only (built 2025-12-05)

Hi, I’ve just realized there’s a regression related to the test case from the first post - the modified #upload sample:

isc.DynamicForm.create({
    autoDraw: false,
    ID: "uploadForm", width: 300,
    dataSource: mediaLibrary,
    fields: [
        { name: "title", required: true },
        { name: "image", type: "imageFile", multiple:false, hint: "Maximum file size is 5 MiB" },
        { title: "Save", type: "button",
            click: function () {
                this.form.saveData("if(dsResponse.status>=0) uploadForm.editNewRecord()");
            }
        }
    ]
});

isc.DynamicForm.create({
    autoDraw: false,
    ID: "viewForm",
    dataSource: mediaLibrary,
    width: "100%",
    fields: [
        { name: "title", title: "Title", type: "text", width: "*" },
        { name: "image", title: "image", editorType: "ViewFileItem", showFileInline:false, canEdit:false,
            startRow: false, endRow: false
        }
    ]
});

isc.ListGrid.create({
    autoDraw: false,
    ID: "mediaListGrid",
    width: "100%",
    height: 224,
    autoFetchData: true,
    recordClick:"viewForm.editRecord(record)",
    dataSource: mediaLibrary
});

isc.VLayout.create({
    autoDraw: false,
    ID:"mainLayout",
    width:500,
    height:250,
    members:[viewForm, mediaListGrid]
});

isc.HStack.create({
    width:"100%",
    membersMargin: 10,
    members:[uploadForm, mainLayout]
});

With both showFileInline set to either true or false, and using either type=“binary” or type=“imageFile” for the image field, after uploading an image, when I click on the corresponding record in the grid, nothing is displayed in the image formItem (viewForm). I don’t see the image when showFileInline is true, nor the view/download icons when it’s false.

We’ll check on the regression. Regarding it being called multiple times, it looks like your sample doesn’t have autoDraw set up to avoid redraws, so that’s expected (and is warned about in the SmartClient log).

Thanks for the quick reply.
I’m not sure I fully understand the suggestion regarding autoDraw, and I’m not seeing any WARN messages related to it.
Moreover, I’m observing the same behaviour in my application, where I’m already using isc.setAutoDraw(false).

https://smartclient.com/smartclient-latest/isomorphic/system/reference/?id=attr..Canvas.autoDraw

If you run your code from #7, where you reported seeing duplicate formatValue calls, in an environment where autoDraw is not defaulted to false, you will see each component draw, then get reparented, then draw in its new parent. This can cause a lot of extra draws. These are all logged in the SmartClient Developer Console.

It’s not clear in which environment you’re seeing a lot of duplicate calls. It’s 100% expected in the above circumstance. If you have another situation in which you’re seeing it, you might use getStackTrace() to take a look at how it’s happening, so you can see whether it’s internal SmartClient processing vs your code doing something multiple times.

Ok, I can investigate what’s happening in my application - where autoDraw is already defaulted to false - to see whether there’s something else triggering the duplicate calls.

But regarding the behaviour in the Showcase: wouldn’t adding isc.setAutoDraw(false) as the first line of the sample be enough to avoid those extra draws, or is there something else that needs to be done in that environment?

The Showcase is special in a number of ways.. autoDraw:true issues are specially prevented.

But you haven’t explained in what environment you see duplicate calls. A standalone file (not the Showcase) would be the definitive way to check. And, that code in a standalone file (where autoDraw:true is the default!) would predictably produce duplicate formatValue calls, for the reasons we explained above.

I see the duplicate calls in the showcase.

Yes, again, the Showcase is special, so:

So, testing in a standalone file, you would need to correct the autoDraw issue - be sure to check the Developer Console!

Hi, I’m still not sure what exactly I should be looking for in the developer console, anyway I’ve set the log categories “draws”, “redraws” and “redrawTrace” to debug level, and then I tried this test case:

isc.DynamicForm.create({
    ID: "testForm",
    dataSource: "JAS_ANAG_GIOCATORI_ALTRE_SQ",
    height: "100%",
    width: "100%", 
    items: [
        {
            name: "FOTO",
            showFileInline: false,
            editorType: "ViewFileItem",
            displayItemProperties: {
                formatValue: function (value, record, form, item) {
                    isc.logEcho(this.getStackTrace(), "formatValue")
                    return "foo";
                }
            },
            canEdit: false
        }
    ]
}).show()

I run it in my application, where isc.setAutoDraw(false) is set before creating any SmartClient widgets. The FOTO field is of type imageFile.

This is what I see in the Developer Console, along with 5 calls to formatValue:

I’m not sure whether this output is actually useful, or how I should proceed from here to understand what is causing these repeated calls. Do you have any suggestions on what I should focus on next?

This output is extremely useful - there’s a reason we work so hard on diagnostics! Although note you can get full stack traces in Chrome, instead of traces that have to end on the first recursion.

Even with that browser limitation, these logs show that the form is being redrawn multiple times, and that’s why your formatter is being called repeatedly.

At least some of the redraws are due to a reflow, that is, something was not given a size in advance that was big enough, so it overflowed, and then other widgets had to change size in response. This is very common, and while inefficient, not especially worth chasing unless there’s a human-noticeable delay.