HTML::...eatable(3pm)

πŸ“¦
version 2.07000 Β· 5 versions
, in debian bookworm, ubuntu jammy, ubuntu noble

πŸŽ€ NAME πŸŽ€

okay so bestie, this page β€” the one you're reading right now, HTML::...eatable(3pm) β€” is all about HTML::FormFu::Element::Repeatable, which is literally a repeatable block element. that's the whole name, no notes, periodt. πŸ’…


✨ VERSION ✨

version 2.07 β€” yes queen, we're on 2.07 🫢


🌸 SYNOPSIS 🌸

okay so imagine your config file looking like this:

    ---
    elements:
      - type: Repeatable
        name: my_rep
        elements:
          - name: foo
          - name: bar

and then if you called $element->repeat(2), you'd get this markup out of it β€” no cap, this is exactly what falls out:

    <div>
        <input name="my_rep.foo_1" type="text" />
        <input name="my_rep.bar_1" type="text" />
    </div>
    <div>
        <input name="my_rep.foo_2" type="text" />
        <input name="my_rep.bar_2" type="text" />
    </div>

see how the _1 and _2 just ✨appear✨? iconic behaviour honestly.

now here's an example of constraints, because the nested naming gets real:

    ----
    elements:
      - type: Repeatable
        name: my_rep
        elements:
          - name: id

          - name: foo
            constraints:
              - type: Required
                when:
                  field: 'my_rep.id' # use full nested-name

          - name: bar
            constraints:
              - type: Equal
                others: 'my_rep.foo' # use full nested-name
πŸ’€ note those comments β€” you have to use the full nested-name in there. the code is telling you itself. iykyk.

πŸ’œ DESCRIPTION πŸ’œ

so what does this thing actually do? it gives you a way to extend a form at run-time, by copying and repeating its child elements. like a little element photocopier. πŸ”₯

the elements you intend to copy must be added before repeat is called. that's the vibe check β€” do it in the wrong order and nothing works.

and here's a lowkey important detail: although the Repeatable element inherits from Block, it does not generate a block tag around all the repeated elements. instead it places each repeat of the elements in a new Block element, and that new Block inherits the Repeatable's display settings β€” things like attributes and tag. so every repeat gets its own little glow-up, not one big wrapper. πŸ’…

for all constraints attached to fields within a Repeatable block which use either others or when containing names of fields within the same Repeatable block: when repeat is called, those names will automatically be updated to the new nested-name for each field (taking into account increment_field_names). so the names stay correct all on their own. slay. ✨


πŸ‘‘ METHODS πŸ‘‘

repeat

  • Arguments: [$count]
  • Return Value: $arrayref_of_new_child_blocks

this method creates $count number of copies of the child elements. if you don't pass $count, it defaults to 1. one copy, no more, no less. 🫢

