Relational Data Grid

Login or register to post comments
68 replies [Last post]
Offline
Joined: 04/09/2009

Hi all,

I want to create a CRUD application with multiple columns (at least 3) as buttons. These buttons should open (in modal or modeless dialog box) the respective table entries again in CRUD with hidden FK that point to the keys in the first table. So anything added/edited or deleted will be appended with the keys of the primary table row (through which the table got opened) to complete the DB query.

What will be the best way to go with? MetaDataGrids looks good but not sure how time consuming will be to add CRUD to it. How about dashboard? Can I add a column of buttons to them and then assign it to open another table in CRUD as a dialog box?

Please suggest which one will be fast.

Thanks a ton for wonderful applciation!!!

Offline
Joined: 04/09/2009

Has anybody done something like this? I am trying to do this in Qpanel. I can add more columns carrying button. Those can be used to open another Qpanel page. But don't know how would I pass the data to the next Qpanel. I want to restrict the entries to this Qpanel say if I have 2 tables.

Table1: PK, Col1, Col2
Table2: PK1, PK2, PK3, Col1, Col2

And say Table1.PK is a FK for Table2.PK1.
Now on the second Qpanel I want to default the Table1.PK value for Table2.PK1 for creating any rows. Also on the list only the records that match Table1.PK should be displayed.

Please help.
Thanks

alex94040's picture
Offline
Joined: 11/06/2008

Take a look at the following two examples:

http://examples.qcu.be/examples/dynamic/inline_editing.php

http://examples.qcu.be/examples/datagrid/rowactions.php (note that this one will only work with the SVN build of QCubed, not the RC2 bits)

Offline
Joined: 04/09/2009

Alex,

Both the examples keep the page same. They just execute javascript to pop up about what you clicked. I want to open another link by press of button with setting some data. It can be a POST or GET request. And then once those FK's reach there, I want to restrict activity to only those keys.

Hope you got my point. How can I achieve a POST request through Qcubed?

Thanks.

alex94040's picture
Offline
Joined: 11/06/2008

Meetsang, you need to carefully look at inline editing example again, in particular its EditColumn_Render() method.

You will notice lines

$btnEdit->ActionParameter = $objPerson->Id;
$btnEdit->AddAction(new QClickEvent(), new QAjaxAction('btnEdit_Click'));

that say that when the user clicks on the Edit button, an Ajax action (HTTP POST) is performed; during the processing of that post, the function btnEdit_Click() is clicked.

You'll see that the way btnEdit_Click is defined:

protected function btnEdit_Click($strFormId, $strControlId, $strParameter)

- the THIRD argument, $strParameter, will be set to $objPerson->Id, as we specified earlier in the declaration of $btnEdit->ActionParameter. Later in that function definition, we could have done anything else we wanted - i.e. updated another datagrid with the list of projects that this person works on, etc.

Hope this helps.

Offline
Joined: 04/09/2009

Thanks Alex.

It helps to know that I can do it this way too.

But I was initially thinking to take the user to CRUD for my secondary table. As the user should be able to do anything on the 2nd table too. Hence I was thinking to POST to another .php file but restricting its CRUD functionality.

With the current procedure I think I can display the secondary table entries on the 2nd panel when the button is clicked. And also add a delete button with inline editing. But all this makes the single php file looks very complicated. What would you suggest to go with this approach or with my original idea?

Thank you!!

alex94040's picture
Offline
Joined: 11/06/2008

Depending on your application, it may turn out to be a little more user-friendly to show the list and the details on a single page. If that's the case, continue with the approach I suggested above.

You can split out the logic for the details QPanel into a separate file, if the single php file looks too complicated at a glance.

Offline
Joined: 04/09/2009

Hey Alex,

I decided to go with your approach. I modified the Panel generated files, in the dashboard folder for that. I have added one link on the "master" list table. When the button is clicked I pass the control to the "item" table. Here I am trying to modify the item list panel file to let me add,edit and delete the records. But I am stuck at the calling of the bind method as done in the inline editing code. I am getting following error in this case:
Fatal error: Call to undefined method Dashboard::dtgItem_Bind() in J:\xampp\htdocs\projectco\includes\qcodo\_core\qform\QFormBase.class.php on line 326

The call on the binder method is made by:
$this->dtgItem->SetDataBinder('dtgItem_Bind');

