Magento 2.1 Form bileşeni alanı özel başka bir alan değerine bağlıdır nasıl oluştururum?


13

Bazı seçenekleri olan bir alan seçin var. Bunlardan birinde değere bağlı bazı alanlar olacak, başka bir alan gizlenecektir. Alanım için bileşen js kopyalayıp genişlettik ama işe yaramadı ya da yanlış bir şekilde yaptım. Kullanıcı arabirimi bileşeni bu özelliği destekliyor mu? Bunu nasıl başarabilirim?

Aşağıda yaptığım şey:

<field name="field1">
    <argument name="data" xsi:type="array">
        <item name="options" xsi:type="object">Namespace\ModuleName\Model\Config\Source\Options</item>
        <item name="config" xsi:type="array">
            <item name="label" xsi:type="string" translate="true">Field name</item>
            <item name="visible" xsi:type="boolean">true</item>
            <item name="dataType" xsi:type="string">number</item>
            <item name="formElement" xsi:type="string">select</item>
            <item name="source" xsi:type="string">item</item>
            <item name="dataScope" xsi:type="string">field1</item>
            <item name="component" xsi:type="string">Pathto/js/form/element/options</item>
            <item name="validation" xsi:type="array">
                <item name="required-entry" xsi:type="boolean">true</item>
            </item>
        </item>
    </argument>
</field>

<field name="field2Depend1"></field>
<field name="field3Depend1"></field>

js Bileşen js/form/element/options:

define([
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select',
    'Magento_Ui/js/modal/modal'
], function (_, uiRegistry, select) {
    'use strict';

    return select.extend({

        onChange: function () {
            this.enableDisableFields();
        },

        /**
         * Enable/disable fields on Coupons tab
         */
        enableDisableFields: function () {
            // code check field
        }
    });
});

Yanıtlar:


26

Bunu deneyin ( Not : "Ad Alanı" satırını ve "ModülAdı" satırını değerlerinizle değiştirmeyi unutmayın):

<field name="field1">
    <argument name="data" xsi:type="array">
        <item name="options" xsi:type="object">Namespace\ModuleName\Model\Config\Source\Options</item>
        <item name="config" xsi:type="array">
            <item name="label" xsi:type="string" translate="true">Parent Option</item>
            <item name="component" xsi:type="string">Namespace_ModuleName/js/form/element/options</item>
            <item name="visible" xsi:type="boolean">true</item>
            <item name="dataType" xsi:type="string">number</item>
            <item name="formElement" xsi:type="string">select</item>
            <item name="source" xsi:type="string">item</item>
            <item name="dataScope" xsi:type="string">field1</item>
            <item name="sortOrder" xsi:type="number">210</item>
            <item name="validation" xsi:type="array">
                <item name="required-entry" xsi:type="boolean">true</item>
            </item>
        </item>
    </argument>
</field>

<field name="field2Depend1">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="label" xsi:type="string">Field 1</item>
            <item name="dataType" xsi:type="string">text</item>
            <item name="formElement" xsi:type="string">input</item>
            <item name="source" xsi:type="string">item</item>
            <item name="sortOrder" xsi:type="number">220</item>
            <item name="breakLine" xsi:type="boolean">true</item>
            <item name="visibleValue" xsi:type="string">2</item>
            <item name="visible" xsi:type="boolean">false</item>
        </item>
    </argument>
</field>
<field name="field3Depend1">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="label" xsi:type="string">Field 2</item>
            <item name="dataType" xsi:type="string">text</item>
            <item name="formElement" xsi:type="string">input</item>
            <item name="source" xsi:type="string">item</item>
            <item name="sortOrder" xsi:type="number">230</item>
            <item name="breakLine" xsi:type="boolean">true</item>
            <item name="visibleValue" xsi:type="string">0</item>
            <item name="visible" xsi:type="boolean">false</item>
        </item>
    </argument>
</field>

