XF 2.1 How can I reuse this code or use it for more than once for a free add-on I plan to release?

Brad Padgett

Well-known member
HTML:
       <a href="{{ link('misc/style', null, {'style_id': property('Dark_Switch'),'_xfRedirect': $xf.fullUri,'t': csrf_token()}) }}"><img src="{{ base_url('styles/default/BP/LightSwitch/bulb-off.png', true) }}"></a>
<a href="{{ link('misc/style', null, {'style_id': property('Light_Switch') ,'_xfRedirect': $xf.fullUri,'t': csrf_token()}) }}"><img src="{{ base_url('styles/default/BP/LightSwitch/bulb-on.png', true) }}"></a>

The code above. What it does is allow me to target specific styles in a light switch add-on (and style chooser) I have almost finished to release as a free add-on to the community. There is but one issue. I do not know how to reuse this code for 4 pairs of additional styles I want to hook up to the light switch.

If I copy the code and use again the light bulb shows 4 additional times. What's happening is it's taking the style property "Dark_Switch" and "Light_Switch" where a user would enter 2 separate style ids in style properties-> click save -> and then it would be hooked up. How can this work for more than 2 styles? Preferably a pair of 5.

My add-on is perfect for what a lot of people would like on their site. It's going to have several options. The style chooser appears right on the far right of the sub-nav. It's got up to 9 styles you can configure through style ids and the light switch also configurable in the nav bar. Style chooser part is finished and ready. My site has 5 light and 5 dark styles. For the light switch portion I cannot release it until I find out how to do 4 more.

I'm going to tag all the people who have helped me in the past. Anyone can help with the answer and If you do not know the answer then it's quite alright. I'm just anxious to finish it. I worked on it all day yesterday. @Chris D @DL6 @Sim @S Thomas @DragonByte Tech
 
Last edited:
Unfortunately @Matt C. I appreciate your help but finding trouble getting it to work considering it repeats the code. It works but displays the light bulb 5 times. I'm familiar with foreach and realize that's what it does. Does anyone have an example on how I could use this without the light bulb appearing more than once?

It's not like I'm not working my butt off before asking. I was working all day yesterday before I asked.
 
You'd need to use a conditional within the foreach to only show the light bulb during the iteration you want it to show in.


Do style property references support the "!" not operator?

{{ !property('myProperty') }} <xf:if is="!property('myProperty') }}"><xf:if>

or is it
{{ property('myProperty', false) }} <xf:if is="property('myProperty', false)"></xf:if>

An example is worth a thousand words. I'm aware of conditionals but I have tried many conditionals. Considering I don't know how to use the ! not operator with style properties it makes it far more difficult. Also if I was somehow able to use the foreach key variable within the conditional then this would work quite easily. I could simply say if it's not targeting the specific key then don't run. However the docs don't say much about using variables in conditionals?

I appreciate your response.
 
Perhaps you could post a screenshot of what you have now and point out what you'd like it to look like?

It's a bit difficult to understand what you are trying to achieve.

Okay this is my code. The entire thing works just that the light bulb displays 5 times. I am actually quite satisfied I was able to get it to work period with all 5 styles. That's quite a feat. Just have to get the light bulb to only display once. I appreciate your assistance, it's very much so valued.

HTML:
<xf:if is="property('LightSwitch_On') == 'Enabled'">

    <xf:if is="property('styleType') == 'light'">

        <xf:set var="$dark" value="{{ [ property('Dark_Switch'), property('Dark_Switch2'), property('Dark_Switch3'), property('Dark_Switch4'), property('Dark_Switch5')] }}" />
        
<xf:foreach loop="$dark" key="$key" value="$style" i="$i">
        
        <div style="float: left;">

            
    <a href="{{ link('misc/style', null, {'style_id': $style,'_xfRedirect': $xf.fullUri,'t': csrf_token()}) }}"><img src="{{ base_url('styles/default/BP/LightSwitch/bulb-off.png', true) }}" alt="turn the lights off"></a>
    </div>
        </xf:foreach>
    
    
    </xf:if>

    
    <xf:if is="property('styleType') == 'dark'">
                
        <xf:set var="$light" value="{{ [ property('Light_Switch'), property('Light_Switch2'), property('Light_Switch3'), property('Light_Switch4'), property('Light_Switch5')] }}" />
        
        <xf:foreach loop="$light" key="$key" value="$style" i="$i">
    <div style="float: left;">
        <a href="{{ link('misc/style', null, {'style_id': $style,'_xfRedirect': $xf.fullUri,'t': csrf_token()}) }}"><img src="{{ base_url('styles/default/BP/LightSwitch/bulb-on.png', true) }}" alt="turn the lights on"></a>
            </div>
        </xf:foreach>
    </xf:if>
    </xf:if>

Thank you. It works just got to find the right conditional. I have yet to figure that part out.
 
Just to keep out confusion I just wanted to add that this part is just saying if the style property is on:

<xf:if is="property('LightSwitch_On') == 'Enabled'">

This part is checking the light/dark style property to say if it's light or dark show the appropriate image.

