Magento 2 - Jak dodać niestandardowe pole do kasy, a następnie wysłać je

49

Wszystkie samouczki obejmują tylko dodawanie pól, ale zapisywanie wartości tych pól jest pomijane #mindblown. Nie wiem dlaczego, to najważniejsza część dodawania dowolnego pola lub formularza.

Próbowałem śledzić dokumenty Magento , ale ... to jest do bani.

Do celów testowych próbuję dodać kolejne pola do adresu wysyłki, aby zignorować niestandardowe zakresy, niestandardowe zestawy danych, niestandardowych dostawców danych i inne nieudokumentowane rzeczy, co wydaje mi się zbyt dziwne.

Nie mam pojęcia, co oznacza, że ​​ta forma jest „statyczna” lub „dynamiczna”. Dla mnie wszystkie formularze płatności są budowane dynamicznie na szablonach KnockoutJS, ale ... kiedy próbuję „statycznie”, mogę tutaj dodawać dane wejściowe (więc jest to forma statyczna, czy nie?).

Najpierw próbuję debugować, dlaczego obserwowalne Knockout po prostu ignorują moje pola podczas analizowania i wysyłania danych. Odkryłem, że moje pola mają pusty nameparametr, ale nie mogę znaleźć sposobu, aby rozwiązać ten problem. IMO powinno być przekazane do interfejsu komponentu renderowania poprzez inputNameparametr, tak samo jak wszelkie inne opcje jak disabled, placeholderitd. (Inne parametry działa dobrze, sprawdziłem konfigurację generowane z mojego XML do kasy Moduł inicjalizacji i wygląda dobrze dla mnie)

Po drugie próbowałem użyć „dynamicznego” sposobu tworzenia wtyczki LayoutProcessori przekazywania dokładnie tych samych danych ... a teraz mam pola z names, ale wysyłanie wciąż nie działa.

Po wkopaniu w JS odkryłem, że przygotowanie tego żądania jest przechowywane w module-checkout/view/frontend/web/js/model/shipping-save-processor/default.jspliku, co zależy od tego, module-checkout/view/frontend/web/js/model/quote.jsgdzie są definiowane / tworzone obserwowalne Knockout.

Jakoś module-checkout/view/frontend/web/js/model/address-converter.jszaktualizuj to obserwowalne i zależy od tego module-checkout/view/frontend/web/js/model/new-customer-address.js, gdzie w końcu znalazłem ciekawe opcje konfiguracji - listę wszystkich pól adresowych.

Kiedy dodam tutaj moje pola, skrypty zaczynają parsować i wysyłać je, OFC dostaję 500, backend b / c ich nie rozpoznaje ... (nie pytaj, nie jestem devenderem)

Oto moje pytania:

  • Czy to odpowiedni sposób na obsługę tego rodzaju dostosowań? (b / c wygląda dziwnie dla mnie)
  • Jak wysłać wartości pól niezwiązanych z nowymi adresami? Nigdzie nie widziałem podobnej konfiguracji. W moim przypadku chciałbym wysłać komentarz do zamówienia (pole tekstowe) i żądanie faktury (pole wyboru). Oba nie powinny być zapisywane jako adres, b / c niektórzy użytkownicy mogą chcieć zapisać ten adres do wykorzystania w przyszłości.
  • Czy istnieje dokumentacja dotycząca formularzy „statycznych” i „dynamicznych” lub niektórych przykładów / porównań? Warto o tym myśleć w ten sposób?

Dodatkowe pytanie egzystencjalne:

  • Dlaczego to jest tak niespójne? Dlaczego muszę zdefiniować tony parametrów w plikach XML / PHP, podczas gdy Magento w ogóle może tylko renderować dane wejściowe, a następnie muszę samodzielnie wszystko obsłużyć?
igloczek
źródło
3
Magento Devdocs dodał ostatnio nowe dokumenty dotyczące korzystania ze składników interfejsu użytkownika. Jesteśmy w trakcie pisania całego nowego przewodnika ... ale wciąż mamy przed sobą wiele do zrobienia. Proszę spojrzeć na devdocs.magento.com/guides/v2.1/ui_comp_guide/bk-ui_comps.html . Niestety, nie ukończyliśmy jeszcze tematów na temat źródeł danych, co wydaje się, że najbardziej potrzebujesz. Istnieje temat dotyczący przepływu konfiguracji przy użyciu składników interfejsu użytkownika, który może pomóc. Popracuję nad znalezieniem kolejnych odpowiedzi.
tanberry
Dlaczego to musi być koszmar, dodając proste pole przy kasie? Po prostu nie rozumiem. I prawie wszystko jest tak trudne
slayerbleast
@slayerbleast World się zmienia, renderowanie po stronie serwera umiera. Więc jest inaczej, nie trudniej bez żadnego powodu.
igloczek

Odpowiedzi:

55

