Skip to content
Grav 2.0 is officially stable. Read the announcement →

Community guidelines

Please keep discussions civil and on-topic. Repeated violations may lead to a temporary ban.

Forms & Blueprints

Populate select field with function call (data-*@)

Solved by pamtbaau View solution

Started by Julien 6 years ago · 8 replies · 1293 views
6 years ago

I'm trying to populate a select field in a blueprint with entries from a list field in a plugin configuration.

Consider this excerpt of blueprint.yaml of plugin Foo:

YAML
fields:
    bar:
        type: list
        fields:
            .id:
                type: text
                label: "ID"
            .value:
                type: text
                label: "Value"

Now, in a page blueprint, I'd like to have a select field that lists all bar items via their id. I don't think this is possible with config-*@ syntax, but reading through the documentation on blueprint function calls (data-*@) makes me believe it should be possible this way. However, from the documentation, I don't understand how to call upon a function from plugin Foo. Here is what I tried:

YAML
header.baz:
    type: select
    label: "Baz"
    data-options@: '\Grav\Plugin\Foo::myStaticFunc'

Where the foo.php has the appropriate function (currently just returning dummy data):

TXT
public static function myStaticFunc()
{
    // Obviously, this should actually fetch the configuration
    // and then get and return all `id` values of items in `bar`
    return ["some", "values", "please"];
}

I thought this might work, as the documentation has this example: '\Grav\Plugin\Admin::route'. However, the above did not yield any values in the select field. Thinking that I might return the wrong type, I also tried the same with an associative array, to no avail. I'm thinking the error might be in how I call the function, so I also tried the following without success (I'm just guessing at this point):

  • '\Grav\Plugin\Foo\Foo::myStaticFunc'
  • '\Grav\Plugins\Foo::myStaticFunc'
  • '\Grav\Plugins\Foo\Foo::myStaticFunc'
  • '\Grav\Common\Plugin\Foo::myStaticFunc'
  • '\Grav\Common\Plugin\Foo\Foo::myStaticFunc'

Hence, I hope you can help me to figure out...

  • What is the correct syntax and is that documented somewhere?
  • What data structure would a function need to return for data-options@, an array?
last edited 04/20/20 by Julien
6 years ago Solution

@domsson, You may have named the plugin 'Foo', but the php class will be named 'FooPlugin'. In the blueprint, you should be referencing the name of the class, not the name of the plugin.

So try the following:

TXT
data-options@: '\Grav\Plugin\FooPlugin::myStaticFunc'
👍 1
6 years ago

Thank you, @pamtbaau - that did the trick. To summarize, here is how it worked:

Blueprint:

TXT
data-options@: '\Grav\Plugin\FooPlugin::myStaticFunc'

foo.php:

JS
public static function myStaticFunc()
{
    return ["some" => "Some", "values" => "Values", "please" => "Please"];
}
last edited 04/20/20 by Julien
5 years ago

I ran into this scenario again and found this post of myself. However, I was left with one more question: How to get the plugin configuration from within PHP?

Now, I'm not sure this is the best way (probably not), but this will do the trick:

PHP
public static function myStaticFunc()
{
    $pluginName = "whatever_the_name";
    $pluginConfig = Grav::instance()["config"]["plugins"][$pluginName];
    $desiredData = $pluginConfig["foo"];
    return $desiredData;
}

This has at least one issue, though: the hard-coded plugin name. In a non-static function, we could use $this->name, but $this isn't available in a static context. If someone knows a way around this, please let me know.

5 years ago

@domsson, Would you mind explaining why using a hardcoded plugin name is an issue?

5 years ago

Presumably it would be more broadly applicable if it was dynamic. That's not possible though because of the context, as you noted @domsson. You can, however, parametrize the method:

YAML
data-default@: ['\Grav\Plugin\FooPlugin::myStaticFunc', 'pluginname']

With:

PHP
public static function myStaticFunc($pluginName)
{
    return Grav::instance()['config']->get(
        'plugins.' . $pluginName. '.arrayOfStuff',
        ['' => 'None']
    );
}

The second parameter of the get()-method is the default value. It would also be pertinent to check the shape of the retrieved data before returning it, as the user could have broken an expected associated array.

The benefit of the getter is that you won't be getting errors about arrays. Stacking accessors in the form of ["config"]["plugins"][$pluginName]["foo"] will fail if any of the keys do not exist, rather than fallback to null.

👍 1
last edited 05/20/21 by Ole Vik
5 years ago

@pamtbaau I shouldn't have used the word "issue", really. After all, a plugin's name occurs all over the place, from directory and file names to class names. However, I do like to keep my code as dynamic as possible wherever that is an option.

To name just one possible benefit here: it would make for easily reusable code. Or, to phrase it differently, it might prevent issues resulting from copy & paste of existing code.

@OleVik thank you, those are great suggestions.

5 years ago

@domsson, OK, fair enough.

By the way, I presume OleVik meant the following syntax to get the config:

PHP
Grav::instance()['config']->get();
👍 1
last edited 05/20/21 by pamtbaau
5 years ago

Oh, indeed! I'll correct that, thanks.

Suggested topics

Topic Participants Replies Views Activity
Forms & Blueprints · by Ton Haarmans, 5 years ago
13 1135 4 months ago
Forms & Blueprints · by Hugo Oliveira, 5 months ago
0 60 5 months ago
Forms & Blueprints · by Flachy Joe, 6 months ago
9 132 6 months ago
Forms & Blueprints · by Augustus, 7 months ago
7 108 7 months ago
Forms & Blueprints · by Julien, 7 months ago
10 127 7 months ago