Frage

Ich habe ein Feldsatz im Admin-Bereich mit einer übergeordneten Auswahl (hat 5 Optionen) und 2 Felder, das angezeigt werden sollte, wenn der ausgewählte übergeordnete Wert 3, 4 oder 5 ist.Ich habe keine Beispiele für eine ähnliche Logik in Magento gefunden und habe versucht, analog zur üblichen Abhängigkeit zu schreiben, aber es funktioniert nicht.In meinem Beispiel werden die abhängigen Felder nur angezeigt, wenn Sie die Optionen mit dem Wert 5 aus der Auswahl auswählen, und nicht, wenn Sie 1, 2, 3 oder 4 auswählen.

Vollständiger Code (Blockbeispiel):

<?php

namespace Siarhey\Test\Block\Adminhtml\Promo\Quote\Edit\Tab;

class Actions extends \Magento\Backend\Block\Widget\Form\Generic implements
    \Magento\Backend\Block\Widget\Tab\TabInterface
{
    /**
     * @param \Magento\Backend\Block\Template\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param \Magento\Framework\Data\FormFactory $formFactory
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Data\FormFactory $formFactory,
        array $data = []
    ) {
        parent::__construct($context, $registry, $formFactory, $data);
    }

    public function getTabLabel()
    {
        return __('Actions');
    }

    public function getTabTitle()
    {
        return __('Actions');
    }

    public function canShowTab()
    {
        return true;
    }

    public function isHidden()
    {
        return false;
    }

    protected function _prepareForm()
    {
        $model = $this->_coreRegistry->registry('current_promo_quote_rule');

        /** @var \Magento\Framework\Data\Form $form */
        $form = $this->_formFactory->create();
        $form->setHtmlIdPrefix('rule_');

        $fieldset = $form->addFieldset(
            'action_fieldset',
            ['legend' => __('Rules')]
        );

        $parentField = $fieldset->addField(
            'simple_action',
            'select',
            [
                'label' => __('Apply'),
                'name' => 'simple_action',
                'options' => [
                    1 => __('Amount 1'),
                    2 => __('Discount 1'),
                    3 => __('Amount 2'),
                    4 => __('Discount 2'),
                ]
            ]
        );

        $childFieldOne = $fieldset->addField(
            'amount',
            'text',
            [
                'name' => 'amount',
                'required' => true,
                'class' => 'validate-not-negative-number',
                'label' => __('Amount')
            ]
        );
        $model->setAmount($model->getAmount() * 1);

        $childFieldTwo = $fieldset->addField(
            'percent',
            'text',
            ['name' => 'percent', 'label' => __('Percent')]
        );
        $model->setPercent($model->getPercent() * 1);

        $this->setChild(
            'form_after',
            $this->getLayout()->createBlock(
                'Magento\Backend\Block\Widget\Form\Element\Dependence'
            )->addFieldMap(
                $parentField->getHtmlId(),
                $parentField->getName()
            )->addFieldMap(
                $childFieldOne->getHtmlId(),
                $childFieldOne->getName()
            )->addFieldMap(
                $childFieldTwo->getHtmlId(),
                $childFieldTwo->getName()
            )->addFieldDependence(
                $childFieldOne->getName(),
                $parentField->getName(),
                '1,3'
            )->addFieldDependence(
                $childFieldTwo->getName(),
                $parentField->getName(),
                '2,4'
            )
        );

        $form->setValues($model->getData());

        if ($model->isReadonly()) {
            foreach ($fieldset->getElements() as $element) {
                $element->setReadonly(true, true);
            }
        }

        $this->setForm($form);
        return parent::_prepareForm();
    }
}

Ergebnis (Ansicht):

Option 1
Option 1 ausgewählt

Option 4 Option 4 ausgewählt

Without dependency Ohne Abhängigkeit

Codebeispiel 1 (funktioniert nicht):

/*
 * $parentField is select with values (0,1,2,3,4,5)
 */
$this->setChild(
    'form_after',
    $this->getLayout()->createBlock(
        'Magento\Backend\Block\Widget\Form\Element\Dependence'
    )->addFieldMap(
        $parentField->getHtmlId(),
        $parentField->getName()
    )->addFieldMap(
        $childFieldOne->getHtmlId(),
        $childFieldOne->getName()
    )->addFieldDependence(
        $childFieldOne->getName(),
        $parentField->getName(),
        '3'
    )->addFieldDependence(
        $childFieldOne->getName(),
        $parentField->getName(),
        '4'
    )->addFieldDependence(
        $childFieldOne->getName(),
        $parentField->getName(),
        '5'
    )->addFieldMap(
        $parentField->getHtmlId(),
        $parentField->getName()
    )->addFieldMap(
        $childFieldTwo->getHtmlId(),
        $childFieldTwo->getName()
    )->addFieldDependence(
        $childFieldTwo->getName(),
        $parentField->getName(),
        '3'
    )->addFieldDependence(
        $childFieldTwo->getName(),
        $parentField->getName(),
        '4'
    )->addFieldDependence(
        $childFieldTwo->getName(),
        $parentField->getName(),
        '5'
    )
);

