Looping tags and Sub-tags

### Index Up

## Looping tags and Sub-tags

Certain tags are not standalone; these are the ones that are interpreted as part of a surrounding looping tag like `[loop]`, `[item-list]`, `[query]`, or `[region]`.

        [PREFIX-accessories]
        [PREFIX-alternate]
        [PREFIX-calc]
        [PREFIX-change]
        [PREFIX-change]
        [PREFIX-code]
        [PREFIX-data]
        [PREFIX-description]
        [PREFIX-discount]
        [PREFIX-field]
        [PREFIX-increment]
        [PREFIX-last]
        [PREFIX-match]
        [PREFIX-modifier]
        [PREFIX-next]
        [PREFIX-param]
        [PREFIX-price]
        [PREFIX-quantity]
        [PREFIX-subtotal]
        [if-PREFIX-data]
        [if-PREFIX-field]
        [modifier-name]
        [quantity-name]

PREFIX represents the prefix that is used in that looping tag. They are only interpreted within their container and only accept positional parameters. The default prefixes:

        Tag           Prefix     Examples
        -----        --------   ----------
        [loop]        loop       [loop-code], [loop-field price], [loop-increment]
        [item-list]   item       [item-code], [item-field price], [item-increment]
        [search-list] item       [item-code], [item-field price], [item-increment]
        [query]       sql        [sql-code], [sql-field price], [sql-increment]

Sub-tag behavior is consistent among the looping tags.

There are two types of looping lists; ARRAY and HASH.