Nerede:

  • Alt öğelerin görünürlüğü varsayılan olarak false;
  • visibleValue- bir field1elemanı görünür olmalıdır değeri;

Ad alanı \ modulename \ Modeli \ Config \ Source \ Seçenekler

namespace Namespace\ModuleName\Model\Config\Source;

use Magento\Framework\Option\ArrayInterface;

class Options implements ArrayInterface
{
    /**
     * @return array
     */
    public function toOptionArray()
    {
        $options = [
            0 => [
                'label' => 'Please select',
                'value' => 0
            ],
            1 => [
                'label' => 'Option 1',
                'value' => 1
            ],
            2  => [
                'label' => 'Option 2',
                'value' => 2
            ],
            3 => [
                'label' => 'Option 3',
                'value' => 3
            ],
        ];

        return $options;
    }
}

Uygulama / kod / Ad / modül ismi / görünüşüdür / adminhtml / ağ / js / form / eleman / options.js

define([
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select',
    'Magento_Ui/js/modal/modal'
], function (_, uiRegistry, select, modal) {
    'use strict';

    return select.extend({

        /**
         * On value change handler.
         *
         * @param {String} value
         */
        onUpdate: function (value) {
            console.log('Selected Value: ' + value);

            var field1 = uiRegistry.get('index = field2Depend1');
            if (field1.visibleValue == value) {
                field1.show();
            } else {
                field1.hide();
            }

            var field2 = uiRegistry.get('index = field3Depend1');
            if (field2.visibleValue == value) {
                field2.show();
            } else {
                field2.hide();
            }

            return this._super();
        },
    });
});

Sonuç:

Değer 0 seçildi: Değer 0 seçildi

Değer 1 seçildi: Değer 1 seçildi

Değer 2 seçildi: Değer 2 seçildi

Değer 3 seçildi: Değer 3 seçildi

PS: Muhtemelen en iyi çözüm değil, ama size yardımcı olacaktır


onUpdate iyi çalışıyor, ancak onLoad nasıl yapılır? Field1.value nasıl edinilir?
zhartaunik

@zhartaunik initializeui-element'in herhangi bir onLoadyöntemi olmadığı için, sizin durumunuzda yöntemi kullanmanız gerektiğini düşünüyorum . Sen girdi endeksi tuşunu kullanarak kayıt defterinden herhangi bir yerde herhangi bir alan değeri elde edebilirsiniz: uiRegistry.get('index = field1'). Daha fazla sorunuz varsa, lütfen bana skype (sarj1989) adresinden ulaşın, Rusça iletişim kurmak daha kolay olacaktır.
Siarhey Uchukhlebau

Teşekkürler @Siarhey. Başlatma işlevini kullanmaya karar verdim. this._super, gerekli doğrulamayı ekleyin.
zhartaunik

1
Başlatma yöntemi değeri "tanımsız" kullanırken alan değeri alamıyorum.
Saurabh Taletiya

1
@Siarhey Uchukhlebau Bunun yerine onay kutusu ekleyebilir miyim?
Juliano Vargas

9

Magentix tarafından önerilen çözüm, başlatmayı kullanırken zaman zaman bir hata verecektir. Tarayıcınızın bileşenleri oluşturması için geçen süreye bağlıdır. Düzeltmek için setTimeout kullanabilirsiniz.

Aşağıdaki koda bakın:

