【问题标题】:Static page dropdown within static page in OctoberCMSOctoberCMS静态页面中的静态页面下拉列表
【发布时间】:2018-05-24 03:19:11
【问题描述】:

我有一个带有幻灯片的模板。每张幻灯片包括:

  • 图片
  • 标题
  • 一段文字
  • 按钮

对于前 3 项,我在模板中设置了以下内容:

{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}

但是,我对按钮使用什么字段类型有点困惑,它需要链接到站点内的静态页面。

我不想使用用户可以在其中输入 URL 的文本框,因为用户难以理解。我宁愿有一个下拉菜单,其工作方式与静态菜单插件相同(即:从“类型”中选择“静态页面”,然后在第二个下拉菜单中获取静态页面列表)但它没有看看如何做到这一点。

【问题讨论】:

    标签: octobercms


    【解决方案1】:

    是的,您可以在那里添加带有静态页面列表的下拉列表。

    要在下拉列表中显示页面列表,您需要扩展页面并向其添加动态方法,因此当转发器添加下拉列表时,它将从该方法获取其值/选项。

    您需要在任何插件内的boot方法中添加代码,它将扩展可以进一步处理ajax请求的页面类。

        \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;
            });
        });
    

    您可以在中继器中添加下拉菜单

        {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}
    

    所以你可以看到我们添加了动态方法 getPageOptions 它包括三个部分 1:get 第二部分:fieldname 第三部分:选项

    所以我们的方法名称将是 get + Page + Options => getPageOptions

    在该页面中,我们将数组作为值返回 => 您可以根据需要在其中自定义标签对。

    所以当下拉菜单创建时它会搜索这个方法并使用它的返回值作为选项。

    如果您发现任何进一步的困难,请发表评论。

    更新

    好的,现在我们终于可以添加条件下拉菜单了 到目前为止它不是 ajax 可更新的,但是我们可以根据条件隐藏和显示它。

    您可以在布局中添加此标记。

        {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}
    

    那么在插件内部你需要添加一些额外的方法。

    您的 plugin.php 的启动方法如下所示

    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'];
            });
        });
    
    }
    

    一个额外的方法你需要添加到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;
    }
    

    因此,您可以在第一个下拉菜单中看到我们可以有“cms-page”、“static-page”和“Blog post”选项,基于此我们可以显示其他下拉菜单。

    在显示或使用结果期间,您首先需要根据该字段值检查 type 字段的值,您可以进一步选择需要使用的下拉列表值,例如 type=cms- page 那么你需要寻找 cms-page 字段。

    注意:不确定是否在变量中使用 -(破折号),因此如果没有输出值,如果需要不确定这些东西,您可以转换 cmsPage 骆驼大小写的变量

    您需要添加此更改作为更改核心文件的要求的其他更改,我还为它创建了拉取请求,因此它们还包括下一个版本中的更改,这意味着我们需要手动执行此操作。 它需要才能工作
    请参考此 PR 请求:https://github.com/octobercms/library/pull/292/files

    【讨论】:

    • 非常感谢您提供超详细的答案以及对方法名称为何如此重要的解释。我已将您的答案标记为正确,因为它符合我的要求,但我也想知道是否有办法实现静态菜单插件的“类型/引用”样式,用户可以选择 URL、标题、 CMS 页面、博客文章或静态页面,然后在第二个下拉列表中填充与第一个下拉列表中的选择相关的列表?
    • 澄清一下,我了解如何扩展 pages 类以检索博客文章的选项,但我不确定如何重新创建静态菜单组件提供的动态双下拉功能。
    • 嘿,是的,我需要检查一下,可能是这样,让我做那些事情,我会告诉你,它就像依赖下拉列表一样吗?
    • 嘿,为您的下拉菜单添加了一些解决方案,可能对您有用,请查看 :)
    • 谢谢你,看来你完全明白我想要做什么了。但是,当我尝试实现此功能时出现错误:Undefined variable: references on line 169 of /path/to/project/modules/cms/classes/Page.php on build 430。
    【解决方案2】:

    如果您不需要链接到 CMS 页面,可以使用 staticpagepicker 小部件。 https://github.com/rainlab/pages-plugin#backend-forms

    如果您需要从自己的后端表单中的静态页面列表中进行选择,可以使用staticpagepicker 小部件:

    fields:
        field_name:
            label: Static Page
            type: staticpagepicker
    

    该字段的分配值将是静态页面的文件名,可用于链接到上述页面。

    在您的布局文件中:

    {variable name="button_page" label="Button URL" type="staticpagepicker"}{/variable}
    
    <a href="{{ button_page | staticPage }}">Button</a>
    

    由于 CMS 页面未在此小部件中列出,您始终可以设置一个替代字段,为用户提供更大的灵活性。

    {variable name="button_url" label="Button (URL)" type="text" span="left" comment="Leave empty if using Button (Page) instead" placeholder="http://"}{/variable}
    {variable name="button_page" label="Button (Page)" type="staticpagepicker" span="right" comment="Used if Button (URL) is left empty"}{/variable}
    
    <a href="{{ button_url ? button_url : (button_page | staticPage) }}">Button</a>
    

    【讨论】:

    • 谢谢你!这在我的项目中非常有用。有什么办法可以过滤掉特定页面,让staticpagepicker中只出现特定页面的子页面?
    • 遗憾的是没有过滤功能,您必须扩展 staticpagepicker 表单小部件才能过滤结果。
    • 感谢 Jeremy,我已经创建了一个自定义解决方案,我正在完善该解决方案。如果您有兴趣,可以在这里分享您的观点:github.com/rainlab/pages-plugin/issues/376
    【解决方案3】:

    我有和 Panagiotis Koursaris 一样的问题。我使用了没有中继器的模板变量。我通过指定选项并在插件启动方法中添加别名来解决问题。 例如:

    {variable name="type" type="dropdown" options="StaticPage | getTypeOptions" label="Link Type" tab="Text Image Header (dark)"}{/variable}
    
    \Illuminate\Foundation\AliasLoader::getInstance()->alias('StaticPage','RainLab\\Pages\\Classes\\Page');
    

    但是触发器不起作用,所有下拉菜单都显示出来了。 有什么办法解决吗?

    接下来的问题是,所有cms页面显示如下:

    项目[项目]

    我将第二个循环中的代码改成如下:

    if ($type == 'cms-page') {
                $cmsPages = [];
    
                if (!is_array($value)) {
                  continue;
                }
    
                foreach ($value as $url => $pageArray) {
                  $page = \Cms\Classes\Page::find($url);
                  if ($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;
              }
    

    【讨论】:

    • 如果您有新问题,请点击按钮提出。如果有助于提供上下文,请包含指向此问题的链接。
    猜你喜欢
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    • 2016-11-16
    相关资源
    最近更新 更多