Back to Code repository sumary
The 2 levels DB tree navigator is a very useful component for displaying hierarchically organized data in the form of categories/subcategories. The classic usage is in products catalogues, where the db tree is used to filter data based on the active subcategory.
There is a case where you might need to force syncing the navigator, because you have selected a product regardles of its subcategory/category binding, such as when you search for a product by name, or id.
The following code shows how to resync the navigator to display the active subcategory/category matching the active row of the mask. See how to set up a navigator to get familiar with the datasources involved. A general assumption sees products bound to a subcategory which is uniquely bound to a parent category.
function syncNav() { $sc =& $this->subcategory_source; $cc =& $this->category_source; //this is the subcategory of the currently active product. it is the target for our resyncing. $subcategory_id = $this->data->fields->subcategory_id->getValue(); //we drop the filter that synchronizes the subcategory source to the category source so that we can loop through the whole source $sc->dropFilter("category_id = ?"); $sc->firstRow(); $num_rows = $sc->getNumRows(); //we now look for the subcategory matching the one bound the product we are displaying for ($i=0; $i<$num_rows; $i++) { $row = $sc->row(); if($row['id'] == $subcategory_id) { //we've found it. We take note and exit. $category_id = $sc->fields->category_id->getValue(); break; } $sc->nextRow(); } //Once we found the subcategory we need to find the category $cc->firstRow(); $num_rows = $cc->getNumRows(); for ($i=0; $i<$num_rows; $i++) { $row = $cc->row(); if($row['id'] == $category_id) { //We've found it. We don't have to do anything since by stopping here, we leave the current row as active break; } $cc->nextRow(); } //we add back the filter that synchronizes the subcategories $this->subcategory_source->addFilter("category_id = ?", $this->category_source->fields->id); //adding the filter has the unfortunate side effect of resetting the datasource, so we need to loop once more to select the active row. $sc->firstRow(); $num_rows = $sc->getNumRows(); for ($i=0; $i<$num_rows; $i++) { $row = $sc->row(); if($row['id'] == $subcategory_id) { //no need to do anything, as simply exiting will leave this row as active break; } $sc->nextRow(); } }
The code makes three loops in order to synchronize the db tree. The first finds the active subcategory, and obtains the parent category. The second loop finds and sets the active category. The third loop is necessary because the datasource changes after applying the filter that keeps the relationship between parent category and child subcategory. It refinds the active subcategory and leaves it current.
2007-02-12: initial contrib. pecus