Jump to content
grantful

get idDrink out of database , based on what is clicked in listbox

Recommended Posts

I am trying to show only the records based on the item i click in a listbox.

on the onclick item i have

procedure TForm2.ListBox1ItemClick(const Sender: TCustomListBox;
const Item: TListBoxItem);
var
  drinkid: Integer;
begin

  FDQuery1.SQL.Clear;
  FDQuery1.SQL.Text := ('select idDrink from drinks where idDrink = :idDrink ');
  drinkid := FDQuery1.FieldByName('idDrink').AsInteger := listbox1.ItemIndex;
  showmessage(intToStr(drinkid));
  FDQuery1.Open;
  TabControl1.ActiveTab := TabItem8;
end;

so if i make this query in the fdQuery1 sql and exacute it all looks good.

listboxItemClick.thumb.png.a1e89c8fd1dcd1c4ce2792af9c6294ee.png

 

here is the drinklist listbox

 

dirnklistIdDrink.thumb.png.c7ecb1a2ba7a3ee4b65914549263e39a.png

 

 

I need to replace the From drinks where idDrink = 12910 with the record that is clicked on in the listbox. 

The detail on the right is the idDrink for each record.

 

 

I am not sure i am going about this the right way.

 

Thanks for any help with the correct code to get this to work.

 

 

Share this post


Link to post

You're going down a very bad road. ItemIndex has no meaningful value. 
I don't know TCustomListBox at all. I assume it has Items, which is a child of TString.
It does the following:
Name: string;
ID: T.. - some class from TObject into which you can put an integer.
Items.AddObject(Name, ID);
You use T..(ID) as the parameter for Query;
Details are in the tutorial.

Share this post


Link to post
8 minutes ago, Stano said:

You're going down a very bad road. ItemIndex has no meaningful value. 
I don't know TCustomListBox at all. I assume it has Items, which is a child of TString.
It does the following:
Name: string;
ID: T.. - some class from TObject into which you can put an integer.
Items.AddObject(Name, ID);
You use T..(ID) as the parameter for Query;
Details are in the tutorial.

do you have a link to a tutorial ? I need to figure this out

Share this post


Link to post

i am trying with a listview but now luck.

procedure TForm2.ListView2ItemClick(const Sender: TObject;
const AItem: TListViewItem);
begin
  FDQuery1.Active := True;
  while not FDQuery1.Eof do
  begin
    fdquery1.SQL.Clear;
    FDQuery1.SQL.Text :=
      ('Select strDrink,idDrink From drinks Where strDrinks = :idDrink');
    if ListView2.ItemIndex >= 0 then
    begin
      FDQuery1.ParamByName('idDrink').asinteger := (listview2.Items.Item[listview2.ItemIndex].detail);
      FDQuery1.Open;
      FDQuery1.Next;
    end;
    TabControl1.ActiveTab := TabItem8;
  end;
end;

i get an error at detail

[dcc64 Error] uMain.pas(470): E2003 Undeclared identifier: 'detail'

Edited by grantful

Share this post


Link to post

Help

You got it all on...
First just a basic fix
Give here an example of how you fill listview2.Items. We can't move without it
Kindly name all your components in a meaningful way!!!

procedure TForm2.ListView2ItemClick(const Sender: TObject; const AItem: TListViewItem);
begin
  //// It has nothing to do here!!!
  /// It's supposed to be where you create FDQuery1
  /// A separate function. For all Query
  FDQuery1.SQL.Text :=
    ('Select strDrink,idDrink From drinks Where strDrinks = :idDrink');
  /// Something like that
  FDQuery1.ParamByName('IDDRINK').AsInteger := TMyObject(listview2.Items.Objects[listview2.ItemIndex]).Value;

  try
    FDQuery1.Open

    while not FDQuery1.Eof do
    begin
      ///  Tu niečo urobíš
      FDQuery1.Next;
    end;

    TabControl1.ActiveTab := TabItem8;
  finally
    FDQuery1.Close;
  end;
end;

 

Share this post


Link to post

While it works, storing and using data in the UI is never a good idea. If one day you want to change the ListBox to something else you’ll have to rewrite the whole logic.

 

I’d suggest parsing (deserializing) the JSON into your custom class, filling the ListBox and extracting the ID from there when needed.

Share this post


Link to post
18 hours ago, Serge_G said:

First question : Is this supposed to be a FMX or a VCL program ?

If FMX you can write this app with "no code" (except itemclick to change from list to view and reverse)  using Livebindings

Here a french tuturial I wrote (2018)

@Serge_G

Very informative tutorial. I learned alot from it.

 

I have a question about binding multiple fields to the same memo.

multifieldsInMemo2.thumb.png.1f7bf94d773dbb2ed8b4ba2073791ea0.png

I need to bind all of the  stringrediants1,2,3 ect to the same memo.

Do you have any more tutorials that might help with this or is there a way to do it you have not made a tutorial ??

Thanks for the help i really appreciate it.

Share this post


Link to post

Hi,

First, all my tutorials are Here

 