define([
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select',
    'Magento_Ui/js/modal/modal'
], function (_, uiRegistry, select, modal) {
    'use strict';

    return select.extend({

        /**
         * Extends instance with defaults, extends config with formatted values
         *     and options, and invokes initialize method of AbstractElement class.
         *     If instance's 'customEntry' property is set to true, calls 'initInput'
         */
        initialize: function () {
            this._super();

            this.resetVisibility();

            return this;
        },

        toggleVisibilityOnRender: function (visibility, time) {
            var field = uiRegistry.get('index = field_to_toggle');
            if(field !== undefined) {
                if(visibility == 1) {
                    field.show();
                } else {
                    field.hide();
                }

                return;
            }
            else {
                var self = this;
                setTimeout(function() {
                    self.toggleVisibilityOnRender(visibility, time);
                }, time);
            }
        },

        /**
         * On value change handler.
         *
         * @param {String} value
         */
        onUpdate: function (value) {
            if (value == 1) {
                this.showField();
            } else {
                this.hideField();
            }
            return this._super();
        },

        resetVisibility: function () {
            if (this.value() == 1) {
                this.showField();
            } else {
                this.hideField();
            }
        },

        showField: function () {
            this.toggleVisibilityOnRender(1, 1000);

        },

        hideField: function () {
            this.toggleVisibilityOnRender(0, 1000);
        }
    });
});

Düzgün çalışıyor.
Dhaduk Mitesh

Yanımda +1. Başka işler değil ama bu benim işimi yaptı.
anonim

7

Bu, işe yarayan birden fazla yanıtı olan eski bir sorudur, ancak Magento'nun bileşenlerini genişletmeye gerek kalmadan (2.1.0'dan itibaren) sağladığı şeyi kullanarak bir çözüm keşfettim. Birden fazla soru yinelenen ve burada yönlendirildiği için, bu seçenek hakkında bazı bilgiler vermenin yararlı olacağını düşündüm.

Uzatmak Tüm form elemanı ui bileşenleri Magento_Ui/js/form/element/abstract.jsbir var switcherConfigelemanlarının yanı sıra diğer eylemleri gösteren / böyle gizleme gibi amaçlar için ayar mevcut. switcherBileşen bulunabilir Magento_Ui / js / form / değiştiricinin merak için. Bunun satışlarını sales_rule_form.xml ve catalog_rule_form.xml dosyalarında bulabilirsiniz . Tabii ki kendi özel bileşeninizi zaten kullanıyorsanız, bileşeniniz sonunda abstractsoruda verilen örnek koda dayalı olarak görünen durumda olduğu sürece bunu yine de kullanabilirsiniz .

Şimdi orijinal soruyu cevaplamak için daha spesifik bir örnek.

İçinde Namespace/ModuleName/view/adminhtml/ui_component/your_entity_form.xmlsadece settingskontrol yapan alanlara (yani hangi alanların gizli / görünür olduğunu belirleyen alan) aşağıdakileri eklemeniz yeterlidir . Örneğinizde bu olurdu field1.

<field name="field1">
    <argument name="data" xsi:type="array">
        ...
    </argument>
    <settings>
        <switcherConfig>
            <rules>
                <rule name="0">
                    <value>2</value>
                    <actions>
                        <action name="0">
                            <target>your_entity_form.your_entity_form.entity_information.field2Depend1</target>
                            <callback>show</callback>
                        </action>
                        <action name="1">
                            <target>your_entity_form.your_entity_form.entity_information.field3Depend1</target>
                            <callback>hide</callback>
                        </action>
                    </actions>
                </rule>
                <rule name="1">
                    <value>3</value>
                    <actions>
                        <action name="0">
                            <target>your_entity_form.your_entity_form.entity_information.field2Depend1</target>
                            <callback>hide</callback>
                        </action>
                        <action name="1">
                            <target>your_entity_form.your_entity_form.entity_information.field3Depend1</target>
                            <callback>show</callback>
                        </action>
                    </actions>
                </rule>
            </rules>
            <enabled>true</enabled>
        </switcherConfig>
    </settings>
</field>

Biraz parçalayalım. switcherBileşen dizisi içeriyor rulesbiz burada yapıyolar şeydir. Her <rule>birinin bu örnekte bir sayı olan bir adı vardır. Bu ad, bu öğenin dizi anahtarı / dizinidir. Sayıları dizi dizini olarak kullanıyoruz. Dizeler de çalışmalı ama bu teoriyi test etmedim . GÜNCELLEME - @ChristopheFerreboeuf tarafından yorumlarda belirtildiği gibi, burada çalışmayan dizeler. Bunlar dizilerdir ve 0dizelerle veya 1 ile başlamalıdır .

