Field set и разработка Apex

Приветствую!

Предположим, у вас есть задача построить динамический UI с полями или написать динамический SOQL запрос. В каждом из этих случаев нужно как-то реализовать возможность легкого добавления и удаления полей для отображения. Пример: у меня есть какая-то страница с набором полей, бизнесу нужно добавить ещё пару полей. Моя задача это сделать с минимальными затратами и максимально быстро. При этом я не хочу менять код решения и исправлять тесты для этого решения.

Как часто вы встречались с такой ситуаций?

В итоге вы начинаете работать над задачей и понимаете, что вам нужно создать доп хранилище под динамическую часть, где будет храниться какой-то более менее приемлемый интерфейс для редактирования этого списка полей. И как итог — задача обрастает таким количеством дополнительных подзадач, что может занять весьма большой отрезок времени.

FieldSet похож на page layout, однако без разделения на секции. В Fieldset могут входить любые поля: стандартные, кастомные, из установленных пакетов.

Field set можно создать для любого объекта.

Теперь мы, зная теоретическую часть, можем перейти к практике.

Создание FieldSet

FieldSet создается декларативным путем. Значит, мы можем легко это сделать через меню Setup. Для каждого объекта FieldSet создается отдельно. Единственное ограничение: fieldset можно создать лишь в Salesforce Classic, Lightning пока не поддерживается.

Путь для стандартных объектов

Setup -> Customize -> Object -> Field Sets

FieldSet Standard

Путь для кастомных объектов

Setup -> Create-> Objects -> Object -> Field Sets

Далее мы создаем новый FieldSet и вносим необходимые данные, как на картинке ниже.

FieldSet new

После чего мы попадаем в окно редактирования полей в FieldSet. Как вы можете заметить, эта форма очень похожа на page layout, однако имеет свои отличительные особенности. В данной форме нам интересна колонка In the FieldSet, в неё мы и будем добавлять наши поля.

FieldSet pagel ayout

Fieldset в Apex

Fieldsets легко можно использовать в Apex коде. Для этого у нас есть специальный системный класс Schema.FieldSet и ниже мы можем видеть пример его использования. В этом примере мы получаем коллекцию для sObject.

Map<String, Schema.FieldSet> FsMap = Schema.SObjectType.Account.fieldSets.getMap();

Однако, данный пример не самый оптимальный. В случае, если нам нужно получить один определенный FieldSet, мы можем использовать другой подход описанный в следующем примере.

Schema.FieldSet fs1 = Schema.SObjectType.Account.fieldSets.getMap().get('field_set_name');

Schema.FieldSet fs2 = Schema.SObjectType.Account.fieldSets.field_set_name;

В этом примере мы получаем данные определенного FieldSet для Account.

FieldSet и SOQL

Мы можем использовать FieldSet и для построения динамических SOQL запросов

String query = 'SELECT';

for(Schema.FieldSetMember fieldSet : SObjectType.Merchandise__c.FieldSets.Dimensions.getFields()) {
    query += f.getFieldPath() + ', ';
}
query += 'Id, Name FROM Merchandise__c LIMIT 1';

List<Merchandise__c> merchandise = Database.query(query);

Таким образом мы можем получить гибкий и динамический SOQL запрос.

Fieldset и UI

Также мы можем использовать FieldSet для построения гибких интерфейсов. Давайте возьмем предыдущий пример и добавим визуальную часть.

Начнем с Apex класс:

public class MerchandiseDetails {

    public Merchandise__c merch { get; set; }

    public MerchandiseDetails() {
        this.merch = getMerchandise();
    }

    public List<Schema.FieldSetMember> getFields() {
        return SObjectType.Merchandise__c.FieldSets.Dimensions.getFields();
    }

    private Merchandise__c getMerchandise() {
        String query = 'SELECT ';
        for(Schema.FieldSetMember f : this.getFields()) {
            query += f.getFieldPath() + ', ';
        }
       query += 'Id, Name FROM Merchandise__c LIMIT 1';
       return Database.query(query);
    }
}

Дальше добавим Visualforce страницу

<apex:page controller="MerchandiseDetails">
    <apex:form >
    <apex:pageBlock title="Product Details">
        <apex:pageBlockSection title="Product">
            <apex:inputField value="{!merch.Name}"/>
        </apex:pageBlockSection>
        <apex:pageBlockSection title="Dimensions">
            <apex:repeat value="{!fields}" var="f">
                <apex:inputField value="{!merch[f.fieldPath]}" required="{!OR(f.required, f.dbrequired)}"/>
            </apex:repeat>
        </apex:pageBlockSection>
    </apex:pageBlock>
    </apex:form>
</apex:page>

И по итогу у нас получается страница с динамическими полями, которые можно изменять максимально удобно и просто. А самое главное — не нужно создавать дополнительную сервисную логику и интерфейсы для работы этого решения.

Данный пример описывает решения на основе VisualForce страницах, однако FieldsSet также можно использовать и в LWC компонентах.

7 Likes

А почему нельзя создать филдсет в лайтнинге? Всегда создаю филдсеты в лайтнинге. Возможно ваша информация устарела.

1 Like

Да, Вы правы, как-то я упустил этот момент из виду. :sweat_smile:

1 Like