For your need, you can use CustomFormat property of the link (should something like %s+' '+dataset.stringrediants1.value+....) 

I never test newline constant in an expression 🙄 something I should test soon 😄 I'm curious.

but I suggest you to treat the problem at the datasource and concatenate the fields in your query (advantage 1 - readonly field, advantage 2 - speed)

Share this post


Link to post

I have never used LiveBindings. Nor will I do so. The main reason is that I have no control over it. It's also not very clear.

Share this post


Link to post
1 minute ago, Stano said:

The main reason is that I have no control over it. It's also not very clear.

Well, you can write all LiveBindings at runtime also 😉. I agree Visual LiveBindings is not a perfect tool 😲

Share this post


Link to post

DBGrid notes. 
When I started, I had it on the form for 3 days. Never more.
I recommend VirtualStringTree (VST) instead. It works perfectly and you can do everything you can think of there. Because of it I created:
A class for VST. This one takes care of the VST data for me. I have two duties. Create the SQL and handle the VST events
Custom (DB)Navigator. So I'm relieved of bulk re-writing code.

Share this post


Link to post

Hum, now I am looking the table structure IMHO the database structure is not a valid one.

I think about a : Beverage table, Ingredient table, and Composition table instead of the "monolithic" table you seem to use (according livebinding screenshot

Edited by Serge_G

Share this post


Link to post
2 hours ago, Serge_G said:

Hi,

First, all my tutorials are Here

 

For your need, you can use CustomFormat property of the link (should something like %s+' '+dataset.stringrediants1.value+....) 

I never test newline constant in an expression 🙄 something I should test soon 😄 I'm curious.

but I suggest you to treat the problem at the datasource and concatenate the fields in your query (advantage 1 - readonly field, advantage 2 - speed)

Thanks for all your help and your tutorails.

I was trying to use the query for the listview.

 

FDQuery1.ParamByName('idDrink').asinteger := (listview2.Items.Item[listview2.ItemIndex].detail);

this is where i was trying to fix the problem.

Im sure some years back i did something like this and this line worked

FDQuery1.ParamByName('idDrink').asinteger := (listview2.Items.Item[listview2.ItemIndex].detail);

but now i am getting problems with this error   

[dcc64 Error] uMain.pas(627): E2003 Undeclared identifier: 'detail'

 

I am looking into useing the live bindings  https://docwiki.embarcadero.com/RADStudio/Sydney/en/Using_Custom_Format_and_Parse_Expressions_in_LiveBindings#Binding_Expressions

 

I would like to figure out this problem with my code.

 

Thanks for any help and any help with the query code.

Edited by grantful

Share this post


Link to post
57 minutes ago, grantful said:

Im sure some years back i did something like this and this line worked

That could never work. You're remembering wrong. One more time:
 

TMyObject(listview2.Items.Objects[listview2.ItemIndex]).Value;

 

Share this post


Link to post
13 hours ago, Stano said:

That could never work. You're remembering wrong. One more time:
 


TMyObject(listview2.Items.Objects[listview2.ItemIndex]).Value;

 

@Stano

Thanks for your patience.

 

I have not worked with objects before.

 

I took your advice and renamed some things.

 

type
  TMyObject = class(TObject);

procedure TForm2.lvDrinksListviewItemClick(const Sender: TObject;
const AItem: TListViewItem);

var
  idDrink: TMyObject;
begin
  idDrink := TMyObject.Create;

  /// / It has nothing to do here!!!
  /// It's supposed to be where you create FDQuery1
  /// A separate function. For all Query
  FDQuery1.SQL.Text :=
    ('Select strDrink,idDrink From drinks Where strDrinks = :idDrink');
  /// Something like that
  FDQuery1.ParamByName('IDDRINK').AsInteger :=
    idDrink(lvDrinksListview.Items.Objects[lvDrinksListview.ItemIndex]).Value;

  try
    FDQuery1.Open

    while not FDQuery1.Eof do
    begin
      /// Tu niečo urobíš
      FDQuery1.Next;
    end;

    TabControl1.ActiveTab := TabItem8;
  finally
    FDQuery1.Close;
  end;

[dcc64 Error] uMain.pas(517): E2003 Undeclared identifier: 'Objects'

[dcc64 Error] uMain.pas(517): E2003 Undeclared identifier: 'Value'

 

I am using Delphi 11 community edition. 

 

This is and FMX multi device program.

 

Can you perhaps tell me what i am doing wrong ?

 

Thanks again for all the help.

Share this post


Link to post

For me, you complicate your life :classic_wink:

21 hours ago, grantful said:

I was trying to use the query for the listview.

If you use livebindings and synchronize your datasource to the listview you don't have to add a query.

23 hours ago, Serge_G said:

I never test newline constant in an expression 🙄 something I should test soon 😄 I'm curious.

I made some tests. Not so evident, I think the best way is to create a new method for livebindings (I explore this in this tutorial).

For now, I just use a database (Firebird one) trick to get linebreak value and use CustomFormat:=%s+dataset.BR.text+dataset.stringrediants1.value+dataset.BR.text+dataset.stringrediants2.value+ ...

 

Can you attach your database and I will write a quick program as demo ?  

 

Attached a quick sample
image.thumb.png.833a55d6bfae659f902af3659dc42d10.png

image.thumb.png.cd8cf15ee452cfd35f535fd65ddaaef3.png

 

Ok, I don't create UI to add some coktails, just respond to first question
"show only the records based on the item i click in a listbox." (listview) 

Cocktails.zip

Edited by Serge_G
Demo added

Share this post


Link to post
4 hours ago, Serge_G said:

For me, you complicate your life :classic_wink:

If you use livebindings and synchronize your datasource to the listview you don't have to add a query.

I made some tests. Not so evident, I think the best way is to create a new method for livebindings (I explore this in this tutorial).

For now, I just use a database (Firebird one) trick to get linebreak value and use CustomFormat:=%s+dataset.BR.text+dataset.stringrediants1.value+dataset.BR.text+dataset.stringrediants2.value+ ...

 

Can you attach your database and I will write a quick program as demo ?  

 

Attached a quick sample
image.thumb.png.833a55d6bfae659f902af3659dc42d10.png

image.thumb.png.cd8cf15ee452cfd35f535fd65ddaaef3.png

 

Ok, I don't create UI to add some coktails, just respond to first question
"show only the records based on the item i click in a listbox." (listview) 

Cocktails.zip

 

Thanks so much I will look at this and the tutorial.

I had made it this far.

var
  DrinkID: Integer;
begin


  FDQuery1.SQL.Text := ('Select * From drinks Where idDrink = :_idDrink');

  // showMessage (intToStr(fdquery1.FieldByName('idDrink').AsInteger));
  FDQuery1.ParamByName('_idDrink').AsString :=
    (TListViewItem(lvDrinksListview.Items.Item
    [lvDrinksListview.ItemIndex]).Text);
  //
  // strToInt(TListViewItem(lvDrinksListview.Items.Item[lvDrinksListview.ItemIndex]).Text) ;
     FDQuery1.Open;
    momoDrinkIngrediants.Lines.Add(FDQuery1.FieldByName('strIngredient1')
    .AsString);
  momoDrinkIngrediants.Lines.Add(FDQuery1.FieldByName('strIngredient2')
    .AsString);





  FDQuery1.Next;

  TabControl1.ActiveTab := tiDrinksIngreediantsAndDirections;

  FDQuery1.Close;
end;

// ShowMessage(TListViewItem(lvDrinksListview.Items.Item[lvDrinksListview.ItemIndex]).Text);
// ShowMessage(TListViewItem(lvDrinksListview.Items.Item[lvDrinksListview.ItemIndex]).Detail);

 

Share this post


Link to post

I've written once before that everything associated w/in DB should be capitalized.  And name of component!!! * is only used in special cases. You always have to enumerate the required fields.

FQryDrink.SQL.Text := 'SELECT * FROM DRINKS WHERE IDDRINK = :IDDRINK';


Why are you mixing Integer and string types?  ItemIndex is not what you need.

FDQuery1.ParamByName('IDDRINK').AsInteger := (TListViewItem(lvDrinksListview.Items.Item[lvDrinksListview.ItemIndex]).Text);

  I have never worked TListView in my life. So I looked at the TListItem properties

image.thumb.png.3ac228aaca70739833c849c4513b65b8.png

It doesn't seem to me that it's something thrown in for you. It's too complicated. I assume you only need to display simple texes.
Then I see two components suitable for you:
ComboBox - only one item is visible
VirtualStringTree (my favorite) - if you want to see all items
Decide and let me know. Because your style will get us nowhere!!!

Edited by Stano

Share this post


Link to post

I went through the discussion again. I don't understand what you actually want to do. The description of the task is incomprehensible to me. Is it supposed to be a Master-Detail relationship?
Are you working with one table or two? Can you put a snapshot of the form in question here? I'm sure that would help a lot.
Why do you want to go into live bindings? Why do you need this?

Share this post


Link to post

Thanks for your help Stano

 

it is  1 table(drinks)

 

there are fields

stringrediants1

stringrediants2

stringrediants3. Etc

 

So when I click on the listview item I need to get the. Field. ‘IdDrink’ from the table and load up all the 

stringrediants1,stringrediants2,stringrediants3 etc. from the same table into a

Listview or listbox,or memo

Thanks for your patience and help

Share this post


Link to post

Hm, does that mean IDDRINK is repeated in the table?

What are you going to do with that list? Its purpose.

No translator will translate the field name, the rediant part :classic_smile:

Out of curiosity: which DB is it?

Edited by Stano

Share this post


Link to post

It is a SQLite database

 

Example

Table (Drinks)

 

Fields

idDrink,strDirections,stringrediants1,stringrediants2,stringrediants3,stringrediants4,etc


so when I click on any record in the listview I need to use the idDrink (integer) and display all the fields

 

idDrink field is int

strdrink is string

stringrediants1,stringrediants2,stringrediants3 is string


so the strDirections will go into a memo

the stringrediants3,2,3 etc will go in a memo

 

 

 

Edited by grantful
A

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×