Her birinin içinde ruleiki argüman geçiyoruz.

  1. value- Bu, aşağıda tanımlanan değeri field1tetiklemesi gereken değerdir actions.
  2. actions- Burada başka bir dizimiz var. Bunlar, bu kuralın koşulları yerine getirildiğinde tetiklenecek eylemlerdir. Yine, her birinin actionadı yalnızca o öğenin dizi dizini / anahtarıdır.

Şimdi her ikisinin actionde iki argümanı var (isteğe bağlı 3.).

  1. target- Bu, bu eylem altında manipüle etmek istediğiniz unsurdur. Magento'da ui_component eleman adlarının nasıl oluşturulduğunu bilmiyorsanız Alan Storm'un makalesine göz atabilirsiniz . Temel {component_name}.{component_name}.{fieldset_name}.{field_name}olarak bu örnekteki gibi bir şey .
  2. callback- Yukarıda belirtilenler için yapılacak işlem target. Bu geri arama, hedeflenen öğede bulunan bir işlev olmalıdır. Örneğimiz hideve kullanır show. Bu, kullanılabilir işlevselliği genişletmeye başlayabileceğiniz yerdir. Daha catalog_rule_form.xmlönce bahsettiğim setValidationörnek, farklı bir örnek görmek istiyorsanız kullanır .
  3. Bunları <params>gerektiren herhangi birine de ekleyebilirsiniz action. Bunu catalog_rule_form.xmlörnekte de görebilirsiniz.

Nihayet son öğe içeride switcherConfigolduğunu <enabled>true</enabled>. Bu oldukça basit olmalı, yeni uyguladığımız değiştirici işlevini etkinleştirmek / devre dışı bırakmak için bir Boole.

Ve işimiz bitti. Gördüğünüz gereken yukarıdaki örneği kullanarak alandır field2Depend1Eğer değerle bir seçenek belirleyin görüntülenir 2üzerinde field1ve field3Depend1sen değerle bir seçenek belirleyin görüntülenir 3.

Bu örneği sadece hideve showgerekli bir alanda kullanarak test ettim ve doğrulama için görünürlüğü dikkate alıyor gibi görünüyor. Başka bir deyişle, gerekirse field2Depend1yalnızca görünür olduğunda gereklidir. Bunun çalışması için daha fazla yapılandırmaya gerek yoktur.

Umarım bu daha hazır bir çözüm arayan herkes için biraz yardım sağlar.


1
"Dizeler de çalışmalı ama ben bu teoriyi test etmedim." Yanlışlıkla test ve değil ... Eylemler eylem 0 veya kural 0 değil 1 veya bir dize ile başlamak için gereken kurallar dizisi olarak ...
Christophe Ferreboeuf

6

Bu soru için birçok cevap var, ancak çoğu uiRegistry'nin tamamen yüklü olup olmadığı konusunda varsayımlar yapar veya setTimeoutçağrı yığınını temizlemek için kullanır ve bir sonraki olay döngüsünü bekler (ki bence hala yanlış yol budur) Diğer UI bileşenlerinin ne zaman yüklendiğinden emin olamayacağınız için - yanlışsam beni düzeltin).

İlk olarak, elbette, özel JS bileşeninizi alan yapılandırmasına ekleyin (ayrıntılar için diğer yanıtlara bakın):

<item name="component" xsi:type="string">Namespace_ModuleName/js/form/element/options</item>

Ardından, bağımlı alanları gizleyen veya gösteren özel UI bileşeni - neler olduğunu açıklayan yorumlarla birlikte.