where datagrid is declared as:
$this->dtgItem = new QDataGrid($this); in __construct method of ItemListPanel.class.php.

I am not sure if I can combine the panels and inline editing code. Please help.

Thank you.

Offline
Joined: 04/09/2009

I think the call has to be made as:
$this->dtgItem->SetDataBinder('dtgItem_Bind', $this);

But now, I am unable to set the datasource for it. Here is the code in method dtgItem_Bind:

$objCoNRArray = $this->dtgItem->DataSource = Item::LoadAll(QQ::Clause(
$this->Item->OrderByClause,
$this->Item->LimitClause
));

Please help.

alex94040's picture
Offline
Joined: 11/06/2008

You're exactly right - using the second parameter in SetDataBinder is the way to do it.

I'm not sure what you mean by "unable to set the datasource for it." What is the error you're seeing?

I see that the QQuery you're using is not quite correct - you're missing QQ::All() before QQ::Clause().

Offline
Joined: 04/09/2009

Alex,

Thanks for quick reply.

I am having a lot of difficulty in understranding "QQ", "QQN" and QApplication and things like that. Are they php things? or Qcubed? Can you give a brief overview or any link to go understand them.

Also, currently I am looking to bring the data so I commented the QQ clauses hoping its just used to sort. And yeah, the code is working, its bringing me everything if I use LoadAll().

I would like to reduce the data selection as I just need the PK from the table. So I used Item::Load($intKey) and initially tried to set $intKey with a static value. But it doesn't return any records. I even checked the ItemGen.class.php data class, the Load function seems to return the Item object if I provide the Item Key. But its unable to get the data.

Thanks.

RKotenko's picture
Offline
Joined: 07/03/2008

Anything starting with Q is a QCubed function or class.

If your query is not showing up, you may want to use the profiler to view the SQL:

QApplication::$Database[1]->EnableProfiling();
QApplication::$Database[1]->OutputProfiling();

Put the first line at the top of the page and second at the bottom and then you can see query results.

Go to the examples link and look through Code Generator section. In the future, we hope to have a more linear tutorial on the various aspects of QQuery.

Offline
Joined: 07/10/2008

The error you are seeing is because you don't have a function to set the binder which you specified. You need to add:

public function dtgItem_Bind () {

$this->dtgItem->DataSource = Item::LoadAll();

}

To define columns for your datagrid, after $this->dtgItem = new QDataGrid($this); add

$this->dtgItem->AddColumn (new QDataGridColumn('Id', '<?= $_ITEM->id ?>'));

Hope that helps.

Offline
Joined: 04/09/2009

Basilieus,

I did as you said and it shows all the records. But now I want to restrict the records so instead of using LoadAll() I used Load() and passed the integer key to it statically to test if it works. But its not returning any records. As per RKotenko's comments I turned the profiling at global level. Where can I see the profiling results?

I must be doing something incorrectly, why would LoadAll work and not Load(PK). Its an integer with zero fill and 7 digits. Its value is 1050000. I tried various ways: passing it in quotes, without quotes [Load(1050000) and Load("1050000")], used a variable to hold the value both quotes and without quotes again.
$Item_PK = 1050000;
[Load($Item_PK)]
But I don't get either an error or a value in the grid in any of the cases.

Please help.

Thanks.

Offline
Joined: 07/10/2008

meetsang:

take a look at:

/data_classes/generated/ItemGen.class.php

This will show you all the functions available to you for you to use.

I would assume in your case its probably:

LoadById ($strId)

If you are trying to use an association table and find all the associated objects, you will find functions in that file (class) relating to that table, such as:

GetAllAssociatedItemWidgets ();

ps. i'm not sure thats the actual function you will have to look that up in the file above.

RKotenko's picture
Offline
Joined: 07/03/2008

If you have the profiling enabled, at the very bottom of the page, there should be a link to the queries performed for that page.

If you do not see that link, then the profiling is not enabled correctly.

Offline
Joined: 04/09/2009

Thank you for replies. I just wrote this code:

<?php
>$intTest = 1050000;
           
$Item = Item::Load($intTest);
       
QApplication::DisplayAlert($Item->Date); <
?>

And I am getting the pop up with the date. So I think the Load function is working for me but its not binding well with the grid.
Here is my code for binding it:

<?php
>$this->dtgItem->SetDataBinder('dtgItem_Bind', $this);<
?>

