Skip to content

Come rendere i campi del fieldset multidipendenti?

Il nostro team di redattori ha passato ore a cercare soluzioni alle tue ricerche, ti offriamo le soluzioni ed è per questo che il nostro desiderio è di esserti di grande aiuto.

Soluzione:

Se si controlla il codice che è responsabile dell'aggiunta dei campi corrispondenti in base alle dipendenze nel file lib/web/mage/adminhtml/form.jssi vedrà il seguente 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;
            }
        }
    }

Se si impostano valori separati da virgole, per esempio:

    /** @var MagentoBackendBlockWidgetFormElementDependence $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
        ))
    );

allora durante il debug si vedrà che indexOf sta cercando di trovare il valore esistente nell'array a un elemento, che nel vostro caso è un valore separato da virgole. Questo elemento non può essere trovato:

enter image description here

L'output passo-passo di console.log del metodo:

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

Per creare campi multidipendenza, si può usare lo stesso valore separato da coma, ma con alcune modifiche. Avremo bisogno del blocco che estenderà il campo MagentoBackendBlockWidgetFormElementDependence:

_depends) {
            return '';
        }

        return '';
    }

    /**
     * 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 MagentoConfigModelConfigStructureElementDependencyField */
                $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;
    }
}

Come si può vedere, il valore è FORZATO a essere trasformato in un array di 1 valore.

Il problema principale risiede nel blocco addFieldDependence della classe MagentoBackendBlockWidgetFormElementDependence:

Il punto è che il valore (la riga della dipendenza) viene trasferito come unico elemento dell'array. indexOf cerca di trovare il valore dell'opzione scelta corrispondente, ma non riesce a trovare la corrispondenza esatta. Di conseguenza, restituisce 'false'.

Non c'è nemmeno modo di trasferire i valori come array, poiché PHP restituisce l'elemento Notice: Array to string conversion a causa della conversione di 'value' => (string)$refField.

Nel nostro esempio, abbiamo ricreato l'array a un elemento in uno a più elementi, dove ogni elemento è costituito da diverse dipendenze.

Il codice della dipendenza deve essere modificato (è necessario cambiare il blocco). Ecco come fare:

// Dependency START
/** @var MagentoBackendBlockWidgetFormElementDependence $blockDependence */
$blockDependence = $this->getLayout()->createBlock(
// 'MagentoBackendBlockWidgetFormElementDependence'
'{Vendor}{Module}BlockWidgetFormElementDependence'
);

$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

Il risultato dovrebbe assomigliare a questo:

enter image description here

AGGIORNAMENTO

Se si è sicuri di utilizzare un valore separato da virgole in futuro, il modo migliore è aggiungere la costante UNIQUE_DELIMITER con il valore richiesto del delimitatore alla classe VendorModuleBlockWidgetFormElementDependence: Ad esempio

const UNIQUE_DELIMITER = '~#!~';

Quindi, modificare il metodo di partizione:

/**
 * @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;
}

Quindi, utilizzare VendorModuleBlockWidgetFormElementDependence::UNIQUE_DELIMITER nella propria classe Actions.

Per comodità, aggiungere la classe Dependence (dopo lo spazio dei nomi):

use VendorModuleBlockWidgetFormElementDependence;

E scrivere il codice in questo modo:

 // Dependency START
    /** @var MagentoBackendBlockWidgetFormElementDependence $blockDependence */
    $blockDependence = $this->getLayout()->createBlock(
    // 'MagentoBackendBlockWidgetFormElementDependence'
        '{Vendor}{Module}BlockWidgetFormElementDependence'
    );

    $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

Creare un di.xml sotto adminhtml e aggiungere il seguente codice:

Fondamentalmente è necessario sovrascrivere
Magento Backend Block Widget FormElement Dipendenza classe




namespace VendorModuleBlockWidgetFormElement;

class Dependence extends MagentoBackendBlockWidgetFormElementDependence
{
    /**
     * Register field name dependence one from each other by specified values
     *
     * @param string $fieldName
     * @param string $fieldNameFrom
     * @param MagentoConfigModelConfigStructureElementDependencyField|string $refField
     * @return MagentoBackendBlockWidgetFormElementDependence
     */
    public function addFieldDependence($fieldName, $fieldNameFrom, $refField)
    {
        if (!is_object($refField)) {
            /** @var $refField MagentoConfigModelConfigStructureElementDependencyField */
            $refField = $this->_fieldFactory->create(
                ['fieldData' => ['value' => (string)$refField, 'separator' => ','], 'fieldPrefix' => '']
            );
        }
        $this->_depends[$fieldName][$fieldNameFrom] = $refField;
        return $this;
    }
}

Ora è possibile utilizzare il seguente metodo.


->addFieldDependence(
    $childFieldTwo->getName(),
    $parentField->getName(),
    '2,4'
)

Cancellare la cache di Magento2.

Penso che dovreste guardare la classe MagentoBackendBlockWidgetFormElementDependence. Puoi creare il tuo blocco ereditato da questa classe e riscriverlo come vuoi. Nel vostro codice sostituisce la chiamata al blocco:

$this->getLayout()->createBlock(
    'MagentoBackendBlockWidgetFormElementDependence'
)

a:

this->getLayout()->createBlock(
    'SiarheyTestBlockWidgetFormElementDependence'
)

Crea il blocco SiarheyTestBlockWidgetFormElementDependence e potete implementare in esso la vostra logica di verifica.

È solo un consiglio. Spero che vi sia d'aiuto.

Ricorda qualcosa che hai il permesso di dire.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.