|
| 1 | +--- |
| 2 | +docid: hack-builder-custom-renderers |
| 3 | +title: Custom Renderers |
| 4 | +layout: docs |
| 5 | +permalink: /docs/hack-builder/custom-renderers/ |
| 6 | +--- |
| 7 | + |
| 8 | +There are 3 main ways to implement custom rendering: |
| 9 | + |
| 10 | + - Pre-process your values to code, then use `HackBuilderValues::literal()` or |
| 11 | + `HackBuilderKeys::literal()` |
| 12 | + - use `HackBuilderValues::lambda()` or `HackBuilderKeys::lambda()` |
| 13 | + - create classes that implement `IHackBuilderValueRenderer` or |
| 14 | + `IHackBuilderKeyRenderer` |
| 15 | + |
| 16 | +Pre-processing |
| 17 | +-------------- |
| 18 | + |
| 19 | +Pre-process the values so that the keys/values are the literal code you want |
| 20 | +instead: |
| 21 | + |
| 22 | +``` php |
| 23 | +<?hh |
| 24 | + |
| 25 | +$map = Map { /* ... */ }; |
| 26 | +$processed = Map { }; |
| 27 | +foreach ($map as $k => $v) { |
| 28 | + $processed[my_render_function($k)] = $v; |
| 29 | +} |
| 30 | +$builder |
| 31 | + ->addValue( |
| 32 | + $map, |
| 33 | + HackBuilderValues::map( |
| 34 | + HackBuilderKeys::literal(), |
| 35 | + HackBuilderValues::export(), |
| 36 | + ), |
| 37 | + ); |
| 38 | +``` |
| 39 | + |
| 40 | +This is usually the right approach for a single value, but not the most readable |
| 41 | +for multiple values, eg for collections. |
| 42 | + |
| 43 | +Lambdas |
| 44 | +------- |
| 45 | + |
| 46 | +The lambda takes an `IHackCodegenConfig` and the value; the value can be used |
| 47 | +to create a `HackCodegenFactory` if neccessary, though as there's usually one |
| 48 | +in scope, it's usually unneeded. |
| 49 | + |
| 50 | +``` php |
| 51 | +<?hh |
| 52 | + |
| 53 | +$map = Map { /* ... */ }; |
| 54 | +$builder |
| 55 | + ->addValue( |
| 56 | + $map, |
| 57 | + HackBuilderValues::map( |
| 58 | + HackBuilderKeys::lambda( |
| 59 | + ($_config, $v) ==> my_render_function($v), |
| 60 | + ), |
| 61 | + HackBuilderValues::export(), |
| 62 | + ), |
| 63 | + ); |
| 64 | +``` |
| 65 | + |
| 66 | +This can be the right choice when the same renderer is needed for many values but |
| 67 | +in few places. |
| 68 | + |
| 69 | +Custom Renderer Classes |
| 70 | +----------------------- |
| 71 | + |
| 72 | +If you are using the same renderer in multiple places, you can implement the |
| 73 | +`IHackBuilderKeysRenderer<T>` or `IHackBuilderValuesRenderer<T>` interfaces; |
| 74 | +this is the same way the built-ins are implemented. |
| 75 | + |
| 76 | +While it's possible to implement both in the same class, it's usually better |
| 77 | +not to so that the hack typechecker has more visibility into argument order |
| 78 | +mistakes for collections. |
0 commit comments