Note that if I replace Load() with LoadAll, it works and brings all the data. But the Load() is not populating the results.

Please help. Thanks.

Offline
Joined: 07/10/2008

meetsang:

goto pastebin and paste your panel for us.

Thanks

Offline
Joined: 04/09/2009

I am sorry I am not sure what is pastebin. Can you please provide the link?

Thanks

Offline
Joined: 07/10/2008

http://pastebin.com/

paste your Panel class in there and once you are done, post the link so we can help you.

bas

Offline
Joined: 04/09/2009

Here it is:

http://pastebin.com/m27a2dc47

I am trying to create the grid on a panel with restricted values from the db. It is called from another panel that is bearing a father-child relation to this panel. I have some more issues wrecking my brain. If you can help me resolve them too.

  1. Selective data not binding to datagrid. (You know @ it)
  2. I am unable to render the New button ($btnNew) for inserting the new row. The code for that is
    <?php
    $_CONTROL
    ->btnNew->Render();
    ?>
  3. Can you please help with a date and an upload field in datagrid. I want them nice and functional in edit and view mode. In edit mode user should be able to select date from Calendar like QCalendar and upload a single file for upload that will overwrite the previous file. In view mode the upload file should become a link. Can I achieve it?

Thanks.

Offline
Joined: 07/10/2008

$objCoNRArray should be named $objConR, because you are using QuerySingle not QueryArray.

And the function (Load) will return an object, not an array, so the array_push at the bottom will not work.

try and comment out:

if ($this->intEditCoNBRId == -1)
array_push($objCoNRArray, new CoNursingBoardRegistration());

And tell me what that does. Make sure to use $objCoNRArray = CoNursingBoardRegistration::Load($intTest); instead of the LoadAll();

bas

Offline
Joined: 04/09/2009

Hey Bas,

Thank you for all the help. The data I am seeking is based on multiple keys. My table is structured as:
ContractorID, RegNumber, Date and Registration. Where first 2 fields are keys.

I started writing my own data grabbing method and now I am able to get the restricted list. The Load function can't return a list. Now my question is will I be able to update the key parameter RegNumber if its changed? If its not possible please let me know.

Can you please help me with Upload and Date fields on the datagrid? They are really frying my brain.

Thank you.

Offline
Joined: 07/10/2008

meetsand:

The load method only loads 1 object.

If you want a list you can use QueryArray, or any of the Array functions provided through the generated classes.

I would suggest looking over the examples section here on the site (I'm sure you have), it will explain a lot more in detail.

bas

Offline
Joined: 04/09/2009

Bas,

I managed to bring up the list. Thanks for the help.

Now my question is can Qcodo manage change in one of the composite key value? My logic is to allow user to change one of the key parameter. Is it possible?

Thanks.

Offline
Joined: 07/10/2008

Yes it is, once you set a value for your new key (contractorid ??) all you have to do is $this->datagridname->Refresh(); And it will execute the bind method supplied.

Bas

Offline
Joined: 04/09/2009

Hey Bas,

I got it working. Thanks a lot. Now 3 more to go:

1. I am unable to get the Create New button. I have updated my code at http://pastebin.com/m13b13f6b. The code for rendering it on the panel is:

<?php
$_CONTROL
->btnNew->Render();
?>

I am not sure what the problem is with rendering it.

2. Date field in the datagrid. How to go about it. I have once used the QDateTimeTextBox with QCalendar but only on a normal form. Can I have that combination on a datagrid. If I use $this->dtDate->Text it gives me error. Please help.

3. Also, please help me with an upload field, I have a Blob field to upload.

Thanks.

Offline
Joined: 07/10/2008

try and set your variable btnNew to public.

Offline
Joined: 04/09/2009

Bas,

I have pasted the error after making it public here:

http://pastebin.com/d5cf738fe

I think you are correct it should be public. But still unresolved. Please check.

Thanks.

Offline
Joined: 07/10/2008

Change
$this->btnNew->AddAction(new QClickEvent(), new QAjaxAction($this, 'btnNew_Click'));

To:
$this->btnNew->AddAction(new QClickEvent(), new QAjaxControlAction($this, 'btnNew_Click'));

Offline
Joined: 04/09/2009

Thank you dude. I am so much thankful to you. I got it!!! You are the man.
Will put a code for that tomorrow. Going to sleep now. Hoping to have date and upload fields working soon too!!

Offline
Joined: 07/10/2008

Sleep is not an option.

Offline
Joined: 04/09/2009

Bas,

The New button does not refresh the panel. It just processes and stops. Putting $this->datagridname->Refresh(); gives an error. If you look into the inline editing example, there is a method Form_Prerender that refreshes the datagrid. I tried to use that one too, but its not called either. It must be named something else for a panel. How can I take control back to refresh the datagrid once the New button is clicked?

Thanks.

Offline
Joined: 07/10/2008

meetsand:

datagridname is the name of your datagrid, you obviously have to change it.

Offline
Joined: 04/09/2009

Ohh yeah, I changed it. By that I meant my datagrid only.

Offline
Joined: 07/10/2008

hehe, post your new qpanel now :)