define([
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select'
], function (_, uiRegistry, select) {

    'use strict';

    return select.extend({

        /**
         * Array of field names that depend on the value of 
         * this UI component.
         */
        dependentFieldNames: [
            'my_field_name1',
            'my_field_name2'
        ],

        /**
         * Reference storage for dependent fields. We're caching this
         * because we don't want to query the UI registry so often.
         */
        dependentFields : [],

        /**
         * Initialize field component, and store a reference to the dependent fields.
         */
        initialize: function() {
            this._super();

            // We're creating a promise that resolves when we're sure that all our dependent
            // UI components have been loaded. We're also binding our callback because
            // we're making use of `this`
            uiRegistry.promise(this.dependentFieldNames).done(_.bind(function() {

                // Let's store the arguments (the UI Components we queried for) in our object
                this.dependentFields = arguments;

                // Set the initial visibility of our fields.
                this.processDependentFieldVisibility(parseInt(this.initialValue));
            }, this));
        },

        /**
         * On value change handler.
         *
         * @param {String} value
         */
        onUpdate: function (value) {
            // We're calling parseInt, because in JS "0" evaluates to True
            this.processDependentFieldVisibility(parseInt(value));
            return this._super();
        },

        /**
         * Shows or hides dependent fields.
         *
         * @param visibility
         */
        processDependentFieldVisibility: function (visibility) {
            var method = 'hide';
            if (visibility) {
                method = 'show';
            }

            // Underscore's invoke, calls the passed method on all the objects in our array
            _.invoke(this.dependentFields, method);
        }
    });
});

5

Field is UndefinedAlan görünürlüğünü başlatırken yaptığınız gibi bir hatayla karşılaşırsanız setTimeout(), bağlı alanları yüklemek için kullanın :

fieldDepend: function (value) {
     setTimeout(function(){ 
        var field1 = uiRegistry.get('index = field2');

        if (field1.visibleValue == value) {
               field1.show();
        } else {
               field1.hide();
        }

       var field2 = uiRegistry.get('index = field3');

        if (field2.visibleValue == value) {
              field2.show();
        } else {
              field2.hide();
        }    
     }, 1);
     return this._super();
},

SetTimeout yerine, bağımlılıkları elde etmek için eşzamansız yöntemi kullanın:uiRegistry.get('q', function(field) { ... }));
Erfan

Yorumda öneride bulunma ve cevabımı aşağı oylama yazabilirsiniz Cevabınızı buraya gönderebilirsiniz kardeşim, Bu herhangi bir cevabı ayırmanın yolu değil, Sadece farklı bir yol öneriyorsunuz, cevabım yanlış değil. @Erfan. aşağı oyunuz yanlış bir izlenim bırakıyor.
Ronak Chauhan

@RonakChauhan - Nokta üzerinde anlaştı !!! cevabınız yanlış değil, farklı insanlar farklı fikir, öneri ve çözümlere sahiptir. Cevabınız da doğru !!
Manthan Dave

Başlamak için bir saniye beklemek ve başlatmayı engellemek, bunu yapmanın yanlış yoludur. Bağımlılıklarınızın bir saniyede yükleneceğini nasıl anlarsınız? Neden iki saniye olmayacak? Burada bir varsayımda bulunuyorsunuz, bundan kaçınılmalıdır.
Erfan

Burada 1 saniye ayarlamadı, Milisaniye, SetTimeout () sadece sayfa yükledikten sonra kodumu yükleyecek Ve eğer cevabınız varsa o zaman gönderebilirsiniz. Birinin cevabını aşağı çekmek, kendinizi kanıtlamanın bir yolu değildir! @Erfan
Ronak Chauhan

2

İnit özel bileşeni:

define([
    'underscore',
    'uiRegistry',
    'Magento_Ui/js/form/element/select',
    'Magento_Ui/js/modal/modal'
], function (_, uiRegistry, select, modal) {
    'use strict';

    return select.extend({

        /**
         * Init
         */
        initialize: function () {
            this._super();

            this.fieldDepend(this.value());

            return this;
        },

        /**
         * On value change handler.
         *
         * @param {String} value
         */
        onUpdate: function (value) {
            this.fieldDepend(value);

            return this._super();
        },

        /**
         * Update field dependency
         *
         * @param {String} value
         */
        fieldDepend: function (value) {
            var field = uiRegistry.get('index = field_to_toggle');

            if (value == 'xxxxx') {
                field.show();
            } else {
                field.hide();
            }

            return this;
        }
    });
});

