Search code examples
shopwareshopware6

[Shopware6]: How to reuse the customer selection component in administration?


I'm trying to create a custom-field that is an entity-single-select for customers, exactly like the one in the sw-order module as seen here sw-order-create-details-header > sw-entity-single-select

Is there some way for me, to configure the look of my custom-field to be the same as the extended select-field in the sw-order module? With that i mean, inclusive of firstName, lastName, address and customernumber? (Without creating a a new component)

What i have so far is this:

    protected $customFields =  [
    [
        'name' => 'referrer_set',
        'config' => [
            'label' => [
                'en-GB' => 'Referrer',
                'de-DE' => 'Referrer',
            ],
        ],
        'customFields' => [
            [
                'active' => true,
                'name' => 'refferer_set',
                'type' => CustomFieldTypes::ENTITY,
                'config' => [
                    'componentName' => 'sw-entity-single-select',
                    'entity' => CustomerDefinition::ENTITY_NAME,
                    'placeholder' => "Wurde empfohlen von ...",
                    'highlightSearchTerm' => true,
                    'allowEntityCreation' => false,
                    'show-clearable-button' => true,
                    'labelProperty' => 'firstName',
                    'label' => [
                        'en-GB' => 'Empfohlen von',
                        'de-DE' => 'Empfohlen von',
                    ],
                ],
            ],
        ],
        'relations' => [
            [
                'entityName' => CustomerDefinition::ENTITY_NAME,
            ],
        ],
    ],
];

Solution

  • Unfortunately this isn't quite so trivial to achieve.

    You could override the component which is responsible for rendering custom fields sw-form-field-renderer.

    Inside the override you check if it is your specific custom field that should be rendered. In the template of the override you then set the content of the slot result-item, which is a corresponding to each option in the dropdown. You'll additionally have to extend the binds of the component with a criteria to add the billing address of the customer as an association.

    The override:

    import template from './sw-form-field-renderer.html.twig';
    
    const { Component } = Shopware;
    const { Criteria } = Shopware.Data;
    
    Component.override('sw-form-field-renderer', {
        template,
    
        computed: {
            isMyCustomField() {
                return this.config.componentName === 'sw-entity-single-select' && this.$attrs.name === 'refferer_set';
            },
    
            bind() {
                const bind = this.$super('bind');
    
                if (this.isMyCustomField) {
                    const criteria = new Criteria;
                    criteria.addAssociation('defaultBillingAddress.country');
                    bind.criteria = criteria;
                }
    
                return bind;
            },
        },
    });
    

    The template sw-form-field-renderer.html.twig:

    {% block sw_form_field_renderer_scope_slots %}
    {% parent %}
    <template
        v-if="isMyCustomField"
        #result-item="{ item, index, labelProperty, searchTerm, highlightSearchTerm, isSelected, setValue, getKey }"
    >
        <!-- copy/paste from sw-order-create-details-header -->
        <li
            is="sw-select-result"
            :selected="isSelected(item)"
            v-bind="{ item, index }"
            class="sw-order-create-details-header__customer-result"
            @item-select="setValue"
        >
            <div class="sw-order-create-details-header__customer-result-item has-many-childrens">
                <div>
                    <sw-highlight-text
                        v-if="highlightSearchTerm"
                        :text="getKey(item, 'firstName') || getKey(item, `translated.firstName`)"
                        :search-term="searchTerm"
                    />
    
                    <sw-highlight-text
                        v-if="highlightSearchTerm"
                        :text="getKey(item, 'lastName') || getKey(item, `translated.lastName`)"
                        :search-term="searchTerm"
                    />
                </div>
    
                <sw-highlight-text
                    v-if="highlightSearchTerm"
                    :text="getKey(item, 'customerNumber') || getKey(item, `translated.customerNumber`)"
                    :search-term="searchTerm"
                    class="text-truncate"
                />
            </div>
    
            <div
                v-if="getKey(item, 'company') || getKey(item, `translated.company`)"
                class="sw-order-create-details-header__customer-result-item"
            >
                <sw-highlight-text
                    v-if="highlightSearchTerm"
                    :text="getKey(item, 'company') || getKey(item, `translated.company`)"
                    :search-term="searchTerm"
                />
            </div>
    
            <div class="sw-order-create-details-header__customer-result-item text-gray-500">
                {{ item.defaultBillingAddress.street }} <br>
                {{ item.defaultBillingAddress.zipcode }} {{ item.defaultBillingAddress.city }} <br>
                {{ item.defaultBillingAddress.country.name }}
            </div>
        </li>
    </template>
    {% endblock %}