Jump to content

Access module config data in init() or ready()


gebeer
 Share

Recommended Posts

Hello,

I'm struggling to access module config values inside init() or ready().

My module extends InputfieldCheckboxes and implements Module interface.

I have a custom configuration field

    public function ___getConfigInputfields() 
    {
        $inputfields = parent::___getConfigInputfields();

        $modules = $this->wire('modules');
        $options = $this->getInputfieldCheckboxes();

        $f = $modules->get('InputfieldSelect');
        $f->attr('name', 'targetField');
        $f->set('label', $this->_('Choose the target checkboxes field'));
        $f->set('description', $this->_('The field that has checkboxes which depend on this field\'s checkboxes'));
        // $f->set('notes', $this->_('Types indicated with an asterisk are for multiple field selection.'));
        foreach ($options as $fieldName => $prop) $f->addOption($fieldName, $prop['label']);
        $f->attr('value', $this->targetField);
        $inputfields->add($f);

        return $inputfields;
    }

This is working fine and saving values.

Right after getModuleInfo() I have

	public function __construct() {
        parent::__construct();
		$this->set('targetField', '');
	}

In my render() and getConfigInputfields() methods, I can access the value for the custom config setting with $this->targetField.

But in other methods, it is not available.

In the API Reference for init() it says:

Quote

This method is called after __construct() and after any configuration data has been populated to the module.

When I remove my __construct() method entirely, config values still get saved correctly. But when I access $this->targetField in init() or ready(), I get null.

How can I access configuration data inside init() or ready() ?

I read many posts and looked at how other modules do this. But couldn't find a solution.

Thanks in advance for any pointers.

Link to comment
Share on other sites

The thing you quoted from the API reference is specific to Module configuration. Configuration data for the module (that which is configured in Modules > InputfieldSomething) would be populated after __construct(), and before init(). But you are attempting to access configuration for a Field rather than a Module. The method you are using (getConfigInputfields) is what is used by Fieldtype and Inputfield modules for configuration of a Field. This is unrelated to Module configuration, because a single Fieldtype/Inputfield module can be used for multiple fields. Further, an Inputfield module can be used independently of ProcessWire's Fields system (like in other forms that aren't connected with PW fields) where a getConfigInputfields() method wouldn't even apply. For these reasons, you can't have field/instance-specific configuration data populated to Fieldtype or Inputfield modules as part of the usual Module boot process. For an Inputfield module, you would want to move whatever field-specific initialization you need into the ___render()  method, or renderReady() method instead if you need it to happen before. 

Link to comment
Share on other sites

If you use a renderReady() method, here's what the definition looks like: https://github.com/processwire/processwire/blob/master/wire/core/Inputfield.php#L1009

Remember to end by calling the parent::renderReady() method as well:

public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
  // perform any needed initialization here
  return parent::renderReady($parent, $renderValueMode); 
}

 

  • Like 1
Link to comment
Share on other sites

@ryan thank you for the insight.

Problem is, that I need my config setting values to be available to the

public function addOption($value, $label = null, array $attributes = null) {...}

which replaces the original method in wire/modules/InputfieldSelectMultiple.module.

And that method is called before renderReady().

I'm adding custom data attributes to the checkboxes using

    /**
     * Adds an option with extended attributes
     * Replaces original method in wire/modules/InputfieldSelectMultiple.module
     * taken from https://processwire.com/talk/topic/419-extending-inputfields/?do=findComment&comment=76823
     *
     */
    public function addOption($value, $label = null, array $attributes = null)
    {
        if(is_null($value) || (is_string($value) && !strlen($value))) return $this;

        if (null === $attributes) {
            $attributes = array();
        }

        $extra_atts = $this->extendAttributes($value, $label);
        $attributes = array_merge($attributes, $extra_atts);

        return parent::addOption($value, $label, $attributes);
    }


    /**
     * Hook this and return an array with whatever extended attributes you need.
     *
     */
    public function ___extendAttributes($id, $value)
    {
        /**
         * Either hook this method to do what you want or implement things directly if this
         * is the only use of this Inputfield.
         * For your example you'd grab the fields you want from your page and put into data
         * attributes...
         */
        $atts = array();
        $targets = array();

        $deps = wire('pages')->find("template=certification, instructor_types={$id}");
        foreach ($deps as $d) {
            $targets[] = $d->id;
        }
        $atts['data-icbdtargets'] = json_encode($targets);

        return $atts;
    }

And I want to build the hardcoded selector in 

$deps = wire('pages')->find("template=certification, instructor_types={$id}");

from values that I get from the settings fields in getConfigInputfields().

If it is not possible at all I would have to create an extra configurable module that provides the settings. I'd like to avoid that overhead.

My Inputfield module provides configurable dependent checkboxes.

dependent-checkboxes.gif

It is working with the hardcoded selector. But I want to release this as a configurable module so that people don't need to alter code in the module.
It makes sense to have the settings in the 'Input" Tab of the field settings. So I would like to avoid the need of an extra module for config settings.

I'm pretty new to module development and haven't grasped all concepts yet.

Link to comment
Share on other sites

Kind of solved.

I decided to refactor my module code and replace the original render() method instead of the addOptions() method of InputfieldCheckboxes module. This way I can access my settings values inside the render method and make use of them further down the road.

Link to comment
Share on other sites

Sounds like you found a good solution. Other potential solutions are reading and re-writing the options from your render() method, or override the renderOptions() method, or just modify the protected properties inherited from InputfieldSelect (like $this->options or $this->optionAttributes). 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...