3

I'm working on a small component and depending on $someoption I need to remove a certain option from the JForm. So for example if $someoption == 1 then I need to remove this option <option value="1">COM_MY_FIELD2</option>.

I only know how to set the whole field to hidden via setFieldAttribute, but how to remove only one option?

Here is the XML Form part:

<?xml version="1.0" encoding="utf-8"?>
<form>
    <fieldset>
        <field name="field1" type="radio" default="0" label="COM_MY_LABEL1" class="btn-group btn-group-yesno">
            <option value="0">COM_MY_FIELD1</option>
            <option value="1">COM_MY_FIELD2</option>
            <option value="2">COM_MY_FIELD3</option>
        </field>

        ...

Here comes the preprocessForm Function from the model:

protected function preprocessForm(JForm $form, $data, $group = '')
{
    $app        = JFactory::getApplication();

    ...

    if ($app->isClient('site')) {
        if ($someoption == 1) {
            // this sets the whole field to hidden
            $form->setFieldAttribute('field1', 'type', 'hidden'); 
        }
    }
    parent::preprocessForm($form, $data, $group);
}       

...
1
  • So where does $someoption come from? Will showon not work for your project? May we learn more about the context of your question? Commented Nov 21, 2019 at 22:39

3 Answers 3

2

So this is what I've done:

protected function preprocessForm(JForm $form, $data, $group = '')
{
    $app        = JFactory::getApplication();

    ...

    if ($app->isClient('site')) {
        // remove the field from the form. this is not realy needed, because if the third parameter on setField is true, the field gets replaced
        $form->removeField('field1');
        // create a new XML field
        $element = new SimpleXMLElement('<field name="field1"  default="0" type="radio" />');
         // create only the options i need
        if ($someoption == 1) {
                $option = $element->addChild('option', JText::_('COM_MY_FIELD2'));
                $option->addAttribute('value', 2);
        }
        // add the new field back into the form (replacing the old one if it exists)
        $form->setField($element, $group, true);
    }
    parent::preprocessForm($form, $data, $group);
}       

...
2

Another option could be to place the two versions of the field in separate .xml files in your /forms folder and then decide which one to load.

If ($option == 1)
{ 
    $form->loadFile('field_with_option');
}
else
(
    $form->loadFile('field_without_option');
}

In ../mycomponent/models/forms/field_with_option.xml you have

    <field name="field1" type="radio" default="0" label="COM_MY_LABEL1" class="btn-group btn-group-yesno">
        <option value="0">COM_MY_FIELD1</option>
        <option value="1">COM_MY_FIELD2</option>
        <option value="2">COM_MY_FIELD3</option>
    </field>

And in ../mycomponent/models/forms/field_without_option.xml you have

    <field name="field1" type="radio" default="0" label="COM_MY_LABEL1" class="btn-group btn-group-yesno">
        <option value="0">COM_MY_FIELD1</option>
        <option value="2">COM_MY_FIELD3</option>
    </field>

Originally I was thinking along the lines of something like Zollie's answer this morning when I first read the question but based on Mike's solution this is much the same but just keeps the field definition out of the code and back in a .xml in /forms where it belongs.

Update - 23/11 Having re-read @zollie's answer again, I wasn't looking at the DOM object but looking stepping through the Form object to remove the option in there. It would be similar code.

2
  • There are a lot of options now on options :) I was thinking about your solution too in the morning. It is the simplest one.
    – Zollie
    Commented Nov 22, 2019 at 12:28
  • Thanks for your suggestion too! I prefer managing possible logic combinations dynamically inside the code, rather than creating a lot of single XML files. But if its only one combination it's a good way.
    – Mike
    Commented Nov 22, 2019 at 13:12
2

The small problem with your question is that <option> is not a field attribute but an element in XML, so you cannot set or remove that using methods for field attributes.

You can remove however these elements using PHP DOM extension's methods like:

// $myradioForm = new Form('MyRadioForm'); // this is just a Joomla Form object. You use your own Form in your code like $form for example.

// if ($someoption == 1)

$doc = new DOMDocument;

// load your xml file from a path
$doc->load($file); // example: $file = JPATH_ADMINISTRATOR . '/components/com_mycomponent/models/forms/myradio.xml'

$myFormDoc = $doc->documentElement;

// we retrieve the element and remove it from the form - could be item(1) or item(2) too
$myFieldToRemove = $myFormDoc->getElementsByTagName('option')->item(0);
$parent = $myFieldToRemove->parentNode; // we define the parent node

$parent->removeChild($myFieldToRemove); // removing the element

$fieldsNew = $doc->saveXML(); // $fieldsnew here is the form without the removed option

$myradioForm->load($fieldsNew); // you load the form again and it is now without the removed option
echo $myradioForm->renderFieldset('radiogroup'); // change 'radiogroup' to whatever your fieldset name is

I'm sorry for the lot of comments in the code but this way I hope that you can understand it better. I hope you can follow and use the above (it is tried and works).

UPDATE

As @mick pointed out well, the above snippet cannot be applied to the case where there are many radio fields are in the Form, so you have to select the target field more precisely. Thus you have to use the getElementsByTagName() method like below if you have more radio fields as it is usually the case in these forms:

$myFieldToRemove = $myFormDoc->getElementsByTagName('field')->item(0)->firstChild->nextSibling;

Where item(0) is the radio field in the Form, but it could be any selection. firstChild->nextSibling is the first option element in the selected radio field and lastChild->previousSibling is the third option in the field, or

$myRadioField = $myFormDoc->getElementsByTagName('field')->item(1);
$optionToDelete = $myRadioField->childNodes->item(3); // as the second option in the field.

so you can target any options you would like to... I do not consider this as the main part of this question since it is now more about learning how to use PHP DOM.

7
  • How does your snippet know which element/field to remove an option from? Commented Nov 22, 2019 at 9:30
  • 1
    @mickmackusa - my purpose with my answer was not giving full coding solution. My example is only pointing to the bone of this question of how to remove an <option> element from a Form field. I think an additional 2-3 lines can precisely target the Form field if needed and if there are more radio field in the Form.
    – Zollie
    Commented Nov 22, 2019 at 9:35
  • Let's be generous and provide working solutions when answering. If you don't have enough information to do this, then the question is not Clear enough and additional details should be requested of the OP. Commented Nov 22, 2019 at 9:36
  • @mickmackusa - the OP did not say that he has many radio field in the Form to handle that is why I have not concentrated on that. His question has a basic approaching problem and I wanted to target that with my answer. But good point, if I have more time I’ll extend my answer with that additional part.
    – Zollie
    Commented Nov 22, 2019 at 9:40
  • The ... seems to indicate that there are more form fields. Commented Nov 22, 2019 at 9:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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