Will give a full write up to this shortly. This is part of my learning curve and I am not a developer, just someone whom is learning fast and puts a problem and works out a solution.
Problem, is having an a dropdown in the backend blueprint of a page, which picks up data originally currently from the same page, to control the selection of input applied to a fieldset repetitively on the same blueprint.
This is still mark 1 of the solution so I am sure people can suggest ways to improve it.
I wanted to have a category section based on a main category and a sub category.
Created this with a list style blueprint
header.category:
type: section
title: Portfolio Category
underline: true
fields:
.arraylist:
name: Category
type: list
style: vertical
collapsed: true
label: Add Portfolio Category
fields:
.group:
type: text
label: Category
.item:
type: text
label: Sub Category
This would create the data in the frontmatter .md page
category:
arraylist:
-
group: Portfolio
item: Portfolio
-
group: Artwork
item: Branding
-
group: Marketing
item: Marketing
-
group: Development
item: 'App Design'
-
group: Development
item: 'Web Design'
I then wanted to be able to assign in each item of the list the friendly sub category text
item:
and then write the
group:
name to the page data of the group of items, and be able to select single or multiple groups to an item
portfolio:
item:
-
categories:
- portfolio
- marketing
title: null
image: null
-
categories:
- artwork
- development
title: null
image: null
-
So that is the outcome, here is how to complete it.
Step 1: Create the blueprint for the dropdown to appear
Step 2: Use the “select field” to create the dropdown, I have been advised that a ‘selectize’ field can be used, but I couldn’t get it to work.
Step 3: When the dropdown is selected, we need to create and call a function, to retrieve the page header info of page.header.category.arraylist and basically create a 'data-options: ’ in the blueprint to return and populate the field
header.portfolio.item:
name: Portfolio Items
type: list
style: vertical
label: Add Portfolio Category
fields:
.categories:
type: select
label: Categories
multiple: true
array: true
data-options@: '\Grav\Theme\YourThemeName::PortfolioCategoriesList'
validation:
type: commalist
options:
.title:
type: text
label: Title
.image:
type: filepicker
folder: '@self'
preview_images: true
label: Background Image
accept:
- .png
- .jpg
- .svg
data-options@: '\Grav\Theme\YourThemeName::PortfolioCategoriesList'
This is the crucial line which is going to call a php function, which has been added to the to the YourThemeName.php which is the root of your theme.
Step 4 Writing the PHP function
public static function PortfolioCategoriesList()
{
$pages = Grav::instance()['pages'];
$pages->enablePages();
$pagename ='/home/_portfolio';
$arr = Grav::instance()['pages']->find('/home/_portfolio')->header()->category['arraylist'];
$selectize_options = [];
foreach($arr as $array)
{
$group = strtolower($array['group']);
$item = $array['item'];
$selectize_options[$group] = $item;
}
return($selectize_options) ;
}
Overview of the code / function
$pages = Grav::instance()['pages'];
$pages->enablePages();
I need to access the page collection, in admin plugin this is turned off to help with speed so we need the above to enable access to the pages.collection and turn it on
$pagename ='/home/_portfolio';
The above lines sets a variable for the page where I know the category data lies, in this case it is a module ( _portfolio which is in the /home/ page)
I need to convert this to a function parameter at some stage, to make my code reuseable and pass the module / page name
$arr = Grav::instance()['pages']->find($pagename)->header()->category['arraylist'];
These next line is to get a (instance) chunk of page collection header data from the \home_portfolio page which is the arraylist which is under the category page.header root and return it to the $arr (array)
$selectize_options = [];
creates an array container which we be putting the results of the data and return to the blueprint select field
foreach($arr as $array) {
$group = strtolower($array['group']);
$item = $array['item'];
$selectize_options[$group] = $item;
}
Now we are going to create a loop to go through the page.header.catogeries.arraylist array where the associated array element of group and item (nested array) and the value which are associated to this blueprint fields
foreach($arr as $array) {
Create a loop which takes the indvidual page.header.catogeries.arraylist array (group and item) from $arr and puts it into a variable called $array
$group = strtolower($array['group']);
to create a standardised answer I am using strtolower, which will take the element and put it to lower case.
It uses a variable $group to store the data from in to the new storage array variable $array r
-
group: Portfolio
item: Portfolio
in this example the first sub array ( where the - defines it in the frontmatter .md and the group and item are the associated array key names
In this first sub array , it is ‘group:’ and the reply with be Portfolio value
$item = $array['item'];
This line is to get the ‘item:’ key value ( in this case again on the first item within page.header.catogeries.arraylist will be also the word ‘Portfolio’
On the 2nd loop of the items in the array the following
$group will = artwork and $item will = Branding
$selectize_options[$group] = $item;
This prepare the data structure of [ $group = $item ] which will create the [ portfolio => Portfolio, artwork => Branding … and so on as the loop continues ]
This will provide a select box, with a list of the $item as friendly input name, but will save the $group name in lowercase to the front matter
On the admin blueprint of the page it creates
the html output on the blueprint when no value has been selected produces
Portfolio
Branding
Marketing
Web Design
Hope this basic tutorial / solution can point people in the right direction , happy to receive comments and criticism of a better way or possible mistakes in my documenting my learning (sorry dyslexic) than will do my best to update this post.
This took me about a week to perfect, mainly due to the lack of correct terminology (array, nested array and associated arrays and the issues with selectize and select field)
But this has been an learning curve (many thanks to Ricardo on discord) and a lot of trying and reading.
Tags: Nested Array, Associated Array, Loop, Selectize, Select, Dropdown, blueprint, dynamic, filled, Array, Key Name
V2 is to make it more of a modular function which can have data passed to for where I want to have this ability to call the option from any blueprint and on any page, move the categories builder blueprint to the themes blueprint rather than on the page.
Also just notice one of the categories sub items is being sent through development => ‘App Design’ is missing,
All this is to create a isotope portfolio cards with selectable filter , so a portfolio item may belong to different multiple buttons /filter