Attribute dependency callbacks
From Achievo/ATK Wiki
|
ATK Howto: Attribute dependency callbacks
|
As of ATK 6.5, ATK supports registering attribute dependency callbacks. This powerful mechanism replaces the older atkAttribute::addDependee mechanism, which is now deprecated (but still works and uses the new dependency mechanism internally).
Dependency callbacks will be called for the initial form setup and if the value of an attribute changes. The mechanism is supported by all attributes which implement an on-change handler (most attributes and relations). At the moment dependency callbacks can easily hide, show and refresh attributes by using simple PHP code (no JavaScript needed), more features might be added in the future.
Most examples below use a PHP 5.3 closures, but you can use other types of callbacks (everything for which is_callable returns true) too.
Contents |
Show / hide
An example using a callback function in the node:
// Tell ATK that there's a dependency on the type field, and it's implemented in the typeDependency method. $this->getAttribute('type')->addDependency(array($this, "typeDependency")); ... // The dependency function public function typeDependency(atkEditFormModifier $modifier) { $record = $modifier->getRecord(); if ($record['type'] == 'other') { $modifier->showAttribute('description'); } else { $modifier->hideAttribute('description'); } }
If you use PHP 5.3, you can use closures instead, removing the need to implement a function in the node:
$this->getAttribute('type')->addDependency(function(atkEditFormModifier $modifier) { $record = $modifier->getRecord(); if ($record['type'] == 'other') { $modifier->showAttribute('description'); } else { $modifier->hideAttribute('description'); } });
In the example above we only show the description attribute when the value of the type attribute is "other". Because the dependency is already evaluated upon initial form setup the description field might already be hidden before the user gets to see the form (depending on the default value of type). After the user changes the type in the form an Ajax callback is used to re-evaluate the dependency and hide/show the description field using some JavaScript code (which you don't need to know about).
Refresh
Another example:
$this->getAttribute('customer')->addDependency(function(atkEditFormModifier $modifier) { $modifier->refreshAttribute('contact'); $modifier->refreshAttribute('contract'); });
In this example we will be refreshing the contact and contract attributes when another customer is selected. Assuming these attributes have a filter which is based on the currently selected customer, this means you can now only select contacts and contracts for the newly selected customer.
Show / hide attributes of a relation
You can also show and hide columns of a relation.:
... // The dependency function public function typeDependency(atkEditFormModifier $modifier) { $record = $modifier->getRecord(); if ($record['type'] == 'other') { $modifier->getNode() ->getAttribute('contracts') ->getDestination ->getAttribute('salary') ->addFlag(AF_HIDE_LIST); } else { $modifier->getNode() ->getAttribute('contracts') ->getDestination ->getAttribute('salary') ->removeFlag(AF_HIDE_LIST); } $modifier->refreshAttribute('contracts'); }
Which will show or hide the salary column of the contracts, depending on the type. Note the refresh of data at the end of the function.
Custom JavaScript
You can also execute custom JavaScript using the scriptCode method, this makes it possible to do any kind of manipulation you can think of:
$this->getAttribute('type')->addDependency(function(atkEditFormModifier $modifier) { $modifier->scriptCode(" alert('Nice, huh?'); "); });
Node and Mode
(Added by WayneH 3/2011) The current Node (in module.node format) and Mode (add or edit) are available with
$node = $modifier->getNode(); $mode = $modifier->getMode();
Refresh Note
(Added by WayneH 3/2011)
Dependency processing is split into 2 phases.
In first phase you can update $record.
In second, you send a callback.
So you need to wrap your callbacks with if (! $modifier->isInitial()) { }
Example -
public function fk_billing_custid_changed(atkEditFormModifier $modifier) { $record = &$modifier->getRecord(); if (! $modifier->isInitial()) { $record['fk_pickup_custid'] = $record['fk_billing_custid']; $modifier->refreshAttribute('fk_pickup_custid'); } }