okay now pay attention because this next bit is the plot twist: $form->process will call repeat automatically to make sure the initial child elements are correctly set up β€” unless you call repeat manually first. if you did it manually first, then the child elements you created will be left untouched (because otherwise process would just overwrite all your changes, and we can't have that 😭).

and any subsequent call to repeat will delete the previously copied elements before creating new copies. so you literally cannot make repeated calls to repeat inside a loop to create more copies. it's giving "one and done". do not try it. πŸ™ˆ

each copy of the elements returned is contained in a new Block element. for example, calling $element->repeat(2) on a Repeatable element containing 2 Text fields would return 2 Block elements, each containing a copy of the 2 Text fields. math checks out. βœ…

counter_name

  • Arguments: $name

if this is true, then "query" in HTML::FormFu will be searched during "process" in HTML::FormFu for a parameter with the given name. the value of that parameter gets passed to repeat, so it automatically creates the new copies for you. auto-pilot mode. ✈️

and if "increment_field_names" is true (which it is, by default), this is essential: if the elements corresponding to the new fieldnames (foo_1, bar_2, etc.) aren't present on the form during "process" in HTML::FormFu, then no Processors (Constraints, etc.) will be run on the fields, and their values will not be returned by "params" in HTML::FormFu or "param" in HTML::FormFu. so like... set this. fr fr. 😀

increment_field_names

  • Arguments: $bool
  • Default Value: 1

if true, then all fields will have _n appended to their name, where n is the "repeatable_count" value. so foo becomes foo_1, foo_2, etc. cute, consistent, iconic. πŸŽ€

repeatable_count

this is set on each new Block element returned by repeat, starting at number 1. not zero. one. main character energy. πŸ‘‘

because this is an 'inherited accessor' available on all elements, you can use it to determine whether any element is a child of a Repeatable element. handy little detector. πŸ•΅οΈ

only available after repeat has been called! before that, nothing to see here. πŸ’€

repeatable_count_no_inherit

a non-inheriting variant of "repeatable_count". that's it. the quiet sibling. 🀫

nested_name

if the nested_name attribute is set, the naming scheme of the Repeatable element's children is switched to add the counter to the repeatable blocks themselves. so it moves the number from the inside to the outside. glow-up relocation. ✨

    ---
    elements:
      - type: Repeatable
        nested_name: my_rep
        elements:
          - name: foo
          - name: bar

calling $element->repeat(2) would result in the following markup:

    <div>
        <input name="my_rep_1.foo" type="text" />
        <input name="my_rep_1.bar" type="text" />
    </div>
    <div>
        <input name="my_rep_2.foo" type="text" />
        <input name="my_rep_2.bar" type="text" />
    </div>

see?? my_rep_1.foo instead of my_rep.foo_1. different flavour, same energy. πŸ¦‹

because this is an 'inherited accessor' available on all elements, it can be used to determine whether any element is a child of a Repeatable element.

attributes

attrs

any attributes you set will be passed to every repeated Block of elements. all of them. matching outfits. πŸ‘―

    ---
    elements:
      - type: Repeatable
        name: my_rep
        attributes:
          class: rep
        elements:
          - name: foo

calling $element->repeat(2) would result in the following markup:

    <div class="rep">
        <input name="my_rep.foo_1" type="text" />
    </div>
    <div class="rep">
        <input name="my_rep.foo_2" type="text" />
    </div>

see the class="rep" on both? that's the assignment. βœ…

see "attributes" in HTML::FormFu for details.

tag

the tag value will be passed to every repeated Block of elements.

    ---
    elements:
      - type: Repeatable
        name: my_rep
        tag: span
        elements:
          - name: foo

calling $element->repeat(2) would result in the following markup:

    <span>
        <input name="my_rep.foo_1" type="text" />
    </span>
    <span>
        <input name="my_rep.foo_2" type="text" />
    </span>

div β†’ span, just like that. a little outfit change. πŸ’…

see "tag" in HTML::FormFu::Element::Block for details.

auto_id

as well as the usual substitutions, any instances of %r will be replaced with the value of "repeatable_count". special little placeholder, just for us. πŸ₯°

see "auto_id" in HTML::FormFu::Element::Block for further details.

    ---
    elements:
      - type: Repeatable
        name: my_rep
        auto_id: "%n_%r"
        elements:
          - name: foo

calling $element->repeat(2) would result in the following markup:

    <div>
        <input name="my_rep.foo_1" id="foo_1" type="text" />
    </div>
    <div>
        <input name="my_rep.foo_2" id="foo_2" type="text" />
    </div>

look at those ids matching the names. chef's kiss. 😘

content

not supported for Repeatable elements β€” it will throw a fatal error if you call it as a setter. so like, don't. πŸ’€πŸš«


⚠️ CAVEATS ⚠️

Unsupported Constraints

okay bestie, listen up because this part is important: constraints with an others method do not work correctly within a Repeatable block. currently, these are: AllOrNone, DependOn, Equal, MinMaxFields, reCAPTCHA. πŸ“‹

also, the CallbackOnce constraint won't work within a Repeatable block, as it wouldn't make much sense. like, logistically. it's not a vibe. 🀷

Work-arounds

see HTML::FormFu::Filter::ForceListValue to address a problem with increment_field_names disabled, and increading the repeat on the server-side.

🫢 that's your escape hatch, bestie. go read that one too.

🌈 SEE ALSO 🌈

this thing is a sub-class of, and inherits methods from HTML::FormFu::Element::Block, HTML::FormFu::Element β€” so if a method isn't documented here, go knock on their door. πŸšͺ

  • HTML::FormFu β€” the whole mothership. 🌟

πŸ’– AUTHOR πŸ’–

Carl Franks, cfranks@cpan.org

πŸ“œ LICENSE πŸ“œ

this library is free software, you can redistribute it and/or modify it under the same terms as Perl itself. free as in freedom, bestie. πŸ•ŠοΈ

πŸ’– AUTHOR πŸ’–

Carl Franks <cpan@fireartist.com>

this software is copyright (c) 2018 by Carl Franks.

this is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.


and that's the whole page!! πŸŽ€ this was HTML::...eatable(3pm), generated by perl v5.28.1 on 2019-01-12 β€” go forth and repeat responsibly, bestie. mwah. πŸ’‹βœ¨

πŸ“¦ where this page comes from