2

My plugin uses a {{ forms.editableTable({...}) }} field within the settings.twig. When the field has row items it will save just fine, but when the table is empty it attempts to save it as an empty string. This throws an error:

Typed property marknotton\myplugin\models\Settings::$whitelist must be array, string used

I would have expected it to save an empty array. Especially as I've defined the default value as an array in the Settings class.

Following Brandons suggestion from an older issue, I have tried to amend the setting before it is saved via an Event listener:

// This is in my plugins init() method
Event::on(
  MyPlugin::class,
  MyPlugin::EVENT_BEFORE_SAVE_SETTINGS,
  [Settings::class, 'onBeforeSaveSettings']
);
class Settings extends Model {

  public array $whitelist = [];

  public function rules(): array 
  {
    return [
      ['whitelist', ArrayValidator::class],
    ];
  }

  public static function onBeforeSaveSettings(ModelEvent $event): ModelEvent
  {
    $plugin = $event->sender;
    $settings = $plugin->getSettings();

    if ( is_string($settings['whitelist']) ) {
      $settings['whitelist'] = [];
    }
    
    return $event;
  }

}

This works perfectly in Craft 4, but in Craft 3 my 'onBeforeSaveSettings' method isn't getting called at all.

Is this just a novice data type issue I'm overlooking? Or is the EVENT_BEFORE_SAVE_SETTINGS event failing to run on Craft 3 specifically?

2 Answers 2

1

So the reason your code worked with Craft 3 was that it wasn't typed, so it was okay with an empty table being stored as a string.

As for why your normalization via event doesn't work:

  • Does the event get triggered?
  • If yes, maybe try:
    if (empty($settings['whitelist'])) {
      $settings['whitelist'] = [];
    }

...in case the value is coming in as null or some other empty value?

1
  • Thanks @andrew, the 'EVENT_BEFORE_SAVE_SETTINGS' event isn't being triggered at all in Craft 3. I've tried using the "EVENT_BEFORE_SAVE_PLUGIN_SETTINGS" instead, which does trigger, however when the whitelist field is empty the type error gets thrown before the event does. Aug 14, 2022 at 20:23
1

Prevent users on Craft 3 from being able to submit an empty table:

In the plugins settings.twig file update the the 'whitelist' rows variables to an empty array if it's empty and the Craft version is starts with "3"

{% if whitelist is empty and craft.app.getVersion()|first == '3' %}
  {% set whitelist = whitelist is empty ? { item : '' } %}
{% endif %}

If you are using the 'allowReorder' property; it is worth hiding the first delete button on the first row item:

{% css %}
  #settings-whitelsit tbody > tr:first-of-type a.delete { display:none; }
{% endcss %}

There is a minRows property that can be defined in the editableTable options:

forms.editableTable({
  minRows : craft.app.getVersion()|first == '3' ? 1 : null,
  ...
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.