Magento 2 - Cara menambahkan bidang khusus ke checkout dan kemudian mengirimkannya

49

Semua tutorial hanya mencakup penambahan bidang, tetapi nilai penyimpanan dari arsip ini dilewati #mindblown. Saya tidak tahu mengapa, itu bagian paling penting dari menambahkan bidang atau formulir apa pun.

Saya mencoba mengikuti dokumen Magento , tapi ... itu menyebalkan.

Untuk tujuan pengujian saya mencoba menambahkan bidang lain ke alamat pengiriman, hanya untuk mengabaikan ruang lingkup kustom, set data kustom, penyedia data kustom dan hal-hal tidak berdokumen lainnya, yang terlihat terlalu aneh bagi saya.

Saya tidak tahu apa artinya bentuk itu "statis" atau "dinamis". Bagi saya semua formulir checkout dibuat secara dinamis di atas templat KnockoutJS, tapi ... ketika saya mencoba cara "statis", saya dapat menambahkan input di sini (jadi ini bentuk statis atau tidak?).

Pertama saya mencoba untuk men-debug mengapa Knockout yang dapat diamati mengabaikan bidang saya selama parsing dan mengirim data. Saya menemukan bahwa bidang saya memiliki nameparameter kosong , tetapi saya tidak bisa mengelola cara untuk memperbaiki masalah ini. IMO harus diteruskan ke renderer komponen UI melalui inputNameparameter, sama seperti opsi lain seperti disabled, placeholderdll. (Parameter lain berfungsi dengan baik, saya memeriksa konfigurasi yang dihasilkan dari XML saya untuk inisialisasi modul modul dan terlihat bagus untuk saya)

Kedua saya mencoba menggunakan cara "dinamis" dengan membuat plugin dengan LayoutProcessordan mengirimkan data yang persis sama ... dan sekarang saya memiliki bidang dengan names, tetapi mengirim masih tidak berfungsi sama sekali.

Setelah menggali ke dalam JS saya menemukan bahwa mempersiapkan permintaan ini disimpan dalam module-checkout/view/frontend/web/js/model/shipping-save-processor/default.jsfile, yang tergantung pada di module-checkout/view/frontend/web/js/model/quote.jsmana Knockout diamati dapat didefinisikan / dibuat.

Entah bagaimana module-checkout/view/frontend/web/js/model/address-converter.jsmemperbarui ini dapat diamati dan tergantung module-checkout/view/frontend/web/js/model/new-customer-address.js, di mana saya akhirnya menemukan beberapa opsi konfigurasi yang menarik - daftar semua bidang alamat.

Ketika saya menambahkan bidang saya di sini, skrip mulai parsing dan mengirimkannya, OFC saya mendapatkan 500, b / c backend tidak mengenalinya ... (jangan tanya, saya bukan pengembang backend)

Jadi inilah pertanyaan saya:

  • Ini cara yang tepat untuk menangani jenis penyesuaian ini? (b / c terlihat aneh bagi saya)
  • Bagaimana cara mengirim nilai bidang yang tidak terkait dengan alamat baru? Saya tidak melihat konfigurasi serupa di mana pun. Dalam kasus saya, saya ingin mengirim komentar pesanan (textarea) dan permintaan faktur (kotak centang). Keduanya tidak boleh disimpan sebagai alamat, karena beberapa pengguna mungkin ingin menyimpan alamat ini untuk digunakan di masa mendatang.
  • Apakah ada dokumentasi tentang formulir "statis" dan "dinamis" atau beberapa contoh / perbandingan? Layak untuk dipikirkan seperti ini?

Pertanyaan eksistensial tambahan:

  • Mengapa ini sangat tidak konsisten? Mengapa saya harus mendefinisikan banyak parameter dalam file XML / PHP, sementara Magento sama sekali hanya dapat membuat input dan kemudian saya harus menangani semuanya sendiri?
igloczek
sumber
3
Magento Devdocs baru-baru ini menambahkan beberapa dokumen baru tentang penggunaan Komponen UI. Kami sebenarnya sedang dalam proses menulis panduan baru ... tetapi masih memiliki cara untuk pergi. Silakan lihat di devdocs.magento.com/guides/v2.1/ui_comp_guide/bk-ui_comps.html . Sayangnya, kami belum menyelesaikan topik tentang sumber data, yang sepertinya paling Anda butuhkan. Ada topik pada aliran konfigurasi menggunakan Komponen UI, yang mungkin membantu. Saya akan berusaha mencari lebih banyak jawaban.
tanberry
Mengapa itu harus menjadi mimpi buruk menambahkan bidang sederhana di kasir? Saya tidak bisa mengerti. Dan hampir semuanya begitu sulit
slayerbleast
@slayerbleast World berubah, rendering sisi server sekarat. Jadi itu berbeda, tidak lebih sulit tanpa alasan.
igloczek

