Extending METAL macros

metal:extend-macro

Attribute syntax

metal:extend-macro="EXPRESSION"

Remarks

Only valid when defined on the same element as a metal:define-macro attribute is present. This attribute indicates that the current macro definition ("the extension") extends the macro referenced by the EXPRESSION ("the extended macro").

The meaning of extension is as follows:

  • The extension may optionally provide any number of elements decorated with metal:fill-slot attributes. These fill slots in the extended macro, as if the extension was decorated with metal:use-macro.
  • Any slots defined upon the extended macro which are not filled by the extension will remain available for filling when the extended macro is used.
  • Within fill-slot attributes, the extension may optionally provide new slots of its own via metal:define-slot attributes - just as if the fill-slot attribute upon the extension were a define-macro attribute. If the extension defines a slot of the same name as the slot it has filled, then when the macro is used, both the extension's markup and the slot-filling markup from the macro usage will be combined.

Software developers may think of this process as being akin to 'subclassing' the extended macro. The net effect is that the extension functions as the extended macro, except that it may provide content for the extended macro's slots, and may additionally define new slots of its own, or modify/override the manner in which some of the extended macro's slots are filled.

Macro-extension example

The following example shows a macro for an 'image box' widget. It may be used as-is, or using the extended version, which adds copyright information to that widget.

<!-- Base macro -->
<div class="imagebox" metal:define-macro="image_box">
  <img metal:define-slot="image_element" src="" />
  <div metal:define-slot="description">Description goes here</div>
</div>

<!-- Extender -->
<div metal:define-macro="image_box_with_copyright" metal:extend-macro="image_box">
  <div metal:fill-slot="description" class="info_wrapper">
    <div metal:define-slot="description">Description goes here</div>
    <div class="copyright_statement">
      <p>
        Image copyright:
        <span metal:define-slot="copyright_holder">Copyright holder</span>
      </p>
    </div>
  </div>
</div>

<!-- Usage -->
<div metal:use-macro="image_box_with_copyright">
  <img metal:fill-slot="image_element" src="http://example.com/my_image_url.png" />
  <div metal:fill-slot="description">
    <p>This is the real image description</p>
  </div>
  <span metal:fill-slot="copyright_holder">Joseph Bloggs</span>
</div>

<!-- How this renders -->
<div class="imagebox">
  <img src="http://example.com/my_image_url.png" />
  <div class="info_wrapper">
    <div>
      <p>This is the real image description</p>
    </div>
    <div class="copyright_statement">
      <p>
        Image copyright:
        <span>Joseph Bloggs</span>
      </p>
    </div>
  </div>
</div>