Akeneo ikona technologiiJak rozszerzyć istniejące moduły oparte o RequireJS?

Jak rozszerzyć istniejące moduły oparte o RequireJS?

Jesteś zadowolony z tego, co oferuje moduł nadrzędny w Akeneo PIM, ale zależy Ci na zmianie jednej z funkcjonalności? Jako Frontend Developer często będziesz stawać przed tego typu wyzwaniem, bowiem nie zawsze możliwe jest pokrycie wszystkich specyficznych potrzeb biznesowych za pomocą zainstalowanego modułu.

Z tego artykułu dowiesz się, jaka jest najprostsza i zarazem najlepsza metoda, by rozszerzyć moduł RequireJS, a także jak zaimportować w plikach "requirejs.yml" pierwotny oraz rozszerzony plik. Pojęcie dziedziczenia jest również ważne w tym kontekście, ponieważ właściwości i metody modułu nadrzędnego (niezmienione) są dziedziczone przez nasz moduł. Gotowy?


Przeczytaj również inne artykuły z cyklu:


Nadpisywać czy rozszerzać?

Moduł modułowi jest nierówny. W przypadku większych modułów RequireJS, które posiadają liczne metody oraz są wykorzystywane w wielu miejscach aplikacji, nie najlepszą praktyką byłoby nadpisywanie ich, co było tematem naszego poprzedniego artykułu. Problem może stanowić też aktualizacja oprogramowania, w sytuacji gdy nadpisujemy złożony moduł.

Jeśli wymagane jest zmodyfikowanie lub dodanie tylko jednej wybranej metody w złożonym module opartym o RequireJS, powinieneś go rozszerzyć. Zaleta takiego podejścia jest oczywista. Rozszerzając domyślny moduł, nadpisujemy tylko te metody, które chcemy zmodyfikować, a nie całość.

Najlepsza praktyka przy rozszerzaniu modułu RequireJS

Wykorzystując dziedziczenie, będziemy chcieli rozszerzyć istniejący moduł RequireJS i zmienić logikę metody "createFields". Naszym celem będzie sprawdzenie, czy aktualne pole ma wartość "name" i przypisanie dla niego jakiejś domyślnej wartości.

Plik "attributes" jest sporym modułem, który występuje w wielu miejscach. Odpowiada za pobranie informacji o danych polach i nadanie im odpowiedniego kontekstu oraz wartości. Ponadto pomaga w sortowaniu ich w odpowiedniej kolejności. W ramach zadania musisz zmodyfikować metodę "createFields". Sprawdź dodatkowo w plikach "requirejs.yml", jak importowany jest domyślnie ten moduł.

Domyślnie dodawany jest w następujący sposób:

pim/form/common/attributes: pimui/js/form/common/attributes

Plik, który będziemy rozszerzać, znajdziesz tutaj:

Aby rozszerzyć istniejący moduł, należy go z zaimportować pod innym kluczem, a następnie dodać go do pliku, w którym rozszerzamy ten moduł. Na końcu rozszerzony moduł importujemy pod kluczem starego.

Plik "attributes.js" dodajemy w RequireJS pod nowym kluczem "base-attributes", upewniając się przy tym, że podany klucz nie jest nigdzie wykorzystywany w projekcie:

pim/form/common/base-attributes: pimui/js/form/common/attributes

Kolejnym krokiem jest stworzenie nowego pliku "attributes", który będzie rozszerzał stary. Do niego dodajemy pierwotny plik "attributes.js" pod kluczem "pim/form/common/base-attributes".

W podanym przypadku z pierwotnego pliku źródłowego kopiujemy tylko te metody, które chcemy rozszerzyć:

'use strict';

/**
* Override of the attributes module.
*
* Purpose of this override is to improve the blocking fields for simple products
* and sets of products including common attributes and variants
*
*/
define(
   [
       'jquery',
       'underscore',
       'oro/mediator',
       'pim/field-manager',
       'pim/attribute-manager',
       'pim/fetcher-registry',
       'pim/user-context',
       'pim/security-context',
       'pim/i18n',
       'pim/form/common/base-attributes'
   ],
   function (
       $,
       _,
       mediator,
       FieldManager,
       AttributeManager,
       FetcherRegistry,
       UserContext,
       SecurityContext,
       i18n,
       BaseAttributes
   ) {

       return BaseAttributes.extend({
           createFields: function (data, values) {
               return FetcherRegistry.getFetcher('attribute')
                   .fetchByIdentifiers(Object.keys(values))
                   .then(attributes => {
                       attributes.sort((a, b) => {
                           if (a.sortOrder  b.sortOrder) {
                               return -1;
                           }

                           if (a.sortOrder > b.sortOrder) {
                               return 1;
                           }

                           return a.meta.id  b.meta.id ? -1 : 1;
                       });

                       return $.when.apply(
                           $,
                           attributes.map(attribute => {
                               console.log(values);

                               return this.createAttributeField(data, attribute.code, values[attribute.code]);
                           })
                       );
                   })
                   .then(function () {
                       return _.values(arguments);
                   });
           }
       });
   }
);

