Tutorial - Nested QDataGrid The How To?
Hi everyone, as my first contribution to the community of qcubed I will explain and demonstrate how to create a nested QDatagrid.
With a MAster QDatagrid and through a button, usually a '+'to prove they can expand, appear a Child QDataGrid with other content as you can see in the screen_1.jpg attach.
Some preconceptions to consider first are:
- Master QDataGrid should go on the FORM.
- Child must be in QPanel QDataGrid (I like it better to say that the style created as User Controls. NET)
- We must always know who are the children and parents the QDataGrids.
- HtmlEntities in QdataGrid always 'False'. I Expend two days looking for this error =P.
Let's start ...
First we need to create the Master QDataGrid...
<?php
// Load the QCubed Development Framework
require ('../../qcubed.inc.php');
// Load User Controls -> This is the First Child QDataGrid.
// It be explian later, at the moment the only you need to know is
// it was created like a .NET User Control and extends from a QPanel.
require (__APP_CONTROLS__ . '/records.summary.php');
class DomainList extends QForm {
// Datagrid List Control for Domains
protected $dtgDomains;
// This is for refresh the QDataGrid and make appear the childs
// Datagrid becaouse i use ajax.
protected function Form_PreRender() {
parent::Form_PreRender();
$this->dtgDomains->Refresh();
}
protected function Form_Create() {
parent::Form_Create();
// Create the Master DataGrid
// I make derived from another QDataGrid but is just for
// apply styles css, nothing important
$this->dtgDomains = new DomainGridControl($this);
$this->dtgDomains->SetDataBinder('dtgDomains_Bind');
// Here we start, create our first control a simple toogle
// button
$this->dtgDomains->AddColumn(
new QDataGridColumn('','<?= $_FORM->render_btnToggleRecordsSummary($_ITEM) ?>','HtmlEntities=false', 'Width=1px'));
// And some other data columns...
$this->dtgDomains->MetaAddColumn(QQN::Domains()->Zone,'Name=Domain',
array('OrderByClause' => QQ::OrderBy(QQN::Domains()->Zone),
'ReverseOrderByClause' => QQ::OrderBy(QQN::Domains()->Zone, false))
);
// Second... we need to create out Child QDataGrid sp put them
// hide in a column.
$this->dtgDomains->AddColumn(
new QDataGridColumn('','<?= $_FORM->render_ucRecordsSummary($_ITEM) ?>','HtmlEntities=false','Width=1px'));
}
public function dtgDomains_Bind() {
// Bind... nothing important...
}
// Function to render our toggle button column
// As you can see we pass as a parameter the item binded in the
// row of QDataGrid
public function render_btnToggleRecordsSummary(Domains $objDomain) {
// Create their unique id...
$objControlId = 'btnToggleRecordsSummary' . $objDomain->Id;
if (!$objControl = $this->GetControl($objControlId)) {
// If not exists create our toggle button who his parent
// is our master QDataGrid...
$objControl = new QButton($this->dtgDomains, $objControlId);
$objControl->Text = '+';
$objControl->CssClass = 'inputbutton';
// Pass the id of the bounded item just for other process
// on click event
$objControl->ActionParameter = $objDomain->Id;
// Add event on click the toogle button
$objControl->AddAction(new QClickEvent(), new QAjaxAction('btnToggleRecordsSummary_Click',$this->dtgDomains->WaitIcon));
}
// We pass the parameter of "false" to make sure the control doesn't render
// itself RIGHT HERE - that it instead returns its string rendering result.
return $objControl->Render(false);
}
// Clicking the toogle button...
public function btnToggleRecordsSummary_Click($strFormId, $strControlId, $strParameter) {
// First get the button himself for change '+' to '-'
$srcControl = $this->GetControl($strControlId);
$intDomainId = intval($strParameter);
// Look for our child QDatagrid if is render...
$objControlId = 'ucRecordsSummary' . $intDomainId;
$objControl = $this->GetControl($objControlId);
if ($objControl) {
// Ask if our Child DataGrid is visible...
if ($objControl->Visible) {
// Make it desapear ...
$objControl->Visible = false;
$srcControl->Text = '+';
} else {
// Or make it appear...
$objControl->Visible = true;
$srcControl->Text = '-';
}
// Important! Refresh the parent QDataGrid...
$this->dtgDomains->Refresh();
}
}
// Ladys and Gentleman... Our Child QDataGrid... =P
public function render_ucRecordsSummary(Domains $objDomain) {
$objControlId = 'ucRecordsSummary' . $objDomain->Id;
if (!$objControl = $this->GetControl($objControlId)) {
// Create the User Control Child QDataGrid passing the
// parent, in this case Master QDataGrid and the unique id.
$objControl = new RecordsSummary($this->dtgDomains, $objDomain, $objControlId);
//Put invisible at the begging, the toogle button gona do
//the job
$objControl->Visible = false;
}
return $objControl->Render(false);
}
}
DomainList::Run('DomainList', __APP_VIEW_ACCOUNT__ . '/domain.list.tpl.php');
?>Well thats all for the Master QDataGrid, at here everythings looks normal uh?
ok here is the Child QDataGrid...
<?php
// Load the QCubed Development Framework
require_once('../../qcubed.inc.php');
// Load User Controls -> Load Other QDataGrids Child of this one
// This is not awseome? QdataGrid can do everything!!
require (__APP_CONTROLS__ . '/a.records.list.php');
require (__APP_CONTROLS__ . '/cname.records.list.php');
require (__APP_CONTROLS__ . '/mx.records.list.php');
require (__APP_CONTROLS__ . '/srv.records.list.php');
require (__APP_CONTROLS__ . '/spf.records.list.php');
// As you can see thie QDataGrid extends the QPanel not a QForm
class RecordsSummary extends QPanel {
// QDatagrid Records Summary
public $dtgRecordsSummary;
// dtgDomains -> this is our Master QDataGrid
protected $objParentObject;
// Protected Objects
protected $objDomain;
// in the contructor pass the item bounded too just for other
// process
public function __construct($objParentObject, Domains $objDomain, $strControlId = null) {
try {
parent::__construct($objParentObject, $strControlId);
// Watch out for template later gonna talk about it,
// need a trick to look good.
$this->Template = __APP_CONTROLS__ . '/records.summary.tpl.php';
// Setting local the MAster QDataGrid to refresh on
// Saves on the Child DataGrid..
$this->objParentObject = $objParentObject;
$this->objDomain = $objDomain;
// Create the child DataGrid as a simply...QDataGrid
// normal
$this->dtgRecordsSummary = new QDataGrid($this);
// Bind him, the normal...
$this->dtgRecordsSummary->SetDataBinder('dtgRecordsSummary_Bind', $this);
// Need another Child QDataGrid? ok add their toogle
// button...
$this->dtgRecordsSummary->AddColumn(
new QDataGridColumn('','<?= $_CONTROL->ParentControl->render_btnToggleRecords($_CONTROL, $_ITEM) ?>','HtmlEntities=false', 'Width=1px'));
// Add some QDataGrid data to show...
$this->dtgRecordsSummary->AddColumn(
new QDataGridColumn('', '<?= $_ITEM . " Records" ?>'));
// Add if you need another column with the other child QDataGrid to show if you need
$this->dtgRecordsSummary->AddColumn(
new QDataGridColumn('','<?= $_CONTROL->ParentControl->render_ucRecords($_CONTROL, $_ITEM) ?>','HtmlEntities=false','Width=1px'));
} catch (QCallerException $objExc) {
$objExc->IncrementOffset();
throw $objExc;
}
}
public function dtgRecordsSummary_Bind() {
//Bind...
}
// Render other toggle...
public function render_btnToggleRecords($parControl, $strType) {
$strControlId = 'btnToggleRecords' . $this->objDomain->Id . $strType;
if (!$objControl = $parControl->GetChildControl($strControlId)) {
// But in this case the parent control of the button
// woluld be this child QDataGrid, dont forget that...
$objControl = new QButton($parControl, $strControlId);
$objControl->Text = '+';
$objControl->CssClass = 'inputbutton';
$objControl->ActionParameter = $strType;
// Important! for a better coding we want to all
// actions referer to the child QdataGris stay
// in the child Qdatagrid, so the actions are now
// QAjaxControlAction or QServerControlAction, were the
// controlId parameter is $this, becaouse in $this class
// is defined the event for this button... kind of easy,
// and clean.
$objControl->AddAction(new QClickEvent(), new QAjaxControlAction($this,'btnToggleRecords_Click',$this->objParentObject->WaitIcon));
}
// We pass the parameter of "false" to make sure the control doesn't render
// itself RIGHT HERE - that it instead returns its string rendering result.
return $objControl->Render(false);
}
// Button press make other child QDataGrid Appear..
public function btnToggleRecords_Click($strFormId, $strControlId, $strParameter) {
$srcControl = $this->Form->GetControl($strControlId);
$parControl = $srcControl->ParentControl;
$strType = $strParameter;
$objControlId = 'ucRecords' . $this->objDomain->Id . $strType;
if ($objControl = $parControl->GetChildControl($objControlId)) {
if ($objControl->Visible) {
$objControl->Visible = false;
$srcControl->Text = '+';
} else {
$objControl->Visible = true;
$srcControl->Text = '-';
}
// And refresh the Child QdataGrid this time...
$this->dtgRecordsSummary->Refresh();
}
}
// Create another child if you want... follow the same exactly
// idea as applid in Master QdataGrid...
public function render_ucRecords($parControl, $strType) {
$strControlId = 'ucRecords' . $this->objDomain->Id . $strType;
if (!$objControl = $parControl->GetChildControl($strControlId)) {
switch ($strType) {
case Records::A :
$objControl = new ARecordsList($this->dtgRecordsSummary, $this->objDomain, $strControlId);
break;
case Records::CNAME :
$objControl = new CNAMERecordsList($this->dtgRecordsSummary, $this->objDomain, $strControlId);
break;
case Records::MX :
$objControl = new MXRecordsList($this->dtgRecordsSummary, $this->objDomain, $strControlId);
break;
case Records::SRV :
$objControl = new SRVRecordsList($this->dtgRecordsSummary, $this->objDomain, $strControlId);
break;
case Records::SPF :
$objControl = new SPFRecordsList($this->dtgRecordsSummary, $this->objDomain, $strControlId);
break;
default:
$objControl = new QDataGrid($parControl);
break;
}
$objControl->Visible = false;
}
return $objControl->Render(false);
}
}
?>As i say before the tpl.php file has a trick to show good we need to break the row of qdatagrid to show pretty and not break the html...
here is the code
</td>
</tr>
<tr>
<td colspan="6">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><?php $_CONTROL->dtgRecordsSummary->Render(); ?></td>
</tr>
</table>
</td>
</tr>
<tr>
<td>Well thats it, the QDataGrid, hope must be usefull for someone it was for me.
In next post gonna expand this and make it with inline editing.
Regards,
JMI

