Open mciszczon opened 6 years ago
Just realized, that @texnixe has already created a Kirby Structure ID plugin that automatically adds unique hash to structure items. This plugin could be used as a dependency.
Still wondering on how I can pass structurepage
and structurefield
values to the template engine. Probably Kirby Architect plugin will do. Will look into this today or tommorow.
@mciszczon did you find a way to implement it yet?
@EdwardLecock Yes, I have implemented it using Select A Structure, Kirby Architect and another plugin for generating unique IDs for structure entries. I will come back here later today with the details.
Ok, so I pushed my changes to my fork: mciszczon/select-a-structure. In order to make it work you'll need some other plugins, but let's start with my fork:
Notable changes that I've made:
yourfield:
optionid: hash_id
optionkey: staffname, staffsurname
optiondivider: ','
optionid
is a field inside the structure that you are targeting. It must contain unique value for each structure entry! This value could be entered manually, or using a plugin. I have used texnixe/kirby-structure-id for this.
optionkey
should contain name or names of the target structure fields. Let's say you have a structure consisting of staffname
, staffsurname
and staffposition
. By using optionkey
s as in the above example, the <select>
options will consist of these two first parameters. You can use as many keys as you wish.
optiondivider
is just for them looks, so you can specify how these keys should be separated. In our example it would be better to change it to ' '
(simply a space) to display names as John Doe
and not John, Doe
.
That would do for the back-end part!
We now need a way to use these values in our templates. Remember that this modified Select A Structure plugin only stores these unique IDs of elements that physically are on a different page. That's where Kirby Architect plugin comes in handy! It allows us to access blueprint data in the template, so we can easily grab the target page and field, and from them we can get our structure entries.
Firstly, you'll need to add these custom page methods: https://gist.github.com/mciszczon/93e4dd9edd58eb8844da53f6be42121c. You can simply save this file to yourkiby/site/plugins/page-methods.php
.
The above file will give you two new page methods: structurepage()
and idfield()
. These are just shortcuts, under the hood they use Kirby Architect to get this data.
Let's say we want to display our staff list (from the example above). Let staffselect
be our dynamic select a structure field, while the staff is stored on a page staff
inside stafflist
structure.
staff
page could look like this:
title: Staff
fields:
...
stafflist:
label: Staff
type: structure
fields:
hash_id: Unique ID
type: text
placeholder: Please, enter a unique value here!
staffname: Name
...
staffsurname: Surname
...
staffposition: Position
...
Notice the hash_id field! In this example it must be filled manually, but it's easy to use Kirby Structure ID for this matter.
And now let's say we want to display it on About us page. That's how about.yml
blueprint should look like:
title: About
fields:
...
staffselect:
structurepage: staff
structurefield: stafflist
optionid: hash_id
optionkey: staffname, staffsurname
optiondivider: ' '
And now, inside about.php
template/snippet just do this:
<?php
# Automatically get the staff page from blueprint
$staffPage = $page->structurepage('staffselect');
# Now get the name of the field that stores unique ids
$idField = $page->idfield('staffselect');
# With these two we can dynamically fetch from the target page!
# page($staffpage) should return `staff` page.
# findBy($idField, $page->staffselect()->value() will grab entry which unique id matches the unique id from select-a-structure select box.
$position = page($staffPage)->stafflist()->toStructure()->findBy($idField, $page->staffselect()->value());
echo $position;
?>
Select A Structure field inside a structure.
There's also one additional use case. In my project I have few select-a-structure fields that themselves are inside a structure. In such case, you must use $page->structurepage()
and $page->idfield()
differently:
$structurePage = $page->structurepage('parent_structure', true, 'select_a_structure_field');
$idField = $page->idfield('parent_structure', true, 'select_a_structure_field');
So, as you can see, both of these methods accept three parameters. First one is the parent structure, the one which contains select a structure field. Next there is true
keyword to indicate that our target field is nested inside this parent structure. Third argument is the name of the select-a-structure
field (like stafflist
).
I know this needs refactoring and could be extended massively. One thing is that manually grabbing the right field (e.g. ->stafflist()
) in the template is unnecessary, as we already store this information in the blueprint. It's just a matter of adding another custom page method. Should be easy.
I lack the time to do this right now, unfortunately. The plugin is working as-is however, so feel free to adapt this and maybe make it better!
If you have any other questions, feel free to ask me!
Thanks for the great write up. I'll take a look at your fork later on and give it a try.
The problem
Currently, the plugin loads the defined value(s) from the structure, and stores them as static text with just the fields defined in the blueprint.
It would be much more handier if the defined optionkeys were there only to make
<select>
options easier to read, but under the hood, the plugin would fetch the results dynamically with all the fields of the desired structure.Use case: Footnotes & bibliography
I am currently working on an academical project. I have a
bibliography
page with all the entries stored in a structure field. It's rather extensive, as you can see below:Then, in different parts of my website, I have content that requires to have the source written down beneath. Every source I use must go to bibliography too, so it seems logical to make
source
a select field with all the entries from the bibliography.For that purpose I wanted to use this plugin. First issue I encountered was the inability to use multiple
optionkey
values, which I have fixed. This is not enough in my case, though, I want not only few fields in my source, but the entire bibliography entry.It's not a good solution to enter all the fields into the
optionkey
, as it would render<select>
unreadable and be basically hard-coded. Any future changes in the bibliography structure and it might get broken.Idea
I have come up with an idea how to fix that. There could be another
dynamic
option in the blueprint for thetype: selectastructure
field:It would default to
false
to keep this backward-compatible. Then it would work just as now.With the dynamic option however, the plugin would rather fetch a
unique ID
of each structure entry, and store this dynamic link instead of the value.Then in the template, Kirby could dynamically load a structure directly from the page. Since we already store information about what page it is and how the field is named, it would work like that:
To get just one structure entry, we have the powerful
get()
method:Caveat
One and only caveat I can see, is that there would have to be something like
uniqueid
field in the structure, and its value would have to be unique per structure. This could be solved either by the user:Or, alternatively, it could be handled by this very plugin, with the introduction of a new custom field type, e.g.:
This would get filled automatically for the user.
UUID
would be my option-of-choice in implementing that.Summary
I will probably try to implement that in the following days, as it's something I have to have in my project. If there's any other ideas on how to accomplish that, then I'll be more than happy to read them.
Also, I want to thank you @calebgrove for the great plugin!