<xf:if is="property('styleType') == 'light'"> <xf:if is="property('styleType') == 'dark'">

Just wanted to add that in to save confusion.
 
You have all of the HTML inside the loop, so it is repeated x times.

Consider moving the image specific HTML outside the loop as a separate div/float.
Or, as suggested, use code/a conditional statement to only show it once.
 
You have all of the HTML inside the loop, so it is repeated x times.

Consider moving the image specific HTML outside the loop as a separate div/float.
Or, as suggested, use code/a conditional statement to only show it once.

I tried moving the code outside the block. If the image wasn't attached to to the link functionality it would easily work as you stated.

A conditional seems to be the best way but I don't have an example on how to use custom variables in a conditional.

Going over the style property options I have an on/off switch, 5 light and 5 dark style areas to enter style IDs. Considering I'm using all 5 it wouldn't work correctly. I would more than likely need to use a conditional that was a variable inside the foreach tag. The variables in Xenforo template syntax page doesn't explain how I could approach this. If you can't help I understand just wanted to say that it's not properly documented what I'm trying to achieve as far as I am personally aware.

I thoroughly appreciate your response however.
 
I still don't know what you are trying to achieve - I asked for a screenshot showing what it looks like now and what you would like it to look like.
 
My dev forums are a mess. This is local host but as you can see there's a style chooser in the sub nav. This part is finished except I will have the words style chooser to the left of it for the finished product. All of the colors for the style preview boxes you can setup in style properties.

As you can see the light bulb appears 5 times. Each version goes to the dark style version for all 5 styles I setup with style IDs in style properties.

Given the code I gave you above with the foreach, I'd simply like to find the correct conditional to basically correspond the dark style based on the light style that I'm using. Right now, If I click the 3rd light bulb it goes to the red dark style. If I click the 5th it goes to the purple dark style and vice versa. The style IDs setup in style properties are basically an area to put in one light corresponding style ID and one dark corresponding style ID for reach style. There are up to 5 areas for each light and dark style IDs (totaling 10). I only want the light bulb to appear once and still go to the corresponding dark style based on the light style I'm using. The code above with the foreach should help you assist me if you have any idea. I appreciate the help.

196716
 
Last edited:
I still don't know what you are trying to achieve - I asked for a screenshot showing what it looks like now and what you would like it to look like.

Hey Sim I found this thread:


So what I'm trying to do is iterate the image one time but have the link the image is inside iterate all 5 times. Still working on it if you have any idea.
 
I assume that all the properties property('Light_Switch') hold the style_ids of the various matching styles?

So does that mean we can assume that (for example), the dark version style_id of property('Light_Switch') is property('Dark_Switch') and the light version style_id of property('Dark_Switch3') is property('Light_Switch3') etc?

If so, then we can probably just use an array to map one to the other without the need for a loop?

Then use the current visitor style_id from $xf.visitor.style_id to work out which is the corresponding opposite style to the one currently in use.

I have no idea if the following code will work - but it might point you in the right direction?

HTML:
<xf:if is="property('LightSwitch_On') == 'Enabled'">

    <xf:set var="$styleMap" value="{{ [
        property('Light_Switch') => property('Dark_Switch'),
        property('Light_Switch2') => property('Dark_Switch2'),
        property('Light_Switch3') => property('Dark_Switch3'),
        property('Light_Switch4') => property('Dark_Switch4'),
        property('Light_Switch5') => property('Dark_Switch5'),
        property('Dark_Switch') => property('Light_Switch'),
        property('Dark_Switch2') => property('Light_Switch2'),
        property('Dark_Switch3') => property('Light_Switch3'),
        property('Dark_Switch4') => property('Light_Switch4'),
        property('Dark_Switch5') => property('Light_Switch5'),
    ] }}" />
    
    <xf:set var="$onOff" value="property('styleType') == 'light' ? 'off' : 'on'">

    <xf:if is="array_key_exists($xf.visitor.style_id, $styleMap)">
        <div style="float: left;">
            <a href="{{ link('misc/style', null, {'style_id': $styleMap[$xf.visitor.style_id],'_xfRedirect': $xf.fullUri,'t': csrf_token()}) }}"><img src="{{ base_url('styles/default/BP/LightSwitch/bulb-' . $onOff . '.png', true) }}" alt="turn the lights {{ $onOff }}"></a>
        </div>
    </xf:if>
            
</xf:if>
 
I assume that all the properties property('Light_Switch') hold the style_ids of the various matching styles?

So does that mean we can assume that (for example), the dark version style_id of property('Light_Switch') is property('Dark_Switch') and the light version style_id of property('Dark_Switch3') is property('Light_Switch3') etc?

If so, then we can probably just use an array to map one to the other without the need for a loop?

Then use the current visitor style_id from $xf.visitor.style_id to work out which is the corresponding opposite style to the one currently in use.

I have no idea if the following code will work - but it might point you in the right direction?