Jawaban:

55

Saya akan mencoba menjawab pertanyaan Anda.

  1. Tidak ada . Ini bukan cara yang benar untuk menambahkan atribut khusus ke formulir alamat pengiriman. Anda tidak perlu mengedit new-customer-address.js. Memang, file JS ini mencantumkan semua atribut alamat yang telah ditentukan dan cocok dengan antarmuka backend yang sesuai, \Magento\Quote\Api\Data\AddressInterfacetetapi Magento memberikan kemampuan untuk meneruskan atribut kustom apa pun ke backend tanpa modifikasi komponen backend / frontend .

    Komponen JS yang disebutkan memiliki customAttributesproperti. Atribut khusus Anda akan ditangani secara otomatis jika atributnya $dataScopePrefixadalah ' shippindAddress.custom_attributes'.

  2. Jika saya memahami pertanyaan Anda dengan benar, Anda memiliki data yang bukan bagian dari alamat pelanggan tetapi Anda harus mengirimnya ke backend juga. Jawaban untuk pertanyaan ini adalah:

    Itu tergantung . Misalnya, Anda dapat memilih pendekatan berikut: tambahkan formulir kustom ke halaman checkout yang mencakup semua bidang tambahan Anda (like comment, invoice request etc) , tambahkan logika JS yang akan menangani formulir ini berdasarkan beberapa acara, dan menyediakan layanan khusus yang akan menerima data dari frontend dan toko suatu tempat untuk digunakan di masa depan.

  3. Semua dokumentasi resmi yang terkait dengan checkout terdapat di http://devdocs.magento.com/guides/v2.1/howdoi/checkout/checkout_overview.html . Istilah statis mengacu pada formulir di mana semua bidang sudah dikenal / ditentukan sebelumnya (misalnya: formulir akan selalu memiliki 2 bidang teks dengan label yang telah ditentukan) dan tidak dapat berubah berdasarkan pada beberapa pengaturan di backend.

    Formulir seperti itu dapat dideklarasikan menggunakan layout XML configuration. Di sisi lain, istilah dinamis mengacu pada formulir yang kumpulan bidangnya dapat berubah (misalnya: formulir checkout dapat memiliki lebih banyak atau lebih sedikit bidang berdasarkan pengaturan konfigurasi).

    Dalam hal ini satu-satunya cara untuk mendeklarasikan formulir tersebut adalah dengan menggunakan LayoutProcessorplugin.

  4. :) Magento mencoba untuk mencakup sebanyak mungkin kasus penggunaan yang dapat signifikan bagi pedagang selama penggunaan / penyesuaian Magento mungkin. Terkadang ini mengarah ke situasi ketika beberapa kasus penggunaan sederhana menjadi lebih kompleks.

Semoga ini membantu.

================================================== =======================

OKE ... Mari kita menulis beberapa kode;)

  1. Kode PHP yang memasukkan bidang tambahan dalam LayoutProcessor

========

/**
 * @author aakimov
 */
$customAttributeCode = 'custom_field';
$customField = [
    'component' => 'Magento_Ui/js/form/element/abstract',
    'config' => [
        // customScope is used to group elements within a single form (e.g. they can be validated separately)
        'customScope' => 'shippingAddress.custom_attributes',
        'customEntry' => null,
        'template' => 'ui/form/field',
        'elementTmpl' => 'ui/form/element/input',
        'tooltip' => [
            'description' => 'Yes, this works. I tested it. Sacrificed my lunch break but verified this approach.',
        ],
    ],
    'dataScope' => 'shippingAddress.custom_attributes' . '.' . $customAttributeCode,
    'label' => 'Custom Attribute',
    'provider' => 'checkoutProvider',
    'sortOrder' => 0,
    'validation' => [
       'required-entry' => true
    ],
    'options' => [],
    'filterBy' => null,
    'customEntry' => null,
    'visible' => true,
];

$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children'][$customAttributeCode] = $customField;

return $jsLayout;

Seperti yang telah saya sebutkan, ini akan menambahkan bidang Anda ke customAttributesproperti objek alamat JS. Properti ini dirancang untuk mengandung atribut alamat EAV khusus dan terkait dengan \Magento\Quote\Model\Quote\Address\CustomAttributeListInterface::getAttributesmetode.

