TFDTable/TFDQuery on blob null - provide alternative image - delphi

Is there a way to configure my TFDTable/TFDQuery such that whenever BLOB in a table record is Null,
i have a chance to provide another Blob/photo.
I looked through TField events for blob, but there seems to be no suitable event.
Setup: Delphi 10.4, MySQL, using FMX framework

Add a CalcField or InternalCalcField to your dataset and in the OnCalcFields() handler check if the blob field is empty. In that case, fill with your 'alternative' data.
Then in the rest of your application refer to the InternalCalcField field instead of the original one.
You do not specify where that data should come from, so you'll have to figure that out yourself.

Related

TDateEdit cannot LiveBinding with a datasource bidirection

This is a simple question.
Start a multidevice App, place a TDateEdit and DBTable with a field containing TdateTime data. Then use LiveBinding designer link the data source field to TDateEdit.DateTime property. However, this link is unidirectional , The control DateEdit can accept the data from the Datasource, but cannot update the changes to the datasource. How to change the link to bidreiction???
There may be some things that are not clearly understood.
Normally a LiveBindings link will be bidirectional - so if you setup two TDateEdits and bind them together changing one should change the other, irrespective of which one you change.
It seems that what you are hoping is that changing the TField will update the data in the database table.
That's not typically how the Data Access components in Delphi work.
The TField is part of a TDataSet. The TDataSet has a Post method to write changes to the underlying data store, if that's supported.
The Data Access components are extremely powerrful and can cope with lots of different scenarios, and allow you to extended capabilities throguh exposed events as well as subclassing the components.
If you want to update your underlying data store you need to have a writeable TDataSet and you need to call Post on it to write.
I suggest you start off with some of the videos in Enbarcadero's YouTube channel about how to use the data acecss components. It's not difficult to do but beyond the scope of an answer here.
If you use the LiveBindings Wizard to hook the DateEdit with a field, it will hook it up bi-diretionally to a "virtual" SelectedDateTime property of the DateEdit. That property doesn't really exist in the TDateEdit but is used by the LiveBindings to map the separate Date and Time properties of the DateEdit.

How to adding new section in INI file using TJvAppIniFileStorage

I have a database application project written in Delphi XE and connected to MySQL Database using dbExpress. I use JVCL grid Components to show the records from the Dataset. It will be more efficiently if I can use another JVCL Components to do the FormStorage.
I've been suggested to use TJvFormStorage and TJvAppIniFileStorage for form storage. I have many forms on this project so I need to adding new section in my INI file to store the form size values but I don't know how to do that using TJvAppIniFileStorage.
The TJvAppIniFileStorage is just providing the DefaultSection() method which means it's just can modify and write into one section only which declared as the default.
Anyone can describe to me how to adding new section using the JVCL's TJvAppIniFileStorage?
Thanks in advance.
Is the TJvFormStorage instance the one that determines in which path of the abstract storage to put the data about this form, with the value of the AppStoragePath property.
You can use the special value '%FORM_NAME%' to determine that path automatically at run-time. The '%FORM_NAME%' is changed for the real .Name property of the form where the component is located, or if it is a frame, a dot list of the frame chain up to the form containing it. That way you can have different instances of the same class saving the info to different paths.
When you're using a TJvAppIniFileStorage instance as the data storage backed to save the form data to a INI file, that path is equivalent to the INI section where the information is stored.
In other words, if you want to store the info of your form in a section called 'MyForm', set that value to the AppStoragePath property of the TjvFormStorage instance in that form.
Use the Source, Luke! ;)
My guess is: It uses Parent.Name or Parent.ClassName to store parameters.
Another point: take in mind several monitors on user's computer. Almost no app takes in mind this case.

SmartGWT LiveGrid unable to apply style to grid records programmatically

