Filter the items in an atkManyToOneRelation

From Achievo/ATK Wiki

Jump to: navigation, search

ATK Howto: Filter the items in an atkManyToOneRelation

Complexity: advanced
Author: Ivo Jansch <ivo@achievo.org>

List of other Howto's

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.

Personal tools
Navigation