HTML:
<xf:if is="property('LightSwitch_On') == 'Enabled'">

    <xf:set var="$styleMap" value="{{ [
        property('Light_Switch') => property('Dark_Switch'),
        property('Light_Switch2') => property('Dark_Switch2'),
        property('Light_Switch3') => property('Dark_Switch3'),
        property('Light_Switch4') => property('Dark_Switch4'),
        property('Light_Switch5') => property('Dark_Switch5'),
        property('Dark_Switch') => property('Light_Switch'),
        property('Dark_Switch2') => property('Light_Switch2'),
        property('Dark_Switch3') => property('Light_Switch3'),
        property('Dark_Switch4') => property('Light_Switch4'),
        property('Dark_Switch5') => property('Light_Switch5'),
    ] }}" />
   
    <xf:set var="$onOff" value="property('styleType') == 'light' ? 'off' : 'on'">

    <xf:if is="array_key_exists($xf.visitor.style_id, $styleMap)">
        <div style="float: left;">
            <a href="{{ link('misc/style', null, {'style_id': $styleMap[$xf.visitor.style_id],'_xfRedirect': $xf.fullUri,'t': csrf_token()}) }}"><img src="{{ base_url('styles/default/BP/LightSwitch/bulb-' . $onOff . '.png', true) }}" alt="turn the lights {{ $onOff }}"></a>
        </div>
    </xf:if>
           
</xf:if>

Thank you so much @Sim. You are correct in the fact that Light_Switch for example and Dark_Switch are corresponding style IDs as well as the other matching examples 2-5. This helps a lot. I'm not a complete noob so I will definitely be able to work with this example and see what I can use. It's just hard when you don't have examples. This seems to be what I need. I really appreciate your help. Regardless of the final result I can definitely work with this. Sometimes it's good to just have code you can work with. You helped me a lot. Your a really nice guy and I appreciate the help
 
@Sim I had to take it back to square one because your code kept giving me syntax errors. No matter how many times I rearranged it and tried to find out where the error was coming from it didn't work. This is what I got now. The areas 'style_id': $dark and 'style_id': $light inside the URL are the ones I need help with. Also $variable[$xf.visitor.style_id] does not work inside 'style_id'. I just need to find a way I can target all 5 possibilities in each array set. I also don't know if array keys are even valid xenforo syntax as that was where one of the errors were coming from.

HTML:
<xf:if is="property('LightSwitch_On') == 'Enabled'">

    <xf:set var="$dark" value="{{ [ property('Dark_Switch'), property('Dark_Switch2'), property('Dark_Switch3'),  property('Dark_Switch4'), property('Dark_Switch5')] }}" />

        <xf:if is="property('styleType') == 'light'">
<div style="float: left;">
           <a href="{{ link('misc/style', null, {'style_id': $dark,'_xfRedirect': $xf.fullUri,'t': csrf_token()}) }}">
                <img src="{{ base_url('styles/default/BP/LightSwitch/bulb-off.png', true) }}" alt="turn the lights off">
            </a>
        </div>
                                                                                                                   
</xf:if>

    <xf:set var="$light" value="{{ [ property('Light_Switch'), property('Light_Switch2'), property('Light_Switch3'),  property('Light_Switch4'), property('Light_Switch5')] }}" />

<xf:if is="property('styleType') == 'dark'">
<div style="float: left;">
           <a href="{{ link('misc/style', null, {'style_id': $light, '_xfRedirect': $xf.fullUri,'t': csrf_token()}) }}">
                <img src="{{ base_url('styles/default/BP/LightSwitch/bulb-on.png', true) }}" alt="turn the lights on">
            </a>
        </div>
                                                                                                                   
</xf:if>


</xf:if>

If I could simply take the those areas and have something I could put there to get the array of the variable $light and $dark and return any possibility. At least when I was using foreach it worked but repeated the image 5 times. I'm close just haven't got it yet.
 
Doesn't look like array_key_exists is in the list of allowed functions (see XF\Template\Templater - the list of default functions shows you what you can use in templates).

However, in_array is, as is array_keys, so you could change my code to use:
HTML:
<xf:if is="in_array($xf.visitor.style_id, array_keys($styleMap))">
    ...
</xf:if>

I think you may have some more fundamental issues though - why are there 5 switches? What if the user doesn't have 5 styles defined?
 
Doesn't look like array_key_exists is in the list of allowed functions (see XF\Template\Templater - the list of default functions shows you what you can use in templates).

However, in_array is, as is array_keys, so you could change my code to use:
HTML:
<xf:if is="in_array($xf.visitor.style_id, array_keys($styleMap))">
    ...
</xf:if>

I think you may have some more fundamental issues though - why are there 5 switches? What if the user doesn't have 5 styles defined?

Thanks I'll play around with the code and see what I can do. There are 5 switches because my site has 5 light and 5 dark styles and I'd like to have the light styles on the chooser and then in correspondence to what style they're viewing they can switch to the dark style with the light bulb. Also I have instructions in the style properties to leave blank the styles you don't want to set up so if the user leaves the box blank then only the style IDs they put in will matter.

So you can basically set up a maximum of 5 corresponding styles but it is not required, only the IDs you put in will matter. The style chooser has a maximum of 9 styles you can set up and it's the same concept with that. I will play with the code using your above method and update you sometime tonight. Thanks for the help.
 
Top Bottom