web-dev-qa-db-fra.com

Suppression d'une seule option JForm via setFieldAttribute

Je travaille sur un petit composant et en fonction de $someoption J'ai besoin de supprimer une certaine option du JForm. Par exemple, si $someoption == 1 alors je dois supprimer cette option <option value="1">COM_MY_FIELD2</option>.

Je sais seulement comment définir le champ entier sur hidden via setFieldAttribute, mais comment supprimer une seule option?

Voici la partie du formulaire XML:

<?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>

        ...

Voici la fonction preprocessForm du modèle:

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);
}       

...
2
Mike

Le petit problème avec votre question est que <option> N'est pas un attribut de champ mais un élément en XML, donc vous ne pouvez pas définir ou supprimer cela en utilisant des méthodes pour le champ les attributs.

Vous pouvez cependant supprimer ces éléments en utilisant PHP méthodes d'extension DOM comme:

// $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

Je suis désolé pour le grand nombre de commentaires dans le code mais de cette façon j'espère que vous pourrez mieux le comprendre. J'espère que vous pourrez suivre et utiliser ce qui précède (c'est essayé et ça marche).

MISE À JOUR

Comme @mick l'a bien souligné, l'extrait ci-dessus ne peut pas être appliqué au cas où de nombreux champs radio sont dans le formulaire, vous devez donc sélectionner le champ cible plus précisément. Vous devez donc utiliser la méthode getElementsByTagName() comme ci-dessous si vous avez plus de champs radio comme c'est généralement le cas dans ces formulaires:

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

item(0) est le champ radio dans le formulaire, mais il peut s'agir de n'importe quelle sélection. firstChild->nextSibling Est le premier élément d'option dans le champ radio sélectionné et lastChild->previousSibling Est la troisième option du champ, ou

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

vous pouvez donc cibler toutes les options que vous souhaitez ... Je ne considère pas cela comme la partie principale de cette question car il s'agit maintenant d'apprendre à utiliser PHP DOM.

1
Zollie

Voici donc ce que j'ai fait:

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);
}       

...
1
Mike

Une autre option pourrait être de placer les deux versions du champ dans des fichiers .xml distincts dans votre dossier/forms, puis de décider laquelle charger.

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

Dans ../mycomponent/models/forms/field_with_option.xml vous avez

    <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>

Et dans ../mycomponent/models/forms/field_without_option.xml vous avez

    <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>

À l'origine, je pensais dans le sens de quelque chose comme la réponse de Zollie ce matin lorsque j'ai lu la question pour la première fois, mais sur la base de la solution de Mike, c'est à peu près la même chose mais garde simplement la définition du champ hors du code et retourne dans un .xml dans/formulaires où ça appartient.

Mise à jour - 23/11 Après avoir relu la réponse de @ zollie, je ne regardais pas l'objet DOM mais je regardais en passant par l'objet Form pour supprimer l'option là-dedans. Ce serait un code similaire.

1
Irata