Offline
Joined: 04/09/2009

The code is same. If I put the refresh on datagrid it gives me error, otherwise I don't get anything just the wait icon shows it moves.

Offline
Joined: 07/10/2008

I understand but I would like to see it again so i have a fresh reference, we did change a bit.

Offline
Joined: 04/09/2009

Bas, updated at http://pastebin.com/m121c57ab.

Thanks.

Offline
Joined: 04/09/2009

Hey Bas,

Anything? I am stuck and desperately need your reply. Please help.

Thanks.

Offline
Joined: 04/09/2009

QCubed gurus,

I am stuck here. I am trying to put an inline modification in the datagrid on a qpanel. I am not able to make the New button refresh the page to bring up a row to enter data. My code is at http://pastebin.com/m121c57ab. Obviously the panel is called from another one.

If possible, please help.

Thank you!!

Offline
Joined: 07/10/2008

In btnNew_Click uncomment:

$this->dtgCoNursingBoardRegistrations->Refresh();

Does that not work?

Offline
Joined: 04/09/2009

Unfortunately that doesn't...Here is the error:

http://pastebin.com/m28ffda2c

Offline
Joined: 07/10/2008

Awwwww its basically stating that you are trying to render a control twice. Which won't work.

Offline
Joined: 04/09/2009

Bas,

Ohh, there were two controls for that one. I have updated the error page with one row now. Still it doesn't show one more line to add it. Can you have a look?

I need to call it only once even if there are more records.

Thanks.

Offline
Joined: 07/10/2008

Well its giving you an error on control c86, which if you named your controls you would know which one it is. (There is another parameter you can pass into QControls which is the name field).

if you look at EditColumn_Render, and study this carefully it is checking to see if the Edit button is already on the form.

Now if you compare what this function is doing compared to your other _Render function for other columns, you should be able to fix it by checking to see if the control is already on the form.

Offline
Joined: 04/09/2009

Bas,

Thank you Bas. It seems to working for me.

One more thing, the date column when rendered as a QDateTimeTextBox, comes as empty since I couldn't set it. I know how to get it as string: $this->dtDate->DateTime->__toString() and I tried to set it through the same expression with the value in db object but it doesn't work. Please let me know how to set a QDateTimeTextBox through code.

My updated code is at http://pastebin.com/m4e9d6a4a.

Thanks a ton.

Offline
Joined: 04/09/2009

Could anybody help me set an object of type QDateTimeTextBox? I have the date coming from MySQL date column.

Thanks.
PS: For reference pls refer my previous post.

Offline
Joined: 07/10/2008

QDateTimeTextBox extends QTextBox:

$this->dtDate->Text = $objCoNBR->Date;

agsel's picture
Offline
Joined: 04/02/2008

Could you specify, around which line you have that problem? There are a lot of code.

Or what exactly are you trying to achieve?

To set value of textbox, you should use $txtSomeTextBox->Text = $dttSomeDateTime->__toString(); I haven't used QDateTimeTextBox myself. I usually add functionality, where I can set QDateTime object for given control and everything is done automatically. Have you tried something? What do you got so far?

Offline
Joined: 04/09/2009

Bas and Agsel,

If I use this: $this->dtDate->Text = $objCoNBR->Date;, it gives me an error.

The variable $objCoNBR->Date is coming out of database. You can refer to line 223 in code at http://pastebin.com/m4e9d6a4a. At next line I am even displaying the Date column thats working but not setting up the date to variable dtDate.

The dtDate is already attached to Qcalendar and the combination works perfectly to bring the date on it. But I am unable to set the initial date from the db.

Thanks.