Cascading Drop-down remove options with PHP eval

Discussion in 'Standard Support' started by pastvne, Dec 7, 2017 at 7:12 AM.

  1. pastvne

    pastvne Bruce Decker

    Level: Standard
    I have a need to filter the drop-down options in a cascading drop down with PHP code. I have been looking for an example of how to use the $opt->value, $opt->text in the (eval) option of the element. I've been able to figure out how to alter an option this way but what I really need to do is to remove it. Ideally, I'd like to add one if necessary. I've tried using $options but I can't see to get that to work.

    I'm not finding tutorials or examples. Can someone point me to some information about how I can use PHP code to remove some options from the drop-down?
     
  2. cheesegrits

    cheesegrits Support Gopher Staff Member

    Level: Professional
    I'm pretty sure if you return false it'll remove the option. I know I added that to the join model, and I think the CDD just extends that.

    -- hugh
     
  3. cheesegrits

    cheesegrits Support Gopher Staff Member

    Level: Professional
    Yup ...

    https://github.com/Fabrik/fabrik/bl...ik_element/databasejoin/databasejoin.php#L536

    You code gets called for each option, and can modify $opt->value or $opt->text, or return false to remove that option.

    I guess to add an option you could do ...

    $opts[] = (object) array('text' => 'Foo', 'value' => '123');

    ... although as you are getting called in a foreach on $opts, you'll need to make sure you only do it once, and account for the fact that you'll then get called with that newly added $opt.

    I've never actually tried adding to an array I'm iterating inside the foreach, but I suppose it'd work.

    -- hugh
     
  4. pastvne

    pastvne Bruce Decker

    Level: Standard
    Excellent. Shoulda thought of this. I'll give it a whirl!
    Thanks Hugh!
    -BD
     
  5. cheesegrits

    cheesegrits Support Gopher Staff Member

    Level: Professional
    I've updated the tooltip to mention returning false to delete.

    -- hugh
     
  6. pastvne

    pastvne Bruce Decker

    Level: Standard
    Awesome Hugh.
    return false; is working great. I am putting in more complex code into this eval and I have a bug but I don't seem to be getting my echo debug statements to the browser to see what is going wrong. Is there a way to be able to see trace messages to the browser or is is because the headers have already been sent and I can't do this? I could write the messages to a log but wondering if there is a better/faster way.
     
  7. cheesegrits

    cheesegrits Support Gopher Staff Member

    Level: Professional
  8. pastvne

    pastvne Bruce Decker

    Level: Standard
    Thanks for that Hugh. j!dump is sort of working. I've messed with system plug-in order but it appears that in the eval code, my use of placeholders such as {my->groups} isn't being processed. Can you confirm that placeholders are allowed within the eval() code on a cascading pull-down element? If so, I'll start to look elsewhere.
     
  9. cheesegrits

    cheesegrits Support Gopher Staff Member

    Level: Professional
    Nope, doesn't look like we do placeholder replacement in evalOpts().

    You could access the form data array directly, with ...

    Code (Text):

    $foo = FArrayHelper::getValue($this->getFormModel()->data, 'yourtable___foo', '');
     
    ... or get a user's authorized groups with ...

    Code (Text):

    $groups = JFactory::getUser()->getAuthorisedGroups();
     
    ... etc.

    -- hugh
     
    pastvne likes this.
  10. pastvne

    pastvne Bruce Decker

    Level: Standard
    Hi Hugh:
    JFactory::getUser() is working great but I am struggling with FArrayHelper:: I am in the form trying to reference a value from a drop-down element. Is this what FArrayHelper is supposed to do?

    Here's my code:
    Code (Text):

    $divisionCode = FArrayHelper::getValue($this->getFormModel()->data, 'csp_subscriptions___division_code', '');
     
    -BD
     
  11. cheesegrits

    cheesegrits Support Gopher Staff Member

    Level: Professional
    Our array helper is just a wrapper around J!'s ArrayHelper, with a couple of added functions.

    It's not compulsory, but typically when accessing arrays, it's best to use ArrayHelper::getValue($array, 'thing', 'default') rather than access $array['thing'] directly, in case 'thing' doesn't exist. When doing direct access, that will throw a PHP warning, whereas ArrayHelper::getValue() will return your default.

    So using the getValue() function is the equivalent of doing ...

    Code (Text):

    if (array_key_exists('thing', $array)) {
       $thing = $array['thing'];
    }
    else {
       $thing = 'default';
    }
     
    The reason for suggesting FArrayHelper is that in >= 3.7, J!'s ArrayHelper is namespaced, so you either have to ...

    use Joomla\Utilities\ArrayHelper

    ... at the start of the file (which you can't in your code), or you have to do ...

    Joomla\Utilities\ArrayHelper::getValue()

    ... which is a little cumbersome. We have a class_alias for FArrayHelper that autoloads our namespaced helper, which in turn extends (and hence autoloads) the J! ArrayHelper class.

    In the case of an element that has the concept of options (joins, dropdowns, etc), its data will itself be an array. So if expecting that, I usually do ...

    Code (Text):

    $divisionCode = FArrayHelper::getValue($this->getFormModel()->data, 'csp_subscriptions___division_code', '');
    $divisionCode = is_array($divisionCode) ? $divisionCode[0] : $divisionCode;
     
    -- hugh
     
  12. pastvne

    pastvne Bruce Decker

    Level: Standard
    Hi Hugh:
    I tried this and still am getting a null returned to $division_code. I also tried $divisionCode2 = var_dump($divisionCode) then dumping that and also get a null. I don't seem to be able to grab the value of the csp_subscriptions___division_code database join element from a cascading drop-down's advanced>eval code. Sorry to be a pest. I can open a hole if's easier to see.
    -BD
     
  13. cheesegrits

    cheesegrits Support Gopher Staff Member

    Level: Professional
  14. pastvne

    pastvne Bruce Decker

    Level: Standard
    Perfect.
    Code (Text):

    $divisionCode=$data['csp_subscriptions___division_code'];
    dump($divisionCode,'$divisionCode');
     
    Gives me what I need. I was expecting the external label from the element drop-down option but the internal (raw) value is stored both in the _raw and unraw versions. But, it turns out I can work with this.

    Not sure about the $this->optionVals[$sqlKey] part of what you are saying but the rest got me to a solution. Do you think that $data[] will be deprecated in the near future and is it safe to reference the named element of the $data[] array?

    Thanks again Hugh,
    BD
     
  15. cheesegrits

    cheesegrits Support Gopher Staff Member

    Level: Professional
    Yup, at this phase of processing, the labels haven't been generated from the raw values. Or rather, you are hooking in to part of the process that does that, so there's no guarantee that other elements will have had this processing done yet.

    Re the optionVals[], in my previous post I said you could (probably) add to the options by adding to $opts ...

    Code (Text):

    $opts[] = (object) array('text' => 'Foo', 'value' => '123');
     
    ... but I was looking at an unused chunk of code, and you'd actually have to do it with ...

    Code (Text):

    $this->optionVals[$sqlKey][] = (object) array('text' => 'Foo', 'value' => '123');
     
    No, $data won't be deprecated.

    Referencing a name in $data is safe, but I still recommend using the array helper getValue() rather than accessing it directly. That's just the way to access arrays, for safe code. I'm sure you noticed warnings in the past from Fabrik code about array keys not existing ... that's where we've been naughty and not used a helper, assuming that a key will always exist, forgetting about some particular condition that causes it not to exist.

    -- hugh
     

Share This Page