Merge 2 fields for a dropdown

Hello everyone,

i’m trying to merge 2 fields together. One hidden field

settingcolorsdefault:
   type: hidden
   default: 1st, 2nd, Accent, Success, Info, Warning, Error, White, Light, Gray, Dark, Black

and one where the users can create additional colors

settingcolorscustom:
   label: Benutzerdefinierte
   type: tags
   icon: settings
   width: 3/4

i tried it with a collection, but don’t know if it is the proper way.

lcomposerbgco:
  label: 'Hintergrund [--]'
  type: select
  options: query
  query:
    fetch: kirby.collection("colors")
    text: '{{ arrayItem.value }}'
    value: '{{ arrayItem.value }}'
  width: 1/4

I had some problems with the collection, didn’t found the right way in kirby and made some workarounds, which didn’t work perfect.

collections/colors.php

<?php

require_once('site/snippets/_includes/getArrayByVariable.php');

return function ($kirby, $site) {
    $defaultVariable = 'settingcolorsdefault';
    $customVariable = 'settingcolorscustom';

    return mergeArraysByVariables($site, $kirby, $defaultVariable, $customVariable, false);
};

getArrayByVariable.php

<?php
require_once('site/snippets/_includes/checkArray.php');
require_once('site/snippets/_includes/getCurrentPathFromKirbyObject.php');

function getCurrentPathFromKirbyObject($kirby){
  $urlFromKirby = $kirby->urls()->current(); // gibt http://127.0.0.1:8000/api/pages/technikdirekt+test2/sections/content-col-0-fields oder http://127.0.0.1:8000/api/pages/technikdirekt+test2
  $extracedShopAndSite = str_replace("pages/", "", substr($urlFromKirby, strpos($urlFromKirby, "pages/"))); // gibt technikdirekt+test2/sections/content-col-0-fields oder technikdirekt+test2
  if (strpos($extracedShopAndSite, "/")){
    $shopAndSitePath = str_replace("+", "/", substr($extracedShopAndSite, 0, strpos($extracedShopAndSite, "/"))); // gibt technikdirekt/test2
  }else{
    $shopAndSitePath = str_replace("+", "/", $extracedShopAndSite); // gibt technikdirekt/test2
  }

  return $shopAndSitePath;
}

function mergeArraysByVariables($site, $kirby, $defaultVariable, $customVariable, $isNotHex)
{
  $shopAndSitePath = getCurrentPathFromKirbyObject($kirby);

  $defaultArray = $site->findPageOrDraft($shopAndSitePath)->$defaultVariable()->split();
  $customArray = $site->findPageOrDraft($shopAndSitePath)->$customVariable()->split();

  if ($isNotHex) {
    $customArray = checkIfCustomEntriesAreProper($customArray);
  }


  return A::merge($defaultArray, $customArray);
};

In addition i noticed, that my draft pages are not found.

TLDR:
i want to merge 2 fields (one already declared and one custom input field) into one dropdown with the data of both fields as options.


When my site is still a draft, i get this errorMessage
image
and i also have problems with the duplicate function.

I tried to return an object by adding (object) to my return, but this wasn’t working either. return (object) A::merge($defaultArray, $customArray);

I also tried to work without the ->split() because this returns an array

Thanks in advance.
Stefan

Have you tried to make a model like allMyColors that does the merge and can then be queried in the blueprint? E.g.:

options:
    type: query
    query: site.allMyColors.split

Where are those two fields you want to merge. Trying to understand what you want with this path stuff…

That’s what i tried in the collection.
How can i change the model?

The yaml is 950 lines long, so i only showed the two fields, which i am trying to merge.
If you mean the path, are under /site/blueprints/pages/layoutcomposer.yml
layoutcomposer is our template.

fields:
          settingcolorsdefault:
            type: hidden
            default: 1st, 2nd, Accent, Success, Info, Warning, Error, White, Light, Gray, Dark, Black
          settingcolorscustom:
            label: Benutzerdefinierte
            type: tags
            icon: settings
            width: 3/4

These are the two fields i want to merge to get one select box.

I did the path stuff the get the shop and page in return.
We have multiple shops in one kirby.
So our content folder looks like this:

- content/
  - shop1/
    -siteA/
    -siteB/
  -shop2/
    -siteA/
    -siteB/

the url then looks like panel/pages/shop1+siteA
and the only location in the objects where i found the needed data was in this path

$defaultArray = $site->findPageOrDraft($shopAndSitePath)->$defaultVariable()->split();

Well, what I rather meant if this is used in a specific page that can be queried. Or if there are multiple pages that use the layoutcomposer.yml blueprint, and if so, where are these located in relation to where they are queried.

Search by :cool: Slinky

1 Like

Thanks. I’ll check

# site/blueprints/site.yml:
# Make sure that the field values are present in site.txt!
fields:
    defaultcolors:
        type: hidden
        default: '#FFFFFF, #808080, #000000'    
    customcolors:
        type: tags
        help: Define your colors.