I am using SmartGWT 2.5, specifically a ListGrid backed by a RESTDataSource.
The Server integration is achieved by way of a servlet, and I only need to implement fetchData(). The data is a List<Map<String, Object>> populated on the server side, converted into JSON and sent in the DSResponse. The Live grid backed by the datasource triggers a server fetch programmatically by way of grid.fetchData().
Requirement:
I wish to set a record base style (or custom style) based on the value of one of the record's attributes, which I send over from the server.
In order to do this, I have tried a DataArrivedHandler, where I iterate over the available rows, get the ListGridRecord from the grid using the row number, and use gridRecord.set_baseStyle(String stylename) or gridRecord.setCustomStyle(String stylename) to try and apply a greyed out css for that record. After this, I call grid.markForRedraw(), however to no effect. The CSS does not get applied.
I must mention that I have used the same css to grey out rows on a normal listGrid (no dataSource) very successfully.
Questions:
Is my strategy the right one?
Is there an alternative method to apply a style to a record based on an attribute value.
Your strategy is correct and I have successfully achieved your required functionality in code of mine. Make sure you are correctly getting the record and that the test attribute is present in it. I suggest a JSON.encode(record.getJsObj()) to see what your record actually is filled with. No need for markForRedraw() explicit call, as after the DataArrivedEvent has fired the ListGrid will redraw its view. Post a small code snippet if you need more help. Also as suggested from the comment from Alain, highlights might be another good option to look at.

How to retrieve information from a field that has the property Required set as false?

I have the following DBX structure in my software:
TSQLDataSet -> TDataSetProvider -> TClientDataSet
One of the fields from my TClientDataSet has the property Required set to false, because this field auto increments based on triggers and generators on the database (Firebird).
However, after configuring both TSQLDataSet and TClientDataSet with this field not being required, I'm getting really weird results when I try to read this field from my TClientDataSet. I suspect that I might need to do something extra to force my TClientDataSet to acquire the value of this field in this condition.
What am I missing here?
Thanks in advance.
EDIT
The help file for the Required property says something about this, but I couldn't quite understand what it want me to do.
Description
Specifies whether a nonblank value for a field is
required.
Use Required to find out if a field requires a value or if the field
can be blank.
If a field is created with the Fields editor, this property is set
based on the underlying table. Applications that set Required to true
for fields that must have values (for example, a password or part
number), but for which the underlying table does not require the
field, must write an OnValidate event handler to enforce the property.
When the Required property reflects a property of the underlying
database table, trying to post apply a null value causes an exception
to be raised. Applications that set the Required property to true when
the underlying table does not require the field, should raise an
EDatabaseError exception on null values in the OnValidate event
handler in order to achieve the same result.
EDIT 2
Forgot to mention: between the TDataSetProvider and the TClientDataSet, there is a DataSnap layer (the TClientDataSet connection is made with a DataSnap driver).
EDIT 3
I created a small test case with this DataSnap setup and it worked perfectly. The project is legacy, messy and I guess that either I have an obscure option configured somewhere that is biting me or I have stumbled in a DataSnap bug.
Haole, have you tried TClientDataset.RefreshRecord after inserting? Or even TClientDataset.Refresh?
Having generators, you can even get the generator in advance (before calling ApplyUpdates) in a query like select gen_id(generator,1) from RDB$Database (it's from memory, don't have Firebird here to test) and fill the PK field in advance.
EDIT: seems this is a heisenbug. I would try to remove the components and reconfigure them again from scratch (which means: after you remove, save and close Delphi).
Or even better, create an empty project with just that needed query configuration and try to view that data in a TDBGrid. If this problem still happens, maybe your FB installation have some component corrupted (or even Delphi installation)
Seems that the problem was an outdated field being read as an INTEGER and it was a SMALLINT in the database.
This problem was hard to debug and this question was misleading. Thanks for everyone that helped me debug this.

Adding a field to a cloned TClientDataset in DELPHI

Hi I have a master and cloned TClientData set
CdsCloned.CloneCursor(CdsMaster,true);
CdsMaster has two Fields 'SessionId' and ’UserID'
CdsCloned will have the same Fields
QUESTION: is it possible to add an extra field to CdsCloned without changing the CdsMaster ?
There are really two questions here: Can I add an extra TField, and can I add an extra data field.
When you clone a client dataset cursor, you end up with two TDataSet instances, each with their own collection of TFields, which share a single data store. You can certainly add additional TFields for things like calculated fields to one or the other without affecting the clone. There is no problem with doing this.
But remember, the original dataset and its clone share a single data store. You cannot change that data store without affecting the other dataset. If you add a new field to the data store, then that new data will be present in the store referenced by the original dataset, whether or not you have created any TField objects to read/write it. If this is starting to sound like a bad idea, well, that's what I'm thinking, too.
Finally, if you want the original dataset and its "clone" to have different data stores, then you can assign the Data property instead of using CloneCursor. When you do this, the data from the original is copied into the data store for the "clone", but the original and "clone" no longer share a single data store.

Resources