Spróbuję odpowiedzieć na twoje pytanie / pytania.

  1. Nie . To nie jest poprawny sposób dodawania niestandardowych atrybutów do formularza adresu wysyłki. Nie musisz edytować new-customer-address.js. Rzeczywiście, ten plik JS zawiera wszystkie predefiniowane atrybuty adresu i odpowiada odpowiadającemu interfejsowi backendu, \Magento\Quote\Api\Data\AddressInterfaceale Magento zapewnia możliwość przekazywania dowolnych niestandardowych atrybutów do backendu bez modyfikacji komponentów backend / frontendu .

    Wspomniany komponent JS ma customAttributeswłaściwość. Twoje niestandardowe atrybuty zostaną automatycznie obsłużone, jeśli $dataScopePrefixmają wartość „ shippindAddress.custom_attributes”.

  2. Jeśli poprawnie zrozumiałem twoje pytanie, masz dane, które nie są częścią adresu klienta, ale musisz wysłać je również do zaplecza. Odpowiedź na to pytanie brzmi:

    To zależy . Na przykład możesz wybrać następujące podejście: dodaj niestandardowy formularz do strony kasy, który zawiera wszystkie dodatkowe pola (like comment, invoice request etc) , dodaj logikę JS, która będzie obsługiwać ten formularz w oparciu o niektóre zdarzenia, i zapewni niestandardową usługę, która odbierze dane z interfejsu użytkownika i sklepu gdzieś do wykorzystania w przyszłości.

  3. Cała oficjalna dokumentacja związana z kasą znajduje się na stronie http://devdocs.magento.com/guides/v2.1/howdoi/checkout/checkout_overview.html . Termin statyczny odnosi się do formularzy, w których wszystkie pola są już znane / predefiniowane (na przykład: formularz zawsze będzie zawierał 2 pola tekstowe ze wstępnie zdefiniowanymi etykietami) i nie może się zmienić w zależności od niektórych ustawień w backendu.

    Takie formularze można zadeklarować za pomocą layout XML configuration. Z drugiej strony termin dynamiczny odnosi się do formularzy, których zestaw pól może ulec zmianie (na przykład: formularz zamówienia może mieć więcej / mniej pól w zależności od ustawień konfiguracji).

    W takim przypadku jedynym sposobem na zadeklarowanie takiej formy jest użycie LayoutProcessorwtyczki.

  4. :) Magento stara się objąć jak najwięcej przypadków użycia, które mogą być znaczące dla handlowców podczas korzystania / dostosowywania Magento. Czasami prowadzi to do sytuacji, gdy niektóre proste przypadki użycia stają się bardziej złożone.

Mam nadzieję że to pomoże.

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

OK ... Napiszmy kod;)

  1. Kod PHP, który wstawia dodatkowe pole w 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;

Jak już wspomniałem, doda to twoje pole do customAttributeswłaściwości obiektu adresu JS. Ta właściwość została zaprojektowana tak, aby zawierała niestandardowe atrybuty adresu EAV i jest związana z \Magento\Quote\Model\Quote\Address\CustomAttributeListInterface::getAttributesmetodą.

Powyższy kod automatycznie obsłuży lokalną trwałość pamięci w interfejsie użytkownika. Możesz uzyskać wartość pola z pamięci lokalnej za pomocą checkoutData.getShippingAddressFromData()(gdzie checkoutDatajest Magento_Checkout/js/checkout-data).

  1. Dodaj mixin, aby zmienić zachowanie „Magento_Checkout / js / action / set-shipping-information” (ten komponent jest odpowiedzialny za przesyłanie danych między etapem wysyłki a rozliczeniem)

========

2.1 Stwórzyour_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 Utwórz swoją nazwę modułu / 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. Utwórz swoją nazwę_modułu / 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>

Spowoduje to dodanie atrybutu rozszerzenia do modelu adresu po stronie zaplecza. Atrybuty rozszerzenia są jednym z punktów rozszerzenia, które zapewnia Magento. Aby uzyskać dostęp do swoich danych na zapleczu, możesz użyć:

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

Mam nadzieję, że to pomaga i zostanie dodane do oficjalnej dokumentacji.

aakimov
źródło
Dzięki za odpowiedź Alex! Próbowałem custom_attributessposób, ale to nie działa dla mnie. Tak wygląda część LayoutProcessor.php` - gist.github.com/Igloczek/eaf4d2d7a0a04bd950110296ec3f7727 Ale shipping-info nawet localStorage w checkout-dataogóle nie zawiera tych danych.
igloczek
Zobacz moją zaktualizowaną odpowiedź powyżej;)
aakimov
4
Oficjalny dokument na ten temat jest już dostępny! devdocs.magento.com/guides/v2.1/howdoi/checkout/…
Alex
1
Czy potrzebny jest dodatkowy krok, aby zapisać wartości w stosunku do zamówienia?
Alex Hadley,
Myślę, że jeśli masz statyczną formę, lepiej wstawić pole do LayoutProcessor za pomocą XML, jak w tym przykładzie: devdocs.magento.com/guides/v2.1/howdoi/checkout/…
cjohansson
-1

Z mojego doświadczenia wynika, że ​​m2 używa xml do definiowania komponentów, takich jak pola itp. Jest to łatwiejsze do debugowania, bardziej interaktywne z danymi. W polu front-enderów powinieneś spróbować zastąpić szablony kasy i dodać tam własne pola niestandardowe. Dzięki KO pomaga Ci pracować i wiązać dane z frontendu i backendu

mrtuvn
źródło
4
To zła rada, szablony kasowe nie zawierają i nigdy nie powinny zawierać ręcznie dodanych pól wejściowych. Musimy używać KO do renderowania szablonów w wybranych regionach (wszystko jest budowane przy użyciu komponentów interfejsu użytkownika)
igloczek,
Czy możesz podać przykład dodania niestandardowych komponentów interfejsu użytkownika w interfejsie użytkownika?
mrtuvn
Jak mówi @igloczek To niewłaściwa rada, ponieważ szablony kas nigdy nie powinny zawierać ręcznie dodanych pól wejściowych.
diazwatson