This sounds like an excellent candidate for an example page, or at the very least, a wiki article.
Can you submit a ticket with a patch to add this as an example, or write a wiki page? :)
Do you have this as an example in order to read it and help to understand it in a practical case???
Many thanks to be interested in my topic when i created really i don't know were we can upload this example of use so you give me a great idea.
I'm preparing to make an article in the wiki and in the example page with all the cases and a better explanation. Stay alert i'm gonna post the link here.
Regards,
JMI
I just wanted to say THANK YOU for posting this. I have been trying to figure out how to call a function on a panel that contains a DataGrid and you have the answer. For those attempting the same thing as I, I wanted to place a DataGrid on a QPanel. In the DataGrid I wanted to create some controls, the problem is how do you reference the Panel's methods and not the Form's as no variable provided in the example site explains this:
$_CONTROL->ParentControl->MyFunction()
Hi what4893 I'm glad you like it and be useful to your work. Sorry for the bad posting by the way, it doesn't looks so nice the code highlighting is mixed all.
Now on I'm working a little as a core contributor for qcubed proyect so I hope take this post and pass it to the Example page to looks better.
Regards, JMI
really nice work! thank you
This would be great to add to the http://examples.qcu.be/ pages.
Ideas for example page (starting from example's tables)
- Master are projects
- child are person assigned to project
I started creating a form derived from project_list draft and applying to it your suggestion, but the work is too difficult for my level of knowledge.
Ciao, Gianni
Neverless I made attemp and here is the result of my brute force attack to this job.
I used qcubed 2.0.1 examples directory.
.... assets\_core\php\examples\
and created a new folder \master_child
Now the scripts derived from initial post.
I apologize for cryptic comments and brute editing but the first part of work is done.
In my environment (who replicate qcubed 2.0.1 - with codgen generated forms) pointing
... /qcubed_201/assets/_core/php/examples/master_child/project_list.php works as expected.
A very simple patch to assets\_core\php\examples\includes\examples.inc.php will insert my work in examples menus.
project_list.php
<?php
// Load the QCubed Development Framework
require('../qcubed.inc.php');
require ('./records.summary.php');
class ProjectListForm extends QForm {
// Local instance of the Meta DataGrid to list Projects
protected $dtgProjects;
// Create QForm Event Handlers as Needed
// protected function Form_Exit() {}
// protected function Form_Load() {}
// protected function Form_PreRender() {}
// protected function Form_Validate() {}
protected function Form_Create() {
// Instantiate the Meta DataGrid
//$this->objDefaultWaitIcon = new QWaitIcon($this);
$this->dtgProjects = new ProjectDataGrid($this);
//$this->dtgProjects->WaitIcon = $this->objDefaultWaitIcon;
// Style the DataGrid (if desired)
$this->dtgProjects->CssClass = 'datagrid';
$this->dtgProjects->AlternateRowStyle->CssClass = 'alternate';
// Add Pagination (if desired)
$this->dtgProjects->Paginator = new QPaginator($this->dtgProjects);
$this->dtgProjects->ItemsPerPage = 20;
/*************************************************************************
/ to use old Magia filter
/ uncomment line ($this->dtgAutovs->ShowFilter = false;)
**************************************************************************/
//$this->dtgProjects->ShowFilter = false;
/************************************************************************/
// Use the MetaDataGrid functionality to add Columns for this datagrid
// Here we start, create our first control a simple toogle button
$this->dtgProjects->AddColumn(
new QDataGridColumn('',
'<?= $_FORM->render_btnToggleRecordsSummary($_ITEM) ?>',
'HtmlEntities=false',
'Width=1px'));
// Create the Other Columns (note that you can use strings for project's properties, or you
// can traverse down QQN::project() to display fields that are down the hierarchy)
$this->dtgProjects->MetaAddColumn('Id');
$this->dtgProjects->MetaAddColumn('Name');
// $this->dtgProjects->MetaAddColumn('Description');
$this->dtgProjects->MetaAddColumn(QQN::Project()->ManagerPerson);
// Second... we need to create out Child QDataGrid sp put them hide in a column.
$this->dtgProjects->AddColumn(
new QDataGridColumn('',
'<?= $_FORM->render_ucRecordsSummary($_ITEM) ?>',
'HtmlEntities=false','Width=1px'));
// Specify the Datagrid's Data Binder method
$this->dtgProjects->SetDataBinder('dtgProjects_Bind');
// Make the DataGrid look nice
$objStyle = $this->dtgProjects->RowStyle;
$objStyle->FontSize = 12;
$objStyle = $this->dtgProjects->AlternateRowStyle;
$objStyle->BackColor = '#eaeaea';
$objStyle = $this->dtgProjects->HeaderRowStyle;
$objStyle->ForeColor = 'white';
$objStyle->BackColor = '#000066';
// Because browsers will apply different styles/colors for LINKs
// We must explicitly define the ForeColor for the HeaderLink.
// The header row turns into links when the column can be sorted.
$objStyle = $this->dtgProjects->HeaderLinkStyle;
$objStyle->ForeColor = 'white';
}
protected function dtgProjects_Bind() {
// We must first let the datagrid know how many total items there are
$this->dtgProjects->TotalItemCount = Project::CountAll();
// Next, we must be sure to load the data source, passing in the datagrid's
// limit info into our loadall method.
$this->dtgProjects->DataSource = Project::LoadAll(QQ::Clause(
$this->dtgProjects->OrderByClause,
$this->dtgProjects->LimitClause
));
}
// Function to render our toggle button column
// As you can see we pass as a parameter the item binded in the
// row of QDataGrid
public function render_btnToggleRecordsSummary(Project $objProject) {
// Create their unique id...
$objControlId = 'btnToggleRecordsSummary' . $objProject->Id;
if (!$objControl = $this->GetControl($objControlId)) {
// If not exists create our toggle button who his parent
// is our master QDataGrid...
$objControl = new QButton($this->dtgProjects, $objControlId);
$objControl->Text = '+';
$objControl->CssClass = 'inputbutton';
// Pass the id of the bounded item just for other process
// on click event
$objControl->ActionParameter = $objProject->Id;
// Add event on click the toogle button
$objControl->AddAction(new QClickEvent(), new QAjaxAction('btnToggleRecordsSummary_Click',$this->dtgProjects->WaitIcon));
}
// We pass the parameter of "false" to make sure the control doesn't render
// itself RIGHT HERE - that it instead returns its string rendering result.
return $objControl->Render(false);
}
// Clicking the toogle button...
public function btnToggleRecordsSummary_Click($strFormId, $strControlId, $strParameter) {
// First get the button himself for change '+' to '-'
$srcControl = $this->GetControl($strControlId);
$intDomainId = intval($strParameter);
// Look for our child QDatagrid if is render...
$objControlId = 'ucRecordsSummary' . $intDomainId;
$objControl = $this->GetControl($objControlId);
if ($objControl) {
// Ask if our Child DataGrid is visible...
if ($objControl->Visible) {
// Make it desapear ...
$objControl->Visible = false;
$srcControl->Text = '+';
} else {
// Or make it appear...
$objControl->Visible = true;
$srcControl->Text = '-';
}
// Important! Refresh the parent QDataGrid...
$this->dtgProjects->Refresh();
}
}
// Ladys and Gentleman... Our Child QDataGrid... =P
public function render_ucRecordsSummary(Project $objProject) {
$objControlId = 'ucRecordsSummary' . $objProject->Id;
if (!$objControl = $this->GetControl($objControlId)) {
// Create the User Control Child QDataGrid passing the
// parent, in this case Master QDataGrid and the unique id.
$objControl = new RecordsSummary($this->dtgProjects, $objProject, $objControlId);
//Put invisible at the begging, the toogle button gona do
//the job
$objControl->Visible = false;
}
return $objControl->Render(false);
}
}
// Go ahead and run this form object to generate the page and event handlers, implicitly using
// project_list.tpl.php as the included HTML template file
ProjectListForm::Run('ProjectListForm');
?>
project_list.tpl.php
<?php require('../includes/header.inc.php'); ?>
<?php $this->RenderBegin(); ?>
<div class="instructions">
<h1 class="instruction_title">Nested QDataGrid</h1>
In this example - (derived from JMY post) we will explain and demonstrate how to create a nested QDatagrid..<br/><br/>
With a MAster QDatagrid and through a button, usually a '+'to prove they can expand,<br/>
appear a Child QDataGrid with other content.<br/><br/>
Some preconceptions to consider first are:<br/>
- Master QDataGrid should go on the FORM.<br/>
- Child must be in QPanel QDataGrid <br/>
</div>
<?php $this->dtgProjects->Render(); ?>
<?php $this->RenderEnd(); ?>
<?php require('../includes/footer.inc.php'); ?>
records.summary.php
/*
Well thats all for the Master QDataGrid, at here everythings looks normal uh?
ok here is the Child QDataGrid...
*/
<?php
// Load the QCubed Development Framework
require_once('../../qcubed.inc.php');
// Load User Controls -> Load Other QDataGrids Child of this one
// This is not awseome? QdataGrid can do everything!!
/*
require (__APP_CONTROLS__ . '/a.records.list.php');
require (__APP_CONTROLS__ . '/cname.records.list.php');
require (__APP_CONTROLS__ . '/mx.records.list.php');
require (__APP_CONTROLS__ . '/srv.records.list.php');
require (__APP_CONTROLS__ . '/spf.records.list.php');
*/
// As you can see thie QDataGrid extends the QPanel not a QForm
class RecordsSummary extends QPanel {
// QDatagrid Records Summary
public $dtgRecordsSummary;
// dtgProjects -> this is our Master QDataGrid
protected $objParentObject;
// Protected Objects
protected $objProject;
// in the contructor pass the item bounded too just for other
// process
public function __construct($objParentObject, Project $objProject, $strControlId = null) {
try {
parent::__construct($objParentObject, $strControlId);
// Watch out for template later gonna talk about it,
// need a trick to look good.
$this->Template = 'records.summary.tpl.php';
// Setting local the MAster QDataGrid to refresh on
// Saves on the Child DataGrid..
$this->objParentObject = $objParentObject;
$this->objProject = $objProject;
// Create the child DataGrid as a simply...QDataGrid
// normal
$this->dtgRecordsSummary = new QDataGrid($this);
// Bind him, the normal...
$this->dtgRecordsSummary->SetDataBinder('dtgRecordsSummary_Bind', $this);
// Need another Child QDataGrid? ok add their toogle
// button...
/*
$this->dtgRecordsSummary->AddColumn(
new QDataGridColumn('',
'<?= $_CONTROL->ParentControl->render_btnToggleRecords($_CONTROL, $_ITEM) ?>',
'HtmlEntities=false',
'Width=1px'));
*/
// Add some QDataGrid data to show...
$this->dtgRecordsSummary->AddColumn(
new QDataGridColumn('', '<?= $_ITEM . " Records" ?>'));
$this->dtgRecordsSummary->AddColumn(new QDataGridColumn('First Name', '<?= $_ITEM->FirstName ?>', 'Width=120' ));
$this->dtgRecordsSummary->AddColumn(new QDataGridColumn('Last Name', '<?= $_ITEM->LastName ?>', 'Width=120'));
/*
// Add if you need another column with the other child QDataGrid to show if you need
$this->dtgRecordsSummary->AddColumn(
new QDataGridColumn('','<?= $_CONTROL->ParentControl->render_ucRecords($_CONTROL, $_ITEM) ?>','HtmlEntities=false','Width=1px'));
*/
} catch (QCallerException $objExc) {
$objExc->IncrementOffset();
throw $objExc;
}
}
public function dtgRecordsSummary_Bind() {
// $this->dtgRecordsSummary->TotalItemCount = Project::CountAll();
// Next, we must be sure to load the data source, passing in the datagrid's
// limit info into our loadall method.
/*
$this->dtgRecordsSummary->DataSource = Project::LoadAll(QQ::Clause(
$this->dtgRecordsSummary->OrderByClause,
$this->dtgRecordsSummary->LimitClause
));
*/
$this->dtgRecordsSummary->DataSource = $this->objProject->GetPersonAsTeamMemberArray
(QQ::Clause($this->dtgRecordsSummary->OrderByClause));
}
// Render other toggle...
public function render_btnToggleRecords($parControl, $strType) {
$strControlId = 'btnToggleRecords' . $this->objProject->Id . $strType;
if (!$objControl = $parControl->GetChildControl($strControlId)) {
// But in this case the parent control of the button
// woluld be this child QDataGrid, dont forget that...
$objControl = new QButton($parControl, $strControlId);
$objControl->Text = '+';
$objControl->CssClass = 'inputbutton';
$objControl->ActionParameter = $strType;
// Important! for a better coding we want to all
// actions referer to the child QdataGris stay
// in the child Qdatagrid, so the actions are now
// QAjaxControlAction or QServerControlAction, were the
// controlId parameter is $this, becaouse in $this class
// is defined the event for this button... kind of easy,
// and clean.
$objControl->AddAction(new QClickEvent(), new QAjaxControlAction($this,'btnToggleRecords_Click',$this->objParentObject->WaitIcon));
}
// We pass the parameter of "false" to make sure the control doesn't render
// itself RIGHT HERE - that it instead returns its string rendering result.
return $objControl->Render(false);
}
// Button press make other child QDataGrid Appear..
public function btnToggleRecords_Click($strFormId, $strControlId, $strParameter) {
$srcControl = $this->Form->GetControl($strControlId);
$parControl = $srcControl->ParentControl;
$strType = $strParameter;
$objControlId = 'ucRecords' . $this->objProject->Id . $strType;
if ($objControl = $parControl->GetChildControl($objControlId)) {
if ($objControl->Visible) {
$objControl->Visible = false;
$srcControl->Text = '+';
} else {
$objControl->Visible = true;
$srcControl->Text = '-';
}
// And refresh the Child QdataGrid this time...
$this->dtgRecordsSummary->Refresh();
}
}
// Create another child if you want... follow the same exactly
// idea as applid in Master QdataGrid...
public function render_ucRecords($parControl, $strType) {
$strControlId = 'ucRecords' . $this->objProject->Id . $strType;
if (!$objControl = $parControl->GetChildControl($strControlId)) {
switch ($strType) {
case Records::A :
$objControl = new ARecordsList($this->dtgRecordsSummary, $this->objDomain, $strControlId);
break;
case Records::CNAME :
$objControl = new CNAMERecordsList($this->dtgRecordsSummary, $this->objDomain, $strControlId);
break;
case Records::MX :
$objControl = new MXRecordsList($this->dtgRecordsSummary, $this->objDomain, $strControlId);
break;
case Records::SRV :
$objControl = new SRVRecordsList($this->dtgRecordsSummary, $this->objDomain, $strControlId);
break;
case Records::SPF :
$objControl = new SPFRecordsList($this->dtgRecordsSummary, $this->objDomain, $strControlId);
break;
default:
$objControl = new QDataGrid($parControl);
break;
}
$objControl->Visible = false;
}
return $objControl->Render(false);
}
}
?>
records.summary.tpl.php
</td></tr>
<tr>
<td colspan="6">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td><?php $_CONTROL->dtgRecordsSummary->Render(); ?></td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
for today that's all, folks.
Gianni
I tried it out immediately. It works great!
Would be interesting if it still works with the filtering (which is unfortunately not in here).
This deserves to be on the example page and can save a lot of people a great deal of work.
Best,
tronics
hello folks... and tronics,
a new cleaned version of project_list.php I hope will solve your filtering wishes....
and respect previous Alex suggestion on my poor editing style.
Now the bind is leaved, as is obvious, to codegenerated ProjectDataGridGen.class.php and I introduced also my trick to filter only on some field.
I will pack my scripts and create a ticket adding also my modified examples.inc.php if Vexed or Alex will agree.
<?php
// Load the QCubed Development Framework
require('../qcubed.inc.php');
// our child QPanel
require ('./records.summary.php');
class ProjectListForm extends QForm {
// Local instance of the Meta DataGrid to list Projects
protected $dtgProjects;
// Create QForm Event Handlers as Needed
//protected function Form_Exit() {}
//protected function Form_Load() {}
//protected function Form_PreRender() {}
//protected function Form_Validate() {}
protected function Form_Create() {
// Instantiate the Meta DataGrid
//$this->objDefaultWaitIcon = new QWaitIcon($this);
$this->dtgProjects = new ProjectDataGrid($this);
//$this->dtgProjects->WaitIcon = $this->objDefaultWaitIcon;
// Style the DataGrid (if desired)
$this->dtgProjects->CssClass = 'datagrid';
$this->dtgProjects->AlternateRowStyle->CssClass = 'alternate';
// Add Pagination (if desired)
$this->dtgProjects->Paginator = new QPaginator($this->dtgProjects);
$this->dtgProjects->ItemsPerPage = 20;
/*************************************************************************
/ to use old Magia filter
/ uncomment line ($this->dtgAutovs->ShowFilter = false;)
**************************************************************************/
// $this->dtgProjects->ShowFilter = false;
/************************************************************************/
// Use the MetaDataGrid functionality to add Columns for this datagrid
// Here we start, create our first control a simple toogle button
$this->dtgProjects->AddColumn(
new QDataGridColumn(
'',
'<?= $_FORM->render_btnToggleRecordsSummary($_ITEM) ?>',
'HtmlEntities=false',
'Width=1px'));
// Create the Other Columns
// Note that you can use strings for project's properties,
// or you can traverse down QQN::project() to display fields
// that are down the hierarchy)
// now is time to add some trick to filter only by some field
//
// remove filter from ID column
// $this->dtgProjects->MetaAddColumn('Id');
$colId =$this->dtgProjects->MetaAddColumn('Id');
$colId->FilterType="";
$this->dtgProjects->MetaAddTypeColumn('ProjectStatusTypeId', 'ProjectStatusType');
$this->dtgProjects->MetaAddColumn('Name');
//$this->dtgProjects->MetaAddColumn(QQN::Project()->ManagerPerson);
$this->dtgProjects->MetaAddColumn('Description');
// remove filter from field
//$this->dtgProjects->MetaAddColumn('StartDate');
$colStartDate = $this->dtgProjects->MetaAddColumn('StartDate');
$colStartDate->FilterType="";
// remove filter from field
//$this->dtgProjects->MetaAddColumn('EndDate');
$colEndDate = $this->dtgProjects->MetaAddColumn('EndDate');
$colEndDate->FilterType="";
// remove filter from field
// $this->dtgProjects->MetaAddColumn('Budget');
$colBudget = $this->dtgProjects->MetaAddColumn('Budget');
$colBudget->FilterType="";
// remove filter from field
// $this->dtgProjects->MetaAddColumn('Spent');
$colSpent = $this->dtgProjects->MetaAddColumn('Spent');
$colSpent->FilterType="";
// Second...
// we need to create out Child QDataGrid
// at moment we put them hide in a column.
$this->dtgProjects->AddColumn(
new QDataGridColumn('',
'<?= $_FORM->render_ucRecordsSummary($_ITEM) ?>',
'HtmlEntities=false','Width=1px'));
// Specify the Datagrid's Data Binder method
//$this->dtgProjects->SetDataBinder('dtgProjects_Bind');
// Make the DataGrid look nice
$objStyle = $this->dtgProjects->RowStyle;
$objStyle->FontSize = 12;
$objStyle = $this->dtgProjects->AlternateRowStyle;
$objStyle->BackColor = '#eaeaea';
$objStyle = $this->dtgProjects->HeaderRowStyle;
$objStyle->ForeColor = 'white';
$objStyle->BackColor = '#000066';
// Because browsers will apply different styles/colors for LINKs
// We must explicitly define the ForeColor for the HeaderLink.
// The header row turns into links when the column can be sorted.
$objStyle = $this->dtgProjects->HeaderLinkStyle;
$objStyle->ForeColor = 'white';
}
// Function to render our toggle button column
// As you can see we pass as a parameter the item binded in the
// row of QDataGrid
public function render_btnToggleRecordsSummary(Project $objProject) {
// Create their unique id...
$objControlId = 'btnToggleRecordsSummary' . $objProject->Id;
if (!$objControl = $this->GetControl($objControlId)) {
// If not exists create our toggle button who his parent
// is our master QDataGrid...
$objControl = new QButton($this->dtgProjects, $objControlId);
$objControl->Text = '+';
$objControl->CssClass = 'inputbutton';
// Pass the id of the bounded item just for other process
// on click event
$objControl->ActionParameter = $objProject->Id;
// Add event on click the toogle button
$objControl->AddAction(new QClickEvent(),
new QAjaxAction(
'btnToggleRecordsSummary_Click',
$this->dtgProjects->WaitIcon));
}
// We pass the parameter of "false" to make sure the control doesn't render
// itself RIGHT HERE - that it instead returns its string rendering result.
return $objControl->Render(false);
}
// Clicking the toogle button...
public function btnToggleRecordsSummary_Click($strFormId, $strControlId, $strParameter) {
// First get the button himself for change '+' to '-'
$srcControl = $this->GetControl($strControlId);
$intProjectId = intval($strParameter);
// Look for our child QDatagrid if is render...
$objControlId = 'ucRecordsSummary' . $intProjectId;
$objControl = $this->GetControl($objControlId);
if ($objControl) {
// Ask if our Child DataGrid is visible...
if ($objControl->Visible) {
// Make it desapear ...
$objControl->Visible = false;
$srcControl->Text = '+';
} else {
// Or make it appear...
$objControl->Visible = true;
$srcControl->Text = '-';
}
// Important! Refresh the parent QDataGrid...
$this->dtgProjects->Refresh();
}
}
// Ladys and Gentleman... Our Child QDataGrid...
public function render_ucRecordsSummary(Project $objProject) {
$objControlId = 'ucRecordsSummary' . $objProject->Id;
if (!$objControl = $this->GetControl($objControlId)) {
// Create the User Control Child QDataGrid passing the
// parent, in this case Master QDataGrid and the unique id.
$objControl = new RecordsSummary($this->dtgProjects, $objProject, $objControlId);
//Put invisible at the begging, the toogle button gona do
//the job
$objControl->Visible = false;
}
return $objControl->Render(false);
}
}
// Go ahead and run this form object to generate the page and event handlers,
// implicitly using project_list.tpl.php as the included HTML template file
ProjectListForm::Run('ProjectListForm');
?>
Best, Gianni
Great =) Now sorting and filtering works.
You did this very well!! Thanks for sharing.
Best,
tronics
This is indeed absolutely amazing!! I would love to have it included into the core distribution. Can you make a ZIP file with all of these and attach them to a ticket?
UPDATE: Just saw the attached files to another forum thread. Created ticket 736: http://trac.qcu.be/projects/qcubed/ticket/736