Here is the listGrid component. https://smartclient.com/smartclient/showcase/?id=fetchOperationFS
It has no examples with images, at least I did not find.
So when you scroll the grid, it fetches from server that part of items, as I understand bit wider than visible area.
But problem is - sometimes images do not load when scroling:
As you can see on the right column (Options) - there should be 3 images in every row. Sometimes they load later. Sometimes they do not load unless you do something, like checking network tab in chrome dev tools, clicking on other images. Also after you scroll up and down, it probably redraws and those images load.
How can this be?
There is such method which draws those images:
private _createListGridRecordComponent(record, colNum: number) {
let result: isc.ICanvas | null = null
switch (this.listGrid.getFieldName(colNum)) {
case "#state":
if(record["#invoiceIsValid"]) {
result =
<HLayout height={25} width={25} membersMargin={2}>
<Img width={25} src={component.icons.small.correct}/>
</HLayout>
} else {
result =
<HLayout height={25} width={25} membersMargin={2}>
<Img width={25} src={component.icons.small.warning}/>
</HLayout>
}
break
case "#options":
result =
<HLayout height={25} width={25} membersMargin={2}>
<Img width={25} src={component.icons.small.preview}
click={() => this._events.onPreviewClicked.fire(record)}/>
<Img width={25} src={component.icons.small.send_mail}
click={() => this._events.onSendEmailClicked.fire(record)}/>
<Img width={25} src={component.icons.small.generate_xml}
click={() => this._events.onGenerateXmlClicked.fire(record)}/>
</HLayout>
break
default:
// do nothing
}
return result
}
You can see '#options' case.
I have tried to 'cache' this code
const icons =
<HLayout height={25} width={25} membersMargin={2}>
<Img width={25} src={component.icons.small.preview}
/>
<Img width={25} src={component.icons.small.send_mail}
/>
<Img width={25} src={component.icons.small.generate_xml}
/>
</HLayout>
by assigning it to variable and then pass icons to _createListGridRecordComponent and assigne icons to result variable.
but then it did not render images at all. Of course if I cache this way, I would need a solution with click events, because every row needs different record object. But first I would need to somehow make always render images.
Update
Noticed one intereting detail:
Here is the details page when we click on eye icon:
So invoice number ends with 10022.
But eye icon which I clicked to open this details page is in row other than invoice ending 10022. The invoice ending 10022 is the last row in this case, which does not have eye icon.
So it means the icons are in wrong rows.
List grid is created this way:
{this.listGrid =
<ListGrid dataSource={InvoiceDataSource.sc()}
useAllDataSourceFields={false}
selectionAppearance="checkbox"
rowDoubleClick={(record: InvoiceDataSource.Record) => {
const refresh = (r: InvoiceDataSource.Record|null) => {
if (!r) return
const rowNum = this.listGrid.getRecordIndex(r)
if (rowNum !== -1) this.listGrid.refreshRow(rowNum)
};
const lastRecord = this._activeRecord
this._activeRecord = record
refresh(lastRecord)
this._events.onPreviewClicked.fire(record)
refresh(this._activeRecord)
}}
showRecordComponents
showRecordComponentsByCell
createRecordComponent={(record, colNum) => this._createListGridRecordComponent(
record,
colNum,
preview,
sendMail,
xml
)}
mixin={mixin.client_management.AirportMixin()}
hilites={[
{
cssText: "background: #E53935;"
}
]}
getCellCSSText={(record: InvoiceDataSource.Record) => {
if (this._activeRecord && record.id === this._activeRecord.id) {
return "background: #F5F7F7;"
}
return ""
}}
>
<ListGridField name={"#state"}
title={translation.title.state}
/>
<ListGridField name={"#invoiceNo"}/>
<ListGridField name={"client"}/>
<ListGridField name={"name"}/>
<ListGridField name={"invoiceType"}/>
<ListGridField name={"validFrom"}/>
<ListGridField name={"validTo"}/>
<ListGridField name={"scheduledForSending"}/>
<ListGridField name={"mustBePaid"}/>
<ListGridField name={"status"}/>
<ListGridField name={"notified"}/>
<ListGridField name={"lastUpdatedTime"}/>
<ListGridField name={"insertedTime"}/>
<ListGridField name={"#options"}
title={translation.title.options}
canFilter={false}
canSort={false}
/>
</ListGrid>
}
And little bit update function of icons creaion, tried using svg, save them into variable and pass them to function which generates icons, but looks like not image problem at all but position problem.
private _createListGridRecordComponent(record, colNum: number, preview: string, sendMail: string, xml: string) {
let result: isc.ICanvas | null = null
switch (this.listGrid.getFieldName(colNum)) {
case "#state":
if(record["#invoiceIsValid"]) {
result =
<HLayout height={25} width={25} membersMargin={2}>
<Img width={25} src={component.icons.small.correct}/>
</HLayout>
} else {
result =
<HLayout height={25} width={25} membersMargin={2}>
<Img width={25} src={component.icons.small.warning}/>
</HLayout>
}
break
case "#options":
result =
<HLayout height={25} width={25} membersMargin={2}>
{/*<Img width={25} src={component.icons.small.preview}*/}
{/* click={() => this._events.onPreviewClicked.fire(record)}/>*/}
{/*<Img width={25} src={svg}*/}
{/* click={() => this._events.onPreviewClicked.fire(record)}/>*/}
<HTMLFlow width={25} contents={ preview } click={() => this._events.onPreviewClicked.fire(record)} />
{/*<HTMLFlow contents={ preview } click={() => this._events.onPreviewClicked.fire(record)} />*/}
{/*<HTMLFlow contents={ preview } click={() => this._events.onPreviewClicked.fire(record)} />*/}
<HTMLFlow width={25} contents={ sendMail } click={() => this._events.onSendEmailClicked.fire(record)} />
{/*<HTMLFlow contents={ xml } click={() => this._events.onGenerateXmlClicked.fire(record)} />*/}
{/*<Img width={25} src={component.icons.small.send_mail}*/}
{/* click={() => this._events.onSendEmailClicked.fire(record)}/>*/}
{/*<Img width={25} src={component.icons.small.generate_xml}*/}
{/* click={() => this._events.onGenerateXmlClicked.fire(record)}/>*/}
</HLayout>
break
default:
// do nothing
}
So how can there be wrong position of icons?