Search code examples
octobercms

Static page dropdown within static page in OctoberCMS


I have a template with a slideshow in it. Each slide consists of:

  • Image
  • Caption
  • A paragraph of text
  • Button

For the first 3 items, I have set up the following in my template:

{repeater name="slideshow" prompt="Add another slide" tab="Slideshow"}
  {variable name="image" label="Image" type="mediafinder" mode="image"}{/variable}
  {variable name="caption" type="text" label="Caption"}Caption{/variable}
  {variable name="body" type="textarea" label="Body"}Body{/variable}
{/repeater}

However, I'm a little stuck about what field type to use for the button, which needs to link to a static page within the site.

I don't want to use a text box where the user can enter a URL as it will be too difficult for the user to understand. I'd rather have a dropdown menu that works in the same way as the static menu plugin (ie: select "Static Page" from "type" and then get a list of static pages in a 2nd dropdown menu) but it doesn't see obvious how to do this.


Solution

  • Yes you can add drop-down there with list of static pages.

    to show list of pages in drop-down you need to extend pages and add dynamic method to it so when repeater add drop down it will get its values/options from that method.

    You need to add code to boot method inside any of your plugin, it will extend pages class which can further handle ajax request.

        \RainLab\Pages\Classes\Page::extend(function($model) {
            $model->addDynamicMethod('getPageOptions', function() {
                $theme = \Cms\Classes\Theme::getEditTheme();
                $pageList = new \RainLab\Pages\Classes\PageList($theme);
                $pages = [];
                foreach ($pageList->listPages() as $name => $pageObject) {
                    $pages[$pageObject->url] = $pageObject->title . ' (' . $pageObject->url . ')';
                }
                return $pages;
            });
        });
    

    and inside your repeater you can add dropdown

        {repeater name="slideshow" prompt="Add another slide" tab="Slideshow"}
          {variable name="image" label="Image" type="mediafinder" mode="image"}{/variable}
          {variable name="caption" type="text" label="Caption"}Caption{/variable}
          {variable name="body" type="textarea" label="Body"}Body{/variable}
          {variable name="page" type="dropdown" label="Page"}{/variable}
        {/repeater}
    

    so you can see we added dynamic method getPageOptions it consist of three part 1: get 2nd: fieldname 3rd: Options

    So our method name will be get + Page + Options => getPageOptions

    within that page we are returning array as value => Label pair you can customize there as per your need.

    so when drop-down created it will search this method and use its return value as option.

    if you find any further difficulties please comment.

    Update

    ok so now we can finally add conditional drop-downs its not ajax updatable so far but yes we can hide and show it based on condition.

    you can add this mark-up in layout.

        {repeater name="slideshow" prompt="Add another slide" tab="Slideshow"}
          {variable name="type" type="dropdown" label="Link Type"}{/variable}
          {variable name="cms-page" type="dropdown" label="Cms Page" trigger="action:show|field:type|condition:value[cms-page]" }{/variable}
          {variable name="static-page" type="dropdown" label="Static Page" trigger="action:show|field:type|condition:value[static-page]"}{/variable}
          {variable name="blog-post" type="dropdown" label="Post" trigger="action:show|field:type|condition:value[blog-post]"}{/variable}
        {/repeater}
    

    then inside plugin you need to add some additional methods.

    your boot method of plugin.php look like this

    public function boot()
    {
    
        $pluginSelf = $this;
        \RainLab\Pages\Classes\Page::extend(function($model) {
                $model->addDynamicMethod('getTypeOptions', function() {
    
                return [
                    '' => 'Select Type',
                    'cms-page' => 'CMS page',
                    'static-page' => 'Static Page',
                    'blog-post' => 'Blog post'
                ];
    
            });
        });
    
        \RainLab\Pages\Classes\Page::extend(function($model) use ($pluginSelf) {
            $model->addDynamicMethod('getStaticPageOptions', function() use ($pluginSelf) {
                $result =  $pluginSelf::getTypeInfo('static-page');
                return $result['references'];
            });
        });
    
        \RainLab\Pages\Classes\Page::extend(function($model) use ($pluginSelf) {
            $model->addDynamicMethod('getCmsPageOptions', function() use ($pluginSelf) {
                $result =  $pluginSelf::getTypeInfo('cms-page');
                return $result['references'];
            });
        });
    
        \RainLab\Pages\Classes\Page::extend(function($model) use ($pluginSelf) {
            $model->addDynamicMethod('getBlogPostOptions', function() use ($pluginSelf) {
                $result = $pluginSelf::getTypeInfo('blog-post'); 
                return $result['references'];
            });
        });
    
    }
    

    and one additional method you need to add inside plugin.php

    public static function getTypeInfo($type)
    {
        $result = [];
        $apiResult = \Event::fire('pages.menuitem.getTypeInfo', [$type]);
    
        if (is_array($apiResult)) {
            foreach ($apiResult as $typeInfo) {
                if (!is_array($typeInfo)) {
                    continue;
                }
    
                foreach ($typeInfo as $name => $value) {
                    if ($name == 'cmsPages') {
                        $cmsPages = [];
    
                        foreach ($value as $page) {
                            $baseName = $page->getBaseFileName();
                            $pos = strrpos($baseName, '/');
    
                            $dir = $pos !== false ? substr($baseName, 0, $pos).' / ' : null;
                            $cmsPages[$baseName] = strlen($page->title)
                                ? $dir.$page->title
                                : $baseName;
                        }
    
                        $value = $cmsPages;
                    }
    
                    $result[$name] = $value;
                }
            }
        }
    
        return $result;
    }
    

    as a result you can see in first drop down we can have options 'cms-page' , 'static-page' and 'Blog post', based on that we can show other drop downs.

    and during showing or using results first you need to check value of type field based on that fields value you can further choose which dropdown's value you need to use for example type=cms-page then you need to look for cms-page field.

    notice : not sure used - (dash) in variables so if value is not in out put you can convert variables in cmsPage camel case if needed not sure about this stuff

    one additional changes you need to add this change as its require to change core file , I also created pull request for it so they also include that change in next release mean while we need to do it manually. its required for this to work
    please refer this PR request : https://github.com/octobercms/library/pull/292/files