An array list is the normal output of a `[query]`, a search, or a `[loop]` tag. It returns from 1 to N `return fields`, defined in the `mv_return_fields` or `rf` variable or implicitly by means of a SQL field list. The two queries below are essentially identical:

        [query sql="select foo, bar from products"]
        [/query]

        [loop search="
                        ra=yes
                        fi=products
                        rf=foo,bar
        "]

Both will return an array of arrays consisting of the `foo` column and the `bar` column. The Perl data structure would look like:

        [
            ['foo0', 'bar0'],
            ['foo1', 'bar1'],
            ['foo2', 'bar2'],
            ['fooN', 'barN'],
        ]

A hash list is the normal output of the [item-list] tag. It returns the value of all return fields in an array of hashes. A normal [item-list] return might look like:

        [
            {
                code     => '99-102',
                quantity => 1,
                size     => 'XL',
                color    => 'blue',
                mv_ib    => 'products',
            },
            {
                code     => '00-341',
                quantity => 2,
                size     => undef,
                color    => undef,
                mv_ib    => 'products',
            },

        ]

You can also return hash lists in queries:

        [query sql="select foo, bar from products" type=hashref]
        [/query]

Now the data structure will look like:

        [
            { foo => 'foo0', bar => 'bar0' },
            { foo => 'foo1', bar => 'bar1' },
            { foo => 'foo2', bar => 'bar2' },
            { foo => 'fooN', bar => 'barN' },
        ]

[PREFIX-accessories arglist]
  The same as the [accessories ...] tag except always supplied the current item code. If the list is a hash list, i.e. an [item-list], then the value of the current item hash is passed so that a value default can be established.

[PREFIX-alternate N] DIVISIBLE [else] NOT DIVISIBLE [/else][/PREFIX-alternate]
  Set up an alternation sequence. If the item-increment is divisible by `N', the text will be displayed. If an `[else]NOT DIVISIBLE TEXT[/else]' is present, then the NOT DIVISIBLE TEXT will be displayed. For example:

          [item-alternate 2]EVEN[else]ODD[/else][/item-alternate]
          [item-alternate 3]BY 3[else]NOT by 3[/else][/item-alternate]

[PREFIX-calc] 2 + [item-field price] [/PREFIX-calc]
  Calls perl via the equivalent of the [calc] [/calc] tag pair. Much faster to execute.

[PREFIX-change][conditoon] ... [/condition] TEXT [/PREFIX-change]
  Sets up a breaking sequence that occurs when the contents of [condition] [/condition] change. The most common one is a category break to nest or place headers.

  The region is only output when a field or other repeating value between [condition] and [/condition] changes its value. This allows indented lists similar to database reports to be easily formatted. The repeating value must be a tag interpolated in the search process, such as `[PREFIX-field field]` or `[PREFIX-data database field]`. If you need access to MML tags, you can use [PREFIX-calc] with a $Tag->foo() call.

  Of course, this will only work as you expect when the search results are properly sorted.

  The value to be tested is contained within a `[condition]value[/condition]` tag pair. The `[PREFIX-change]` tag also processes an `[else] [/else]` pair for output when the value does not change.

  Here is a simple example for a search list that has a field `category` and `subcategory` associated with each item:

       <TABLE>
       <TR><TH>Category</TH><TH>Subcategory</TH><TH>Product</TH></TR>
       [search-list]
       <TR>
          <TD>
               [item-change cat]

               [condition][item-field category][/condition]

                       [item-field category]
               [else]
                       &nbsp;
               [/else]
               [/item-change]
          </TD>
          <TD>
               [item-change]

               [condition][item-field subcategory][/condition]

                       [item-field subcategory]
               [else]
                       &nbsp;
               [/else]
               [/on-change]
          </TD>
          <TD> [item-field name] </TD>
       [/search-list]
       </TABLE>

  The above should put out a table that only shows the category and subcategory once, while showing the name for every product. (The `&nbsp;` will prevent blanked table cells if you use a border.)

[PREFIX-code]
  The key or code of the current loop. In an [item-list] this is always the product code; in a loop list it is the value of the current argument; in a search it is whatever you have defined as the first mv_return_field (rf).

[PREFIX-data table field]
  Calls the column `field` in database table table for the current [PREFIX-code]. This may or may not be equivalent to `[PREFIX-field field]` depending on whether your search table is defined as one of the `ProductFiles`.

[PREFIX-description]
  The description of the current item, as defined in the `catalog.cfg` directive `DescriptionField`. In the demo, it would be the value of the field `description` in the table `products`.

  If the list is a hash list, and the lookup of `DescriptionField` fails, then the attribute `description` will be substituted. This is useful to supply shopping cart descriptions for on-the-fly items.

[PREFIX-discount]
  The price of the current item is calculated, and the difference between that price and the list price (quantity one) price is output. This may have different behavior than you expect if you set the [discount] [/discount] tag along with quantity pricing.

[PREFIX-field]
  Looks up a field value for the current item in one of several places, in this order:

          1. The first ProductFiles entry.
          2. Additional ProductFiles in the order they occur.
          3. The attribute value for the item in a hash list.
          4. Blank

  A common user error is to do this:

          [loop search="
                          fi=foo
                          se=bar
                      "]

          [loop-field foo_field]
          [/loop]

  In this case, you are searching the table `foo` for a string of `bar`. When it is found, you wish to display the value of `foo_field`. Unless `foo` is in `ProductFiles` and the code is not present in a previous product file, you will get a blank or some value you don't want. What you really want is `[loop-data foo foo_field]`, which specifically addresses the table `foo`.

[PREFIX-increment]
  The current count on the list, starting from either 1 in a zero-anchored list like `[loop]` or `[item-list]`, or from the match count in a search list.

  If you skip items with [PREFIX-last] or [PREFIX-next], the count is NOT adjusted.

[PREFIX-last] CONDITION [/PREFIX-last]
  If CONDITION evaluates true (a non-whitespace value that is not specifically zero) then this will be the last item displayed.

[PREFIX-modifier attribute]
  If the item is a hash list (i.e. [item-list]), this will return the value of the `attribute`.

[PREFIX-next] CONDITION [/PREFIX-next]
  If CONDITION evaluates true (a non-whitespace value that is not specifically zero) then this item is skipped.

[PREFIX-param name]
[PREFIX-param N]
  Returns the array parameter associated with the looping tag row. Each looping list returns an array of `return fields`, set in searches with `mv_return_field` or `rf`. The default is only to return the code of the search result, but by setting those parameters you can return more than one item.

  In a [query ...] MML tag you can select multiple return fields with something like:

          [query prefix=prefix sql="select foo, bar from baz where foo=buz"]
              [prefix-code]  [prefix-param foo]  [prefix-param bar]
          [/query]

  In this case, [prefix-code] and [prefix-param foo] are synonymns, for `foo` is the first returned parameter and becomes the code for this row. Another synonym is [prefix-param 0]; and [prefix-param 1] is the same as [prefix-param bar].

[PREFIX-price]
  The price of the current code, formatted for currency. If MiniVend's pricing routines cannot determine the price (i.e. it is not a valid product or on-the-fly item) then zero is returned. If the list is a hash list, the price will be modified by its `quantity` or other applicable attributes (like `size` in the demo).

[PREFIX-quantity]
  The value of the `quantity` attribute in a hash list. Most commonly used to display the quantity of an item in a shopping cart [item-list].

[PREFIX-subtotal]
  The [PREFIX-quantity] times the [PREFIX-price]. This does take discounts into effect.

[if-PREFIX-data table field] IF text [else] ELSE text [/else] [/if-PREFIX-data]
  Examines the data field, i.e. [PREFIX-data table field], and if it is non-blank and non-zero then the `IF text` will be returned. If it is false, i.e. blank or zero, the `ELSE text` will be returned to the page.

  This is much more efficient than the otherwise equivalent `[if type=data term=table::field::[PREFIX-code]]`.

  You cannot place a condition; i.e. [if-PREFIX-data table field eq 'something']. Use `[if type=data ...]` for that.

  Careful, a space is not a false value!

[if-PREFIX-field field] IF text [else] ELSE text [/else] [/if-PREFIX-field]
  Same as [if-PREFIX-data ...] except uses the same data rules as `[PREFIX-field]`.

[modifier-name attribute]
  Outputs a variable name which will set an appropriate variable name for setting the attribute in a form (usually a shopping cart). Outputs for successive items in the list:

          1. attribute0
          2. attribute1
          3. attribute2

  etc.

[quantity-name]
  Outputs for successive items in the list:

          1. quantity0
          2. quantity1
          3. quantity2

  etc. `[modifier-name quantity]` would be the same as `[quantity-name]`.

### Index Up