问题
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.
回答1:
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
回答2:
You could use the staticpagepicker
widget if you don't need to link to CMS pages.
https://github.com/rainlab/pages-plugin#backend-forms
If you need to select from a list of static pages in your own backend forms, you can use the
staticpagepicker
widget:fields: field_name: label: Static Page type: staticpagepicker
The field's assigned value will be the static page's file name, which can be used to link to the page as described above.
In your layout file:
{variable name="button_page" label="Button URL" type="staticpagepicker"}{/variable}
<a href="{{ button_page | staticPage }}">Button</a>
Because CMS Pages aren't listed in this widget, you could always setup an alternative field to offer more flexibility to the user.
{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>
来源:https://stackoverflow.com/questions/47738734/static-page-dropdown-within-static-page-in-octobercms