başlat işlevini kullandıktan sonra "alan tanımsız" olduğunu gösterir.
Prens Patel

1
Kullanım setTimeout()içinde fieldDepend()bağımlı bir henüz yüklenmemesi nedeniyle.
Ronak Chauhan

2

Alan bağımlılıklarını işlemenin birkaç yolu vardır, basit Evet / Hayır açılır menüsü, bir onay kutusu veya bir anahtarlayıcı için Magento 2'deki özellikleri importsveya exportsbağlantı özelliklerini kullanabilirsiniz . Çözüm burada ayrıntılı olarak açıklanmıştır: Magento'daki UI bileşen formlarındaki bağımlı alanlar Boole alanları için Javascript içermeyen 2 :

<!-- In the parent field <settings>...</settings> -->
<exports>
    <link name="checked">${$.parentName}.description:disabled</link>
</exports>

<!-- or -->

<!-- In the dependent field <settings>...</settings> -->
<imports>
    <link name="disabled">${$.parentName}.is_active:checked</link>
</imports>

Bir açılır menüdeki değer listesine bağımlılık gibi bir tür değer türünü işlemek için veya olası olmasa da, bir girdi alanının değerini kullanmak için switcherConfig. Bilgi için Magento 2'deki ui-bileşen formlarındaki Bağımlı alanları kontrol edin .

<switcherConfig>
    <rules>
        <rule name="0">
            <value>list</value><!-- Actions defined will be trigger when the current selected field value matches the value defined here-->
            <actions>
                <action name="0">
                    <target>hs_xml_dependentfield_model_form.hs_xml_dependentfield_model_form.general.list</target>
                    <callback>visible</callback>
                    <params>
                        <param name="0" xsi:type="boolean">true</param>
                    </params>
                </action>
                <action name="1">
                    <target>hs_xml_dependentfield_model_form.hs_xml_dependentfield_model_form.general.hex_code</target>
                    <callback>visible</callback>
                    <params>
                        <param name="0" xsi:type="boolean">true</param>
                    </params>
                </action>
            </actions>
        </rule>
        ...
    </rules>
    <enabled>true</enabled>
</switcherConfig>

Yukarıdaki 2 kural, XML config kullanarak hemen hemen her şeyi halleder. Daha karmaşık kurallar için JavaScript'i de kullanabilirsiniz.

Kullanıcı arabirimi bileşen formundaki her alan, için componentöznitelik kullanılarak genişletilebilen bir bileşendir <field component="path to your js" ...>...</field>. Daha sonra alanı data.config, bileşenin genel olması ve değerleri gözlemlenebilir veya yöntemlere iletmek için importsveya exportsbağlama özelliği ile birlikte kullanılması durumunda, bileşene daha fazla bilgi iletmek için kullanabilirsiniz .

Bağlantı özellikleri hakkında daha fazla bilgi için UI bileşenlerinin bağlantı özelliklerini kontrol edebilirsiniz .


1

Birisinin Erfan çözümü ile mücadele etmesi durumunda , aşağıdaki alanlara giden tam yolu geçmeniz gerekir dependentFieldNames, örneğin:

       dependentFieldNames: [
        'form_name.form_name.fieldset.field_name',
        'form_name.form_name.fieldset.field_name1',
        'form_name.form_name.fieldset.field_name2',
        'form_name.form_name.fieldset.field_name3'
    ],

Form_name'in neden 2 kez olması gerektiğinden emin değilim, ama bu benim için çalıştı.

Bu ben put hata ayıklamak için console.log(query);de static/adminhtml/Magento/backend/en_US/Magento_Ui/js/lib/registry/registry.js(hemen önce get () işlevi 223 hattı this._addRequest(query, callback))

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.