Codebeispiel 2 (funktioniert nicht):

/*
 * $parentField is select with values (0,1,2,3,4,5)
 */
$this->setChild(
    'form_after',
    $this->getLayout()->createBlock(
        'Magento\Backend\Block\Widget\Form\Element\Dependence'
    )->addFieldMap(
        $parentField->getHtmlId(),
        $parentField->getName()
    )->addFieldMap(
        $childFieldOne->getHtmlId(),
        $childFieldOne->getName()
    )->addFieldMap(
        $parentField->getHtmlId(),
        $parentField->getName()
    )->addFieldMap(
        $childFieldTwo->getHtmlId(),
        $childFieldTwo->getName()
    )->addFieldDependence(
        $childFieldOne->getName(),
        $parentField->getName(),
        array('3', '4', '5')
    )->addFieldDependence(
        $childFieldTwo->getName(),
        $parentField->getName(),
        array('3', '4', '5')
    )
);

Ergebnis:

Beachten:Array to String Conversion in /var/www/magento2/app/code/magento/backend/block/widget/form/element/dependence.php in Zeile 95

AKTUALISIEREN:


Codebeispiel 3 (funktioniert nicht, wenn der ausgewählte Wert nicht funktioniert '3,4,5'):

// Parent field
$typeField = $fieldset->addField(
    'action_type',
    'select',
    [
        'label' => __('Type'),
        'name' => 'action_type',
        'options' => ['1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '3,4,5' => '3,4,5']
    ]
);

$this->setChild(
    'form_after',
    $this->getLayout()->createBlock(
        'Magento\Backend\Block\Widget\Form\Element\Dependence'
    )->addFieldMap(
        $parentField->getHtmlId(),
        $parentField->getName()
    )->addFieldMap(
        $childFieldOne->getHtmlId(),
        $childFieldOne->getName()
    )->addFieldMap(
        $typeField->getHtmlId(),
        $typeField->getName()
    )->addFieldMap(
        $childFieldTwo->getHtmlId(),
        $childFieldTwo->getName()
    )->addFieldDependence(
        $childFieldOne->getName(),
        $parentField->getName(),
        '3,4,5'
    )->addFieldDependence(
        $childFieldTwo->getName(),
        $parentField->getName(),
        '3,4,5'
    )
);

Hat jemand das gleiche Problem gehabt und eine Lösung gefunden?

Aktualisieren:

Vielleicht kann jemand anderes das Vorhandensein dieses Problems überprüfen?Ich habe es bei 3 verschiedenen Installationen überprüft und diese Lösung (die Zeile mit den durch Kommas getrennten Werten) funktioniert immer noch nicht.

War es hilfreich?

Lösung

Wenn Sie den Code überprüfen, der für das Hinzufügen der entsprechenden Felder gemäß den Abhängigkeiten in der Datei verantwortlich ist lib/web/mage/adminhtml/form.js, dort sehen Sie folgendes Schema:

    var shouldShowUp = true;
    for (var idFrom in valuesFrom) {
        var from = $(idFrom);
        if (from) {
            var values = valuesFrom[idFrom]['values'];
            var isInArray = values.indexOf(from.value) != -1;
            var isNegative = valuesFrom[idFrom]['negative'];
            if (!from || isInArray && isNegative || !isInArray && !isNegative) {
                shouldShowUp = false;
            }
        }
    }

Falls Sie durch Kommas getrennte Werte festlegen, zum Beispiel:

    /** @var \Magento\Backend\Block\Widget\Form\Element\Dependence $blockDependence */
    $blockDependence->addFieldMap(
        $actionType->getHtmlId(),
        $actionType->getName()
    )->addFieldMap(
        $amountField->getHtmlId(),
        $amountField->getName()
    )->addFieldDependence(
        $amountField->getName(),
        $actionType->getName(),
        implode(',', array(
            Rule::ACTION_TYPE_OVERWRITE_COST,
            Rule::ACTION_TYPE_ADD_SURCHARGE,
            Rule::ACTION_TYPE_ENABLE_SM_AND_OVERWRITE_COST
        ))
    );

Dann werden Sie das beim Debuggen sehen indexOf versucht, den vorhandenen Wert im Ein-Element-Array zu finden, der in Ihrem Fall ein durch Kommas getrennter Wert ist.Dieses Element kann nicht gefunden werden:

enter image description here

Eine Schritt-für-Schritt-Ausgabe von console.log aus der Methode:

console.log(values);
console.log('Value: '+from.value);
console.log('Is in array: '+isInArray);

Um Felder mit mehreren Abhängigkeiten zu erstellen, können Sie denselben durch Kommas getrennten Wert verwenden, jedoch mit einigen Änderungen.Sie benötigen lediglich den Block, der verlängert wird \Magento\Backend\Block\Widget\Form\Element\Dependence:

<?php

namespace Vendor\Module\Block\Widget\Form\Element;

/**
 * Form element dependencies mapper
 * Assumes that one element may depend on other element values.
 * Will toggle as "enabled" only if all elements it depends from toggle as true.
 */
class Dependence extends \Magento\Backend\Block\Widget\Form\Element\Dependence
{
    /**
     * @param \Magento\Backend\Block\Context $context
     * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder
     * @param \Magento\Config\Model\Config\Structure\Element\Dependency\FieldFactory $fieldFactory
     * @param array $data
     */
    public function _construct(
        \Magento\Backend\Block\Context $context,
        \Magento\Framework\Json\EncoderInterface $jsonEncoder,
        \Magento\Config\Model\Config\Structure\Element\Dependency\FieldFactory $fieldFactory,
        array $data = []
    )
    {
        parent::_construct($context, $jsonEncoder, $fieldFactory, $data);
    }

    /**
     * {@inheritdoc}
     */
    protected function _toHtml()
    {
        if (!$this->_depends) {
            return '';
        }

        return '<script>
                require(["uiRegistry", "mage/adminhtml/form"], function(registry) {
                    var controller = new FormElementDependenceController(' . $this->_getDependsJson() .
        ($this->_configOptions ? ', ' .
            $this->_jsonEncoder->encode(
                $this->_configOptions
            ) : '') . ');
                    registry.set("formDependenceController", controller);
                });</script>';
    }

    /**
     * Field dependences JSON map generator * @return string
     */
    protected function _getDependsJson()
    {
        $result = [];
        foreach ($this->_depends as $to => $row) {
            foreach ($row as $from => $field) {
                $values = $this->_prepareValues($field->getValues());
                /** @var $field \Magento\Config\Model\Config\Structure\Element\Dependency\Field */
                $result[$this->_fields[$to]][$this->_fields[$from]] = [
                    'values' => $values,
                    'negative' => $field->isNegative(),
                ];
            }
        }
        return $this->_jsonEncoder->encode($result);
    }

    /**
     * @param $values
     * @return array
     */
    protected function _prepareValues($values)
    {
        if (!is_array($values)) {
            return $values;
        }

        $result = array();
        foreach ($values as $value) {
            if (stripos($value, ',')) {
                $result += explode(',', $value);
            } else {
                $result += $value;
            }
        }

        return $result;
    }
}

Wie Sie sehen können, muss der Wert ZWANGST in ein Array mit einem Wert geändert werden.

Das Hauptproblem liegt in der addFieldDependence der Klasse \Magento\Backend\Block\Widget\Form\Element\Dependence:

Der Punkt ist, dass der Wert (die Linie aus der Abhängigkeit) als einziges Element des Arrays übertragen wird. indexOf versucht, den Wert der entsprechenden ausgewählten Option zu finden, findet jedoch nicht die genaue Übereinstimmung.Als Ergebnis wird „false“ zurückgegeben.

Es gibt auch keine Möglichkeit, die Werte als Array zu übertragen, da PHP die zurückgibt Notice: Array to string conversion wegen der Umwandlung von 'value' => (string)$refField.

In unserem Beispiel haben wir das Array mit einem Element in ein Array mit mehreren Elementen umgestaltet, wobei jedes Element aus mehreren Abhängigkeiten besteht.

Der Code Ihrer Abhängigkeit sollte geändert werden (Sie müssen den Block ändern).So geht's:

// Dependency START
/** @var \Magento\Backend\Block\Widget\Form\Element\Dependence $blockDependence */
$blockDependence = $this->getLayout()->createBlock(
// 'Magento\Backend\Block\Widget\Form\Element\Dependence'
'{Vendor}\{Module}\Block\Widget\Form\Element\Dependence'
);

$blockDependence->addFieldMap(
    $parentField->getHtmlId(),
    $parentField->getName()
)->addFieldMap(
    $childFieldOne->getHtmlId(),
    $childFieldOne->getName()
)->addFieldMap(
    $childFieldTwo->getHtmlId(),
    $childFieldTwo->getName()
)->addFieldDependence(
    $childFieldOne->getName(),
    $parentField->getName(),
    '1,3'
)->addFieldDependence(
    $childFieldTwo->getName(),
    $parentField->getName(),
    '2,4'
);

$this->setChild('form_after', $blockDependence);
// Dependency END

Das Ergebnis sollte so aussehen:

enter image description here

UPD

Wenn Sie sicher sind, dass Sie in Zukunft einen durch Kommas getrennten Wert verwenden werden, fügen Sie am besten const hinzu UNIQUE_DELIMITER mit dem erforderlichen Wert des Trennzeichens für die Klasse Vendor\Module\Block\Widget\Form\Element\Dependence:Z.B.

const UNIQUE_DELIMITER = '~#!~';

Als nächstes ändern Sie die Partitionsmethode:

/**
 * @param $values
 * @return array
 */
protected function _prepareValues($values)
{
    if (!is_array($values)) {
        return $values;
    }

    $result = array();
    foreach ($values as $value) {
        if (stripos($value, self::UNIQUE_DELIMITER)) {
            $result += explode(self::UNIQUE_DELIMITER, $value);
        } else {
            $result += $value;
        }
    }

    return $result;
}

Dann benutze Vendor\Module\Block\Widget\Form\Element\Dependence::UNIQUE_DELIMITER in deiner Klasse Actions.

Fügen Sie der Einfachheit halber die Klasse hinzu Dependence (nach Namensraum):

use Vendor\Module\Block\Widget\Form\Element\Dependence;

Und schreiben Sie den Code so:

 // Dependency START
    /** @var \Magento\Backend\Block\Widget\Form\Element\Dependence $blockDependence */
    $blockDependence = $this->getLayout()->createBlock(
    // 'Magento\Backend\Block\Widget\Form\Element\Dependence'
        '{Vendor}\{Module}\Block\Widget\Form\Element\Dependence'
    );

    $childFieldOneToParentValues = implode(Dependence::UNIQUE_DELIMITER, array('1','3'));
    $childFieldTwoToParentValues = implode(Dependence::UNIQUE_DELIMITER, array('2','4'));

    $blockDependence->addFieldMap(
        $parentField->getHtmlId(),
        $parentField->getName()
    )->addFieldMap(
        $childFieldOne->getHtmlId(),
        $childFieldOne->getName()
    )->addFieldMap(
        $childFieldTwo->getHtmlId(),
        $childFieldTwo->getName()
    )->addFieldDependence(
        $childFieldOne->getName(),
        $parentField->getName(),
        $childFieldOneToParentValues
    )->addFieldDependence(
        $childFieldTwo->getName(),
        $parentField->getName(),
        $childFieldTwoToParentValues
    );

    $this->setChild('form_after', $blockDependence);
    // Dependency END

Andere Tipps

Ich kann mich vielleicht irren, aber leider glaube ich nicht, dass das mit der Standardeinstellung möglich ist Magento\Backend\Block\Widget\Form\Element\Dependence Klasse.

Lassen Sie mich erklären:

Der addFieldDependence Methode sieht so aus:

public function addFieldDependence($fieldName, $fieldNameFrom, $refField)
{
    if (!is_object($refField)) {
        /** @var $refField \Magento\Config\Model\Config\Structure\Element\Dependency\Field */
        $refField = $this->_fieldFactory->create(
            ['fieldData' => ['value' => (string)$refField], 'fieldPrefix' => '']
        );
    }
    $this->_depends[$fieldName][$fieldNameFrom] = $refField;
    return $this;
}

Nehmen wir also an, Sie probieren diesen Code aus:

addFieldDependence($child,$parent,'2,4')

Der value des $refField wird die folgende Zeichenfolge sein: 2,4 Da es in Ihrer Auswahl keinen solchen Wert gibt, wird es nie funktionieren.

Wenn Sie diesen Code ausprobieren:

addFieldDependence($child,$parent,array('2,4'))

Du bekommst das Array to string conversion Fehler wegen der (string)$refField Code

Wenn Sie diesen Code ausprobieren:

addFieldDependence($child,$parent,'2')->addFieldDependence($child,$parent,'4')

Beim ersten Anruf wird das eingestellt $refField mit dem Wert 2 und weisen Sie es den Abhängigkeiten mit folgendem Code zu:

$this->_depends[$fieldName][$fieldNameFrom] = $refField;

Der zweite Code überschreibt diese Abhängigkeit jedoch, da die $fieldName Und $fieldNameFrom Die Variablen sind die gleichen wie beim ersten Aufruf.

Welche Lösungen haben Sie?

  • Verwenden Sie Einstellungen oder Plugins, um das Verhalten des zu ändern Magento\Backend\Block\Widget\Form\Element\Dependence Klasse

Die wichtigsten Methoden, die hier betrachtet werden sollten, sind addFieldDependence Und _getDependsJson.Das Problem hierbei ist, dass die Wahrscheinlichkeit groß ist, dass Sie auch das JavaScript ändern müssen FormElementDependenceController Klasse, die die Abhängigkeiten behandelt.

  • Verwenden Sie mehrere doppelte Felder mit unterschiedlichen Namen:Nun ja, das ist schmutzig, aber ich denke, das würde funktionieren.

Beispiel:

    $parentField = $fieldset->addField(
        'simple_action',
        'select',
        [
            'label' => __('Apply'),
            'name' => 'simple_action',
            'options' => [
                1 => __('Amount 1'),
                2 => __('Discount 1'),
                3 => __('Amount 2'),
                4 => __('Discount 2'),
            ]
        ]
    );

    $childFieldOne = $fieldset->addField(
        'amount',
        'text',
        [
            'name' => 'amount',
            'required' => true,
            'class' => 'validate-not-negative-number',
            'label' => __('Amount')
        ]
    );

    $childFieldOneCopy = $fieldset->addField(
        'amount',
        'text',
        [
            'name' => 'amount',
            'required' => true,
            'class' => 'validate-not-negative-number',
            'label' => __('Amount')
        ]
    );

Dann benutze:

->addFieldDependence(
            $childFieldOne->getName(),
            $parentField->getName(),
            '1'
        )    
->addFieldDependence(
            $childFieldOneCopy->getName(),
            $parentField->getName(),
            '3'
        )

Das Problem besteht darin, dass Sie im Controller, der die Daten verarbeitet, mehrere Prüfungen hinzufügen müssen, um sicherzustellen, dass Sie die richtigen Daten und nicht das versteckte Kopierfeld verarbeiten.

Ich denke, Sie sollten den klassengenerischen Magento\Backend\Block\Widget\Form\Element\Dependence aussehen.Sie können Ihren eigenen Block erstellen, der von dieser Klasse geerbt wurde, und schreibe es neu, wie Sie möchten.In Ihrem Code ersetzt Blockanruf:

generasacodicetagpre.

an:

generasacodicetagpre.

Erstellen Sie den BlockSiarhey\Test\Block\Widget\Form\Element\Dependence und Sie können Ihre Überprüfungslogik implementieren.

Es ist nur Ratschläge.Ich hoffe, dass es dir hilft.

Erstellen Sie ein di.xml unter adminhtml und fügen Sie dem folgende Anmerkungs hinzu:

muss grundsätzlich überschreiben magento \ backend \ block \ widget \ form \ element \ abhängigkeit class

generasacodicetagpre. generasacodicetagpre.

Jetzt können Sie folgende Weise verwenden.

generasacodicetagpre.

löschen magento2-cache.

Ich bin mir da nicht sicher, ich habe es nicht getestet, aber ich schaue mir das an addFieldDependence Methode und bei \Magento\Config\Model\Config\Structure\Element\Dependency\Field Klasse, ich denke, es könnte funktionieren.

Fügen Sie dies in Ihre Klasse ein:

protected $fieldFactory;
public function __construct(
   ....
   \Magento\Config\Model\Config\Structure\Element\Dependency\FieldFactory $fieldFactory,
   ....
) {
    $this->fieldFactory = $fieldFactory;
}

Dann statt

->addFieldDependence(
    $childFieldOne->getName(),
    $parentField->getName(),
    '1,3'
)

Versuche dies:

$someField = $this->fieldFactory()->create([
    'fieldData' => [
         'separator' => ',',
          'value' => '1,3',
    ],
    'fieldPrefix' => ''
]);

->addFieldDependence(
    $childFieldOne->getName(),
    $parentField->getName(),
    $someField
)

$this->_fieldFactory definieren und unter einem versuchen, es arbeitet für mich:

generasacodicetagpre.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit magento.stackexchange
scroll top