Kode di atas akan secara otomatis menangani persistensi penyimpanan lokal di frontend. Anda bisa mendapatkan nilai bidang Anda dari penyimpanan lokal menggunakan checkoutData.getShippingAddressFromData()(di mana checkoutDataadalah Magento_Checkout/js/checkout-data).

  1. Tambahkan mixin untuk mengubah perilaku 'Magento_Checkout / js / action / set-shipping-informasi' (komponen ini bertanggung jawab untuk pengiriman data antara pengiriman dan langkah-langkah checkout checkout)

========

2.1. Membuatyour_module_name/view/frontend/requirejs-config.js


/**
 * @author aakimov
 */
var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/action/set-shipping-information': {
                '<your_module_name>/js/action/set-shipping-information-mixin': true
            }
        }
    }
};

2.2. Buat your_module_name / view / frontend / web / js / action / set-shipping-information-mixin.js


/**
 * @author aakimov
 */
/*jshint browser:true jquery:true*/
/*global alert*/
define([
    'jquery',
    'mage/utils/wrapper',
    'Magento_Checkout/js/model/quote'
], function ($, wrapper, quote) {
    'use strict';

    return function (setShippingInformationAction) {

        return wrapper.wrap(setShippingInformationAction, function (originalAction) {
            var shippingAddress = quote.shippingAddress();
            if (shippingAddress['extension_attributes'] === undefined) {
                shippingAddress['extension_attributes'] = {};
            }

            // you can extract value of extension attribute from any place (in this example I use customAttributes approach)
            shippingAddress['extension_attributes']['custom_field'] = shippingAddress.customAttributes['custom_field'];
            // pass execution to original action ('Magento_Checkout/js/action/set-shipping-information')
            return originalAction();
        });
    };
});
  1. Buat your_module_name / etc / extension_attributes.xml

========

<?xml version="1.0"?>
<!--
/**
 * @author aakimov
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Quote\Api\Data\AddressInterface">
        <attribute code="custom_field" type="string" />
    </extension_attributes>
</config>

Ini akan menambahkan atribut ekstensi ke model alamat di sisi backend. Atribut ekstensi adalah salah satu poin ekstensi yang disediakan Magento. Untuk mengakses data Anda di backend Anda dapat menggunakan:

// Magento will generate interface that includes your custom attribute
$value = $address->getExtensionAttributes()->getCustomField();

Semoga, ini membantu dan akan ditambahkan ke dokumentasi resmi.

aakimov
sumber
Terima kasih atas jawaban Alex! Saya mencoba custom_attributescara, tetapi tidak berhasil bagi saya. Ini adalah bagaimana bagian dari LayoutProcessor.php` terlihat seperti - gist.github.com/Igloczek/eaf4d2d7a0a04bd950110296ec3f7727 Tapi shipping-info atau bahkan localStorage checkout-datatidak mengandung data ini sama sekali.
igloczek
Silakan lihat jawaban saya yang diperbarui di atas;)
aakimov
4
Dokumen resmi tentang topik ini sudah tersedia! devdocs.magento.com/guides/v2.1/howdoi/checkout/…
Alex
1
Apakah ada langkah tambahan yang diperlukan untuk menyimpan nilai-nilai terhadap pesanan?
Alex Hadley
Saya pikir jika Anda memiliki bentuk statis, lebih baik memasukkan bidang ke LayoutProcessor via XML seperti dalam contoh ini: devdocs.magento.com/guides/v2.1/howdoi/checkout/…
cjohansson
-1

Dalam pengalaman saya, m2 menggunakan xml untuk mendefinisikan komponen seperti bidang dll. Ini membantu untuk debugging, interaktif dengan data lebih mudah. Pada bidang front-ender Anda harus mencoba untuk mengganti template checkout dan menambahkan bidang kustom Anda sendiri di sana. Dengan KO membantu Anda kemampuan untuk bekerja dan mengikat data dari frontend dan backend

mrtuvn
sumber
4
Itu saran yang salah, template checkout b / c tidak mengandung dan tidak boleh mengandung kolom input yang ditambahkan secara manual. Kita harus menggunakan KO untuk merender template di wilayah tertentu (semuanya dibangun menggunakan komponen UI)
igloczek
Bisakah Anda membagikan contoh menambahkan ui-komponen bidang kustom di frontend?
mrtuvn
Seperti @igloczek mengatakan Ini saran yang salah, karena template checkout tidak boleh mengandung kolom input yang ditambahkan secara manual.
diazwatson