# site/collections/allcolors.php:
<?php
return function () {
    return array_merge(
        ['#C0FFEE', '#BADA55', '#B000B5'], // also possible
        site()->defaultcolors()->split(),
        site()->customcolors()->split()
    );
};

# site/blueprints/pages/mypage.yml:
fields:
    allcolors:
        type: select
        accept: options
        options:
            type: query
            query: kirby.collection("allcolors")
            help: Choose a color.
1 Like

According to the above, the colors are not stored in the site object…

1 Like

i shorted my blueprint, to the necessary part.
now it is more readable.

title: Layout Composer
icon: grid-top

tabs:
  # page builder tab
  content:
    label: Layout Composer
    icon: grid-top
    columns:
      - width: 1/1
        fields:
          composerArea:
            label: 'Seiten-Inhalt(e)'
            type: layout
            layouts:
              - '1/1'
              - '1/2, 1/2'
              - '7/12, 5/12'
              - '2/3, 1/3'
              - '3/4, 1/4'
              - '5/12, 7/12'
              - '1/3, 2/3'
              - '1/4, 3/4'
              - '1/3, 1/3, 1/3'
              - '1/2, 1/4, 1/4'
              - '1/4, 1/2, 1/4'
              - '1/4, 1/4, 1/2'
              - '1/4, 1/4, 1/4, 1/4'
            fieldsets:
              text:
                label: Text
                type: group
                fieldsets:
                  lCheadline: blocks/lCheadline
                  lCrte: blocks/lCrte
                  lCtable: blocks/lCtable
              media:
                label: Media
                type: group
                fieldsets:
                  lCimg: blocks/lCimg
              misc:
                label: Misc
                type: group
                fieldsets:
                  lCbtn: blocks/lCbtn
                  lCdivider: blocks/lCdivider
            settings:
              tabs:
                row:
                  label: 'Reihe'
                  fields:
                    rowbgco:
                      extends: fields/lib/lc-colorbg

  settings:
    label: Optionen
    icon: settings
    columns:
      - width: 1/2
        fields:
          colHeadlineSettings:
            label: 'Layout Seite'
            type: headline

          lcomposerbgco:
            extends: fields/lib/lc-colorbg
      - width: 1/2
        fields:
          settingColorsHeadline:
            label: '@Farben'
            type: headline
            numbered: false
            width: 1/4
          # is used for the merge
          settingcolorsdefault:
            type: hidden
            default: 1st, 2nd, Accent, Success, Info, Warning, Error, White, Light, Gray, Dark, Black
          settingcolorscustom:
            label: Benutzerdefinierte
            type: tags
            icon: settings
            width: 3/4

fields/lib/lc-colorbg

label: 'Hintergrund [--]'
type: select
options: query
query:
  fetch: kirby.collection("colors")
  text: '{{ arrayItem.value }}'
  value: '{{ arrayItem.value }}'
width: 1/4

Looks pretty good.
Thanks.

The only problem is, due to our different structure, my site object looks different to the normal site object.
This is my site object and i need to go one level deeper than normal.
That’s why i used the strange function getCurrentPathFromKirbyObject() but this worked.
But now the findPageOrDraft() method does not find the drafts anymore and i don’t know why.

Kirby\Cms\Site Object
(
    [children] => Kirby\Cms\Pages Object
        (
            [0] => dexxit
            [1] => dgh
            [2] => difox
            [3] => fotodepot
            [4] => fujifilminstax
            [5] => powered4school
            [6] => powered4you
            [7] => smartlock
            [8] => soular
            [9] => tddemoware
            [10] => technikdirekt
            [11] => wfv
        )

    [content] => Kirby\Cms\Content Object
        (
            [title] => Filialen Panel
        )

    [errorPage] => 
    [files] => Kirby\Cms\Files Object
        (
        )

    [homePage] => 
    [page] => 
    [title] => Filialen Panel
    [url] => http://127.0.0.1:8000/de
)

This field, is that in the same layoutcomposer blueprint? Looks like two different things… maybe just due to your input. And if so where is it used?

Ah damn, i forgot to mention it.
this is the fields/lib/lc-colorbg

OK, then I’d do this in a page model method, as already suggested by @Slinky . But the main problem remains that if the user adds color in custom color settings, for them to appear in the select field, they would have to save the page first. That’s why it would make sense to store this information in a different page from where it is used.

Yes, save and reload or switch the tab.
I tried to change the page model, but couldn’t get it to work.
Maybe our multiple shop structure causes some problems here.

You should have a model like this:

class LayoutComposerPage extends \Kirby\Cms\Page
{
    public function colors()
    {
        $defaultColors = $this->settingcolorsdefault()->split();
        $customColors = $this->settingcolorscustom()->split();
        return array_merge($defaultColors, $customColors);
    }
}

Field:

                    rowbgco:
                      label: 'Hintergrund [--]'
                      type: select
                      options: query
                      query:
                        fetch: page.colors
                        text: '{{ item.value }}'
                        value: '{{ item.value }}'
                      width: 1/4
1 Like

Thank you very much Sonja.
That does exactly what i needed.