Po zaimportowaniu pierwotny plik "attributes" jest dostępny pod nazwą "BaseAttributes". Dzięki użyciu "BaseAttributes.extend" mamy dostęp do wszystkich metod i właściwości zaimportowanego przez nas pliku.

Ostatni krok przed edycją samego pliku polega na dodaniu w "requirejs.yml" stworzonego przez nas pliku. Pamiętaj, aby plik został dodany pod tym samym kluczem, pod jakim pierwotnie był dodany rozszerzany przez nas moduł:

pim/form/common/base-attributes: pimui/js/form/common/attributes
pim/form/common/attributes: macopediaproduct/js/product/maco-attributes

W pierwszej linii dodany jest stary plik "attributes" dostępny pod kluczem "pim/form/common/base-attributes". W drugiej, pod kluczem "pim/form/common/attributes", importowany jest już nasz moduł rozszerzający domyślny plik "attributes".

Teraz możemy przystąpić do edycji stworzonego przez nas modułu. W metodzie "createFields", którą chcemy edytować, wykorzystajmy na razie polecenie "console.log" wyświetlające zmienną "values". To pomoże nam zweryfikować, czy plik został poprawnie dodany oraz do jakich danych mamy dostęp:

console.log(values);

Jeśli wszystko wykonaliśmy poprawnie, powinniśmy  w narzędziach deweloperskich zobaczyć następujące informacje dla każdego pola:

If we did everything properly, we should see the following information for each field in the developer tools

Jak widać, mamy tutaj dostęp do wielu właściwości, a jedną z nich jest "name". Spróbujmy zatem dla pola "name" zmienić właściwość "name" dla wersji angielskiej:

'use strict';

/**
* Override of the attributes module.
*
* Purpose of this override is to improve the blocking fields for simple products
* and sets of products including common attributes and variants
*
*/
define(
   [
       'jquery',
       'underscore',
       'oro/mediator',
       'pim/field-manager',
       'pim/attribute-manager',
       'pim/fetcher-registry',
       'pim/user-context',
       'pim/security-context',
       'pim/i18n',
       'pim/form/common/base-attributes'
   ],
   function (
       $,
       _,
       mediator,
       FieldManager,
       AttributeManager,
       FetcherRegistry,
       UserContext,
       SecurityContext,
       i18n,
       BaseAttributes
   ) {

       return BaseAttributes.extend({
           createFields: function (data, values) {
               return FetcherRegistry.getFetcher('attribute')
                   .fetchByIdentifiers(Object.keys(values))
                   .then(attributes => {
                       attributes.sort((a, b) => {
                           if (a.sortOrder  b.sortOrder) {
                               return -1;
                           }

                           if (a.sortOrder > b.sortOrder) {
                               return 1;
                           }

                           return a.meta.id  b.meta.id ? -1 : 1;
                       });

                       return $.when.apply(
                           $,
                           attributes.map(attribute => {
                               if (attribute.code === 'name') {
                                   values['name'][1].data = 'New description...';
                               }

                               return this.createAttributeField(data, attribute.code, values[attribute.code]);
                           })
                       );
                   })
                   .then(function () {
                       return _.values(arguments);
                   });
           }
       });
   }
);

Załączamy funkcję warunkową JEŻELI, która sprawdzałaby, czy aktualnym polem jest "name", następnie w "values" szukamy obiektu "name". W nim znajduje się kilka obiektów dla każdej wersji językowej. Nam zależy na nadpisaniu dla wersji angielskiej, stąd też wybieramy drugi obiekt i jemu przypisujemy nową wartość dla przykładu "New description…".

Teraz powinieneś być w stanie zobaczyć domyślną wartość pola "name" dodaną przez nas:

Now you should be able to see the default value of the "name" field that we added

Czy kroki opisane w tym artykule okazały się pomocne? Bądź na bieżąco i śledź nas w mediach społecznościowych (Twitter / LinkedIn / Facebook)! W kolejnej odsłonie poznasz jeszcze jedno podejście do modyfikacji modułów w Akeneo PIM. W artykule wyjaśnimy szczegółowo, jak dodawać własne pliki i wykorzystać je w istniejących modułach RequireJS.