1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. This forum has been archived. New threads and replies may not be made. All add-ons/resources that are active should be migrated to the Resource Manager. See this thread for more information.

[GUIDE] Custom Pages with Navigation Tabs

Discussion in 'Development Tutorials [Archive]' started by Jaxel, Oct 7, 2010.

  1. Jaxel

    Jaxel Well-Known Member

    This guide will explain how to make custom pages for your mods. The first thing you need to do is create your mod with a unique addon ID, and then create a directory in the /library/ folder to follow that ID. The name of your addon ID should begin with a letter; I tried to begin with a number, but it created programs as PHP doesn't like classes that start with numbers. For this example, I am using an addon ID I created called "World"... this will be a Hello World mod!

    Once your mod is created, you will need to create a routing class. Based on the name of my mod, I created the class "World_Route_Prefix_Portal" at "/library/World/Route/Prefix/Portal.php".
    Code:
    <?php
    
    class World_Route_Prefix_Index implements XenForo_Route_Interface
    {
    	public function match($routePath, Zend_Controller_Request_Http $request, XenForo_Router $router)
    	{
    		return $router->getRouteMatch('World_ControllerPublic_Index', 'index', 'world', $routePath);
    	}
    }
    
    This one is simple, the class contains a function that matches the URL a user inputs and sends it to the appropriate location. This function assumes the user will be going to the /portal/ URL and it will forward the user to /portal/index. For getRouteMatch, we are passing 4 parameters:
    • World_ControllerPublic_Index - this is the function we will be sending the user to
    • index - you could put $routePath here, in order to have nested actionFunctions depending on if a user puts in /world/subdir or something along those lines. In this case, I am making it so that no matter what a user inputs, they will always be sent to /world/index.
    • portal - this is a variable defining what 'navigation tab' the user is on. Just like the index field, you can customize this, but then you will need to make a navigation tab for each and every portal page. This is what is called the "Major Section"
    • $routePath - this is what is called the "Minor Section". This field will store additional URL information beyond the /world/. So if a user goes to /world/edit, this field will contain "edit". You could use this information to redirect the user depending on whats in the Minor Section.
    The next thing you need to do is create the routing prefix in XenForo so that it knows the routing class we just created exists. You can do this at the "admin.php?route-prefixes/" link on your XF installation. Be warned that you must be in debug mode to create modifications through XenForo's control panel!
    • Route Prefix: world
    • Route Type: public
    • Route Class: World_Route_Prefix_Index
    Next we are going to create a navigation tab so that users cant click a link and head to /world/. The first thing we need to do is create the class which processes the navtab. Based on the name of my mod, I created the class "World_Listeners_Navigation" at "/library/World/Listeners/Navigation.php".
    Code:
    <?php
    
    class World_Listeners_Navigation
    {
    	public static function navtabs(array &$extraTabs, $selectedTabId)
    	{
    		$extraTabs['world'] = array(
    			'title' => 'Hello World',
    			'href' => 'world/',
    			'selected' => ($selectedTabId == 'world'),
    			'linksTemplate' => 'World_Navtabs',
    		);
    	}
    }
    This function creates the second row of links for when you click on the Hello World primary tab. The primary tab is generated in a Template called "World_Navtabs"... which must be created.
    Code:
    <ul class="secondaryContent blockLinksList">
    	<li><a href="{$xenOptions.boardUrl}/world/">Hello World</a></li>
    </ul>
    In order to continue, we need to use XenForo's hook system called "Code Listeners". You can create new Code Listeners at the "admin.php?code-event-listeners/" link on your XF installation.
    • Listen to Event: navigation_tabs
    • Execute Callback: World_Listeners_Navigation::navtabs
    Now we have a Routing Class, and a Navigation Tab Class... whats left? Well the actual page! We'll keep this next part simple. Based on the name of my mod, I created the class "World_ControllerPublic_Index" at "/library/World/ControllerPublic/Index.php".
    Code:
    <?php
    
    class World_ControllerPublic_Index extends XenForo_ControllerPublic_Abstract
    {
    	public function actionIndex()
    	{
    		$text = 'Hello World!';
    
    		$viewParams = array(
    			'text' => $text,
    		);
    
    		return $this->responseView('World_ViewPublic_Index', 'World_Index', $viewParams);
    	}
    }
    This one is simple, declare the action function for when someone goes to /world/index, store Hello World into a string, add the string to passable parameters, then call up the XenForo template generator called responseView. You'll notice a class called "World_ViewPublic_Index", thankfully you dont actually have to make this class, as it will be generated automatically. The second parameter however "World_Index" is referencing a template which must be created.
    Code:
    <xen:if hascontent="true">
    <div class="sectionMain">
    	<xen:contentcheck>
    		{xen:raw $text}
    	</xen:contentcheck>
    </div>
    </xen:if>
    Not so simple is it eh? I made this guide off the top of my head, so if anything is wrong, please tell me.

    Remember! I'm an unemployed programmer who enjoys donations!
     
  2. Floris

    Floris Guest

    This is excellent! Very nicely done :)
     
  3. Brogan

    Brogan XenForo Moderator Staff Member

    Can you post some screenshots?

    I'm very interested to see what can be done with Pages.
     
  4. Facepalmx2

    Facepalmx2 Active Member

    Code:
    	<li><a href="{$xenOptions.boardUrl}/world/">Hello World</a></li>
    
    This would best be replaced with:
    Code:
    	<li><a href="{xen:link world/}">Hello World</a></li>
    
    Besides that, good tutorial. Was about to make it myself, haha.

    One question:
    Here's my navtab template:
    Code:
    <ul class="secondaryContent blockLinksList">
    <li><a href="{xen:link ezirc/options/}">{xen:phrase ezirc_options}</a></li>
    </ul>
    The list / subnav options do not show up on the page itself, but does show on the dropdown from a different page. Any ideas?
     
    Dadparvar likes this.
  5. Jaxel

    Jaxel Well-Known Member

    Yes...
    Code:
    <?php
    
    class World_Route_Prefix_Index implements XenForo_Route_Interface
    {
    	public function match($routePath, Zend_Controller_Request_Http $request, XenForo_Router $router)
    	{
    		return $router->getRouteMatch('World_ControllerPublic_Index', 'index', 'world', $routePath);
    	}
    }
    Code:
    <?php
    
    class World_Listeners_Navigation
    {
    	public static function navtabs(array &$extraTabs, $selectedTabId)
    	{
    		$extraTabs['world'] = array(
    			'title' => 'Hello World',
    			'href' => 'world/',
    			'selected' => ($selectedTabId == 'world'),
    			'linksTemplate' => 'World_Navtabs',
    		);
    	}
    }
    There are three instances of 'world' in the code above. All 3 instances must match, otherwise your subnav will break.
     
    Facepalmx2 likes this.
  6. Facepalmx2

    Facepalmx2 Active Member

    My code is based along those lines, not exactly as my code did not come from this tutorial. Very similar though.
    So, you're saying the href array value must be the same as the identifier?


    Edit: That's odd, changing the identifiers to the original href value worked .. not sure why it's like that, but works for me. Thanks :)
     
  7. Kier

    Kier XenForo Developer Staff Member

    Almost there - you need to use the link builder in the PHP code as well as the templates, and it's good practice to use phrases:
    PHP:
    public static function navtabs(array &$extraTabs$selectedTabId)
    {
        
    $extraTabs['world'] = array(
            
    'title' => new XenForo_Phrase('hello_world'),
            
    'href' => XenForo_Link::buildPublicLink('full:world'),
            
    'selected' => ($selectedTabId == 'world'),
            
    'linksTemplate' => 'World_Navtabs',
        );
    }
     
    Dadparvar, alexp999, Fuhrmann and 3 others like this.
  8. Lynne

    Lynne Member

    Very helpful, thank you!
     
  9. dmnkhhn

    dmnkhhn Active Member

    $routePath - array or string?

    I am asking because if I have something like /world/edit/1 - how do get the '1'?
     
  10. siros

    siros Member

    Thank you for taking the time to write this :)
     
  11. ragtek

    ragtek Guest

    The tab highlight is not working for me:(

    router
    PHP:
    class Ragtek_Linklist_Route_Prefix_Index implements XenForo_Route_Interface
    {
        public function 
    match($routePathZend_Controller_Request_Http $requestXenForo_Router $router)
        {
                   
    $action $router->resolveActionWithIntegerParam($routePath$request'link_id');
            return 
    $router->getRouteMatch('Ragtek_Linklist_ControllerPublic_Index'$action'links');
        }
    }
    Navtab:
    PHP:
    class Ragtek_Linklist_StaticMethods
    {
        static public function 
    addTab(array &$extraTabs$selected)
        {
            
    $extraTabs[] =array(
                
    'title' => new XenForo_Phrase('ragtekLinklist'),
                
    'selected' => ($selected == 'links'),
                
    'href'   => XenForo_Link::buildPublicLink('links'),
            );
        }
    The tab is in the navbar and when i click on it, it loads the right controller, but it's not highlighted.
     
  12. Lawrence

    Lawrence Well-Known Member

    Try using 'selected' => ($selectedTabId == 'links'),

    Set the selected tab ID to match the name of the extra tab, ie:

    $extraTabs['my_cool_tab'] =array(
    'title' => new XenForo_Phrase('coolTab'),
    'selected' => ($selectedTabId == 'my_cool_tab'),
    'href' => XenForo_Link::buildPublicLink('coollinks'),
    );
     
  13. ragtek

    ragtek Guest

    thx

    $extraTabs['links'] =array(

    was missing but it still not works:(

    I've started debugging and here's the strange thing:
    PHP:
    XenForo_CodeEvent::fire('navigation_tabs', array(&$extraTabs$selectedTabId));



            if (!empty(
    $extraTabs[$selectedTabId]))
            {
                 
    Ragtek_Debug::show($extraTabs[$selectedTabId]);
                
    $selectedTab $extraTabs[$selectedTabId];
            }
    [/php]
    $xtraTabs[$selectedTabId] is a Array
    Code:
    Array
    (
        [title] => XenForo_Phrase Object
            (
                [_phraseName:protected] => ragtekLinklist
                [_params:protected] => Array
                    (
                    )
    
                [_insertParamsEscaped:protected] => 1
            )
    
        [selected] => 1
        [href] => links/
    )
    1
     
  14. ragtek

    ragtek Guest

    ok got it,

    it's not working without an linkstemplate
     
  15. Cory Booth

    Cory Booth Well-Known Member

    In the example above, it seems some of the code says "portal" while the instructions say "world" or visa versa...
    I think...
     
  16. Digital Doctor

    Digital Doctor Well-Known Member

    Can someone post code + screenshot.
    Newbs like me need to see things.
    :)
     
  17. Wuebit

    Wuebit Well-Known Member

    Hmm I can't get this part to work
    It will not use the template

    PHP:
    <?php

    class VKmanga_ControllerPublic_Index extends XenForo_ControllerPublic_Abstract
    {
        public function 
    actionIndex()
        {
            
    $text 'Hello World!';

            
    $viewParams = array(
                
    'text' => $text,
            );

            return 
    $this->responseView('VKmanga_ViewPublic_Index''VKmanga_Main'$viewParams);
        }
    }
    Has something changed? as this was posted last year.

    Thanks

    Edit = Np got it working :)
     
  18. sifuhall

    sifuhall Active Member

    Hmmmm....

    I get:

    A controller for the route path World/ was not found.

    What did I do wrong?
     
  19. Richey

    Richey Member

    Same problem here!
     
  20. Richey

    Richey Member

    Arrr problem found ;)

    @sifuhall: Maybe you did the same mistake like me. In Prefix/Portal.php the first line has to be:
    class Texturen_Route_Prefix_Portal, not Index!

    Cheers, now it works. Thank you for this tutorial.
     

Share This Page