XF 2.2 Adding option (select menu)

Anatoliy

Well-known member
It was easy to add an option group and to add an option (positive integer). But I need to add a select option menu, there is nothing about it in the "Let's build an addon", and I'm stuck. Please advise how to do it. What is the format for Format parameters? Can't figure it out.
 
Rule of Thumb: If you can't figure out how to do smth. take a look at how XenForo or official Add-ons are doing it.

Code:
value1={{ phrase('av_ttm_phrase_title1') }}
value2={{ phrase('av_ttm_phrase_title2') }}

Besides that I probably would"t make this an option but offer various sort possibillities via a filter menu.
 
Last edited:
Besides that I probably would"t make this an option but offer various sort possibillities via a filter menu.
I spent all day trying to figure that out, failed and decided to try another way.
Give me a minute I'll show where I stuck.
 
xfRequest, Uri, token, jason... 404. who are all those guys? 🤕

1.webp

Code:
<xf:css>
.block-container{
    padding:10px 20px;
    margin-top: 2px;
    }
.margin0 {margin:0;}
.gray{color:#8c8c8c;}
</xf:css>

<xf:title>Threads with too short titles</xf:title>
    <span>Found <b>{{$tooShortTotal}}</b> threads with too short titles.</span>
<br /><br />

<div class="block">
    <div class="block-header">

            <div class="filterBar">
            <a class="filterBar-menuTrigger" data-xf-click="menu" role="button" tabindex="0" aria-expanded="false" aria-haspopup="true">Sort by:</a>
            <div class="menu menu--wide" data-menu="menu" aria-hidden="true" data-href="av-ttm/shorts/" data-load-target=".js-filterMenuBody">
                <div class="menu-content">

                    <div class="js-filterMenuBody">
                        <form action="av-ttm/shorts/" method="get" class="">

                                <div class="menu-row menu-row--separated">
                                    <div class="inputGroup u-inputSpacer">
            
                                        <select name="order" class="input">
                                            <option value="title_length" selected="selected">Title length</option>
                                            <option value="thread_id">Thread ID</option>
                                            <option value="reply_count">Reply count</option>
                                            <option value="view_count">View count</option>
                                            <option value="creation_date">Creation date</option>
                                        </select>
        
                                        <span class="inputGroup-splitter"></span>

                                        <select name="direction" class="input">
                                            <option value="asc" selected="selected">Ascending</option>
                                            <option value="desc">Descending</option>
                                        </select>
        
        </div>
    </div>

    <div class="menu-footer">
        <span class="menu-footer-controls">
            <button type="submit" class="button--primary button"><span class="button-text">Sort</span></button>
        </span>
    </div>
    <input type="hidden" name="apply" value="1">
                
            </form>
                    </div>
                </div>
            </div>
        </div>
    </div>

    
        <div class="block-body">
            <br />
            <xf:pagenav page="{$page}" perpage="{$perPage}" total="{$tooShortTotal}" link="av-ttm/shorts/" wrapperclass="block" />
            <xf:foreach loop="$data" value="$short">
                <div class="block-container">               
                    <h3 class="margin0">
                        <a href="{{ link_type('public', 'threads', $short) }}" target="new">{$short.title}</a>
                    </h3>
                    <span class="gray">id:</span> {{$short.thread_id}}, <span class="gray">replies:</span> {{$short.reply_count}},  <span class="gray">views:</span> {{$short.view_count}}, <xf:date time="{$short.post_date}" /> - <xf:date time="{$short.last_post_date}" />
                </div>
            </xf:foreach>
</div>
<br />
<xf:pagenav page="{$page}" perpage="{$perPage}" total="{$tooShortTotal}" link="av-ttm/shorts/" wrapperclass="block" />
 
Code:
<xf:css>
.block-container{
    padding:10px 20px;
    margin-top: 2px;
    }
.margin0 {margin:0;}
.gray{color:#8c8c8c;}
</xf:css>
Don't do that, CSS should be in CSS/LESS templates.

Code:
<xf:title>Threads with too short titles</xf:title>
Don't do that, texts should uses phrases.

Code:
    <span>Found <b>{{$tooShortTotal}}</b> threads with too short titles.</span>
Again, use phrases - and it is not necessary to use double curly braces just for variables.

Code:
 <form action="av-ttm/shorts/" method="get" class="">
Entirely wrong ;)

This should be at least
Code:
<xf:form action="{{ link('av-ttm/shorts')}} " class="">
(with corresponding closing tag of course)

As said before, just take a look at how XenForo does things,
 
Last edited:
Don't do that, CSS should be in CSS/LESS templates.
They teach it as alternative method in "Let's build an add-on". With <xf:css src="mycss_file.css" /> I didn't understand. Do I create a css template with xF? Do I create a file with VSCode? What folder to place? What would be a path?
Not clear explanation.

Don't do that, texts should uses phrases.
I didn't learn that phrases thingy yet. I'll finish with functionality first, then will fix those little things.
Entirely wrong ;)

This should be at least
Code:
<xf:form action="{{ link('av-ttm/shorts')}} " class="">
(with corresponding closing tag of course)

Cool! Thanks! So how do I grab variables from a controller if method=post?
 
your controller should have an edit function to show the form (perhaps this is your main view) and a process function to actually do the saving of the data from the form.

use the input filter to grab form data:

Code:
protected function mythingEditProcess(\Namespace\product\Entity\yourEntity $yourEntityvar)
	{
		$form = $this->formAction();

		$input = $this->filter([
			'id' => 'int',
			'foo' => 'str', 
                        'bar' => 'str',
			
		]);
		
		$visitor = \XF::visitor();
		$input['create_user_id'] = $visitor->user_id;
		$input['create_date'] = time();

		$form->basicEntitySave($yourEntityvar, $input);

		return $form;
	}
 
your controller should have an edit function to show the form (perhaps this is your main view) and a process function to actually do the saving of the data from the form.

use the input filter to grab form data:

Code:
protected function mythingEditProcess(\Namespace\product\Entity\yourEntity $yourEntityvar)
    {
        $form = $this->formAction();

        $input = $this->filter([
            'id' => 'int',
            'foo' => 'str',
                        'bar' => 'str',
           
        ]);
       
        $visitor = \XF::visitor();
        $input['create_user_id'] = $visitor->user_id;
        $input['create_date'] = time();

        $form->basicEntitySave($yourEntityvar, $input);

        return $form;
    }
Thanks! But I guess it's not exactly what I'm looking for. I'm not going to get & save data.
My controller passes $items to a template. And a template has a form. I used the xF Filter By form, dropped everything except 2 dropdowns "order" (id, views, posts etc) & "direction" (asc, desc). My plan is to pass from a template to a controller my choice of "order by" and a controller will return $items ordered accordingly.
 
ok, then yeah, ignore that post above :D

in your actionIndex, look for post and handle it by setting a cookie and then redirect back to the index to act on it

Code:
 if ($this->isPost())
           if ($input['order_field'])
               {
                    $this->app()->response()->setCookie('yourprefix_order_field', $input['order_field']);
               }

               if ($input['order_direction'])
               {
                    $this->app()->response()->setCookie('yourprefix_order_direction', $input['order_direction']);
               }

               return $this->redirect($this->buildLink('your/url'));
          }
}

and outside that loop, act on the cookie and those ordering fields.


Code:
          $orderField = $input['order_field'] ?: $this->app()->request()->getCookie('yourprefix_order_field', 'name');
          $orderDir   = $input['order_direction'] ?: $this->app()->request()->getCookie('yourprefix_order_direction', 'ASC');


// then run your finder with

                ->order($orderField, $orderDir)
               ->limitByPage($page, $perPage);
 
Top Bottom