Filter the items in an atkManyToOneRelation
From Achievo/ATK Wiki
|
ATK Howto: Filter the items in an atkManyToOneRelation
|
Contents |
Intro
An atkManyToOneRelation is used to create a dropdown from which the user can select an item from another node. For example, to select the manager of a project, the department of an employee etc.
Sometimes you will want to filter the items that appear in the dropdown. There are 2 ways to accomplish this.
One way is to add a filter to the node to which you have a relation. The effect is that in all situations where this node is used, the filter is applied. This is useful for example if you want to see only records where status='active', in all cases.
The other way is to add a filter to just the one atkManyToOneRelation where you need it. This is useful for specific filters that should only be set in this particular atkManyToOneRelation.
Both methods are explained in detail below.
Adding a filter to a node
If you want to filter a node in every case where it is used, you can add the following code to the node constructor:
<?php useattrib("atklistattribute"); class project extends atkNode { function project() { $this->atkNode("project"); $this->add(new atkAttribute("id", AF_AUTOKEY)); $this->add(new atkAttribute("name")); $this->add(new atkListAttribute("status", array("active", "archived")); $this->addFilter("status='active'"); $this->setTable("project"); } } ?>
This will filter the project node for active records. In the entire application, if the project node is used, either directly, or through a relation, the filter is applied and only active projects are displayed.
Adding a filter to a specific atkManyToOneRelation
Suppose in the above example, that you don't want to filter active projects in all cases, but only in one particular atkManyToOneRelation.
Here's how: don't add the addFilter() call from the above example. Instead, modify the code for adding the atkManyToOneRelation.
Suppose that your relation was coded like this:
$this->add(new atkManyToOneRelation("project", "mymodule.project"));
By changing the code slightly, you can apply a filter to the projects here, so only active projects are selectable:
$rel = &new atkManyToOneRelation("project", "mymodule.project"); $rel->setDestinationFilter("status='active'"); $this->add($rel);
Dynamic filtering
Occasionaly, the filter you apply to an atkManyToOneRelation is dependent on other data in the record that's currently being edited. For example, for a project, you may want to select only contactpersons that match the customer for same project.
In this case, you can use template variables between brackets to use fields from the current record in the filter:
$this->add(new atkManyToOneRelation("customer", "organization.organization")); $rel = &new atkManyToOneRelation("manager", "organization.contact"); $rel->setDestinationFilter("contact.customer_id = [customer.id]"); $this->add($rel);
This will, at runtime, filter the contact dropdown by customer id. If the above sample code does not work for you, see this or that thread.
(Note the dot-notation. Customer is the name of the other attribute in this node, and since that's a relation, we can reference fields from the organization node ('id' in this case) in the template.)
Ajax
As of ATK 5.7, you can add an additional line of code to the previous example:
$cust = &$this->add(new atkManyToOneRelation("customer", "organization.organization")); $rel = &new atkManyToOneRelation("manager", "organization.contact"); $rel->setDestinationFilter("contact.customer_id = [customer.id]"); $this->add($rel); $cust->addDependee("manager");
This will refresh the manager dropdown on the fly using Ajax, as soon as the user changes the customer dropdown.
Related
If you want to filter items in an atkOneToManyRelation, you can find some ideas here.