Format Parameters In XenForo Options

TheBigK

Well-known member
My addon requires the option to be displayed in the following format :-

[...department name...] : [ ...email address.....] (+)

Clicking on + button at the end will duplicate these fields in the above mentioned format just below. I have therefore created a new Contact Group inside Options, and now creating a new option in it. I'm stuck with 'Edit Format' and 'Format Parameters'.

I'm guessing that in order to display the option fields like above, I will have to write HTML in a template and then fetch it. I think the way to do this is to select:

Edit Format: 'Named Template'
Default Value = 'The Template Name?' Or What?

I couldn't find relevant information about using 'Named Template' and 'PHP Callback'. Can someone tell me how do they work?
 
@katsulynx - I explored several templates and tried to figure a way to make my add-on work. My addon does this:

1. In AdminCP Options, adds a new option: Department Names and Email:
[Department Name ] [Department Email]
(Add New Department) ---> This repeats above fields, just like mentioned in your tutorial. But my add-on has two input fields instead of one as described in the tutorial.

Now, I'm really not sure how to make this work with controller. What variables should I define in my template? Basically, what really should my ControllerAdmin's $viewParams define?
 
Using two instead of one field is a bit tricky. You could work around by handling two options inside one template, but I'd rather store them into the same option, which requires a different workaround. I'm using the following template to handle an option-array with two fields:

HTML:
<xen:controlunit label="{$preparedOption.title}:">
    <ul id="{$preparedOption.title}Container" class="FieldChoices">
        <xen:foreach loop="$preparedOption.option_value" key="$key" value="$option">
        <xen:if is="{$option.name}">
            <li>
                <input type="text" name="{$fieldPrefix}[{$preparedOption.option_id}][{$key}][value]" value="{$option.name}" class="textCtrl" placeholder="{xen:phrase acp_tesbooksugestions_bookname}" size="25" />
                <input type="text" name="{$fieldPrefix}[{$preparedOption.option_id}][{$key}][text]" maxlength="25" value="{$option.alt}" class="textCtrl" placeholder="{xen:phrase acp_tesbooksugestions_bookalt}" size="25" />
            </li>
            <xen:set var="$cur_key">{$key}</xen:set>
        </xen:if>
        </xen:foreach>
        <li>
            <input type="text" name="{$fieldPrefix}[{$preparedOption.option_id}][{xen:calc '{$cur_key} + 1'}][value]" class="textCtrl" placeholder="{xen:phrase value}..." size="25" />
            <input type="text" name="{$fieldPrefix}[{$preparedOption.option_id}][{xen:calc '{$cur_key} + 1'}][text]" maxlength="25" class="textCtrl" placeholder="{xen:phrase text}..." size="25" />
        </li>
    </ul>
  
    <input type="button" value="{xen:phrase add_additional_choice}" id="{$preparedOption.title}Adder" class="button smallButton FieldAdder" data-source="ul.FieldChoices li" />
  
    <p class="explain" style="margin-top: 10px;">{xen:raw $preparedOption.explain}</p>
    {xen:raw $editLink}
</xen:controlunit>

<script>
$(document).ready(function() {
    $('#{$preparedOption.title}Adder').click(function() {
        $('#{$preparedOption.title}Container').children().last().children().each(function() {
            $(this).attr('name',$(this).attr('name').replace( /(\d+)/, function(){return arguments[1]*1+1}));
        });
    });
});
</script>

After that, {$xenOptions.yourOption} contains a multidimensional array of the form:
  1. -> Value, Text
  2. -> Value, Text
So every entry contains your desired values. The script at the end is the workaround to ensure everything is saved correctly, as HTML->PHP cannot handle the array-wildcard [] when fields follow. It essentialy just ensures the numeration of all fields is correct, so that all values are stored. There's no need to change the script even if you add more fields, just change the value in the last brackets (where there's now 'value' and 'text').

You can simply call it in your template by looping through {$xenOptions.yourOption}.
 
A callback would essentially just allow you to process your data before showing them in a named template. The problems from above would persist though.
 
A callback would essentially just allow you to process your data before showing them in a named template. The problems from above would persist though.
Thanks! I'm yet to dive into JS and now exploring the way XenForo does this. I checked the way they handle user fields and it looks straightforward. Let's see how it works out. Didn't expect to be complicated!
 
Using two instead of one field is a bit tricky. You could work around by handling two options inside one template, but I'd rather store them into the same option, which requires a different workaround. I'm using the following template to handle an option-array with two fields:

HTML:
...

After that, {$xenOptions.yourOption} contains a multidimensional array of the form:
  1. -> Value, Text
  2. -> Value, Text
So every entry contains your desired values. The script at the end is the workaround to ensure everything is saved correctly, as HTML->PHP cannot handle the array-wildcard [] when fields follow. It essentialy just ensures the numeration of all fields is correct, so that all values are stored. There's no need to change the script even if you add more fields, just change the value in the last brackets (where there's now 'value' and 'text').

You can simply call it in your template by looping through {$xenOptions.yourOption}.

@katsulynx I tried this example and the options don't seem to save. Can you tell me what I'm doing wrong? I copied the code directly.
 
Also, for debugging purposes, where do these values get saved in the database?

EDIT:

Values of options are saved (helpfully) in the database under the xf_options table. Their values are BLOBs, so MySQL Workbench (v5.2.x) won't show you their values, and you'll have to select against the table like so (replace YOUR_OPTION_ID with the named option ID you set in the Edit Option section:

Code:
SELECT *, SUBSTRING(option_value,1,2000)  FROM lsdemo.xf_option
WHERE option_id = 'YOUR_OPTION_ID'
;
 
Last edited:
Ok, after hours of frustration, I figured this out. @katsulynx, please correct me if I'm wrong, but I think your example has a few errors.

It was trying to set the value fields of the input elements to $option.name and $option.alt, when it should have set them to $option.text and $option.value!

Also, the <xen:if is="{option.name}"> line should have been <xen:if is="{option.text}"> (or .value)!

(Make sure you have an asterisk in the "Array Sub-Options" field, and you don't need anything in the Default field.)

Code:
<xen:controlunit label="{$preparedOption.title}:">
    <ul id="{$preparedOption.title}Container" class="FieldChoices">
        <xen:foreach loop="$preparedOption.option_value" key="$key" value="$option">
        <xen:if is="{$option.text}">
            <li>
                <input type="text" name="{$fieldPrefix}[{$preparedOption.option_id}][{$key}][value]" value="{$option.value}" class="textCtrl" placeholder="{xen:phrase value}" size="25" />
                <input type="text" name="{$fieldPrefix}[{$preparedOption.option_id}][{$key}][text]" maxlength="25" value="{$option.text}" class="textCtrl" placeholder="{xen:phrase text}" size="25" />
            </li>
            <xen:set var="$cur_key">{$key}</xen:set>
        </xen:if>
        </xen:foreach>
        <li>
            <input type="text" name="{$fieldPrefix}[{$preparedOption.option_id}][{xen:calc '{$cur_key} + 1'}][value]" class="textCtrl" placeholder="{xen:phrase value}..." size="25" />
            <input type="text" name="{$fieldPrefix}[{$preparedOption.option_id}][{xen:calc '{$cur_key} + 1'}][text]" maxlength="25" class="textCtrl" placeholder="{xen:phrase text}..." size="25" />
        </li>
    </ul>

    <input type="button" value="{xen:phrase add_additional_choice}" id="{$preparedOption.title}Adder" class="button smallButton FieldAdder" data-source="ul.FieldChoices li" />

    <p class="explain" style="margin-top: 10px;">{xen:raw $preparedOption.explain}</p>
    {xen:raw $editLink}
</xen:controlunit>

<script>
$(document).ready(function() {
    $('#{$preparedOption.title}Adder').click(function() {
        $('#{$preparedOption.title}Container').children().last().children().each(function() {
            $(this).attr('name',$(this).attr('name').replace( /(\d+)/, function(){return arguments[1]*1+1}));
        });
    });
});
</script>

I thought my code wasn't saving at first, but that was because it wasn't setting the value fields of the input elements to the proper $option value!

Also, it wasn't entering the for statement at all, due to it checking a variable that was never set!
 
Last edited:
Top Bottom