Создание страницы на Visualforce

Создадим страницу с использованием Visualforce. Которая будет работать с двумя Salesforce объектами «PC Brand» и «Brand Product», связанными между собой Lookup связью.
Страница будет выводить список брендов, при нажатии на имя бренда в этом списке будут все связанные с ним продукты. О связях между объектами в Salesforce можно почитать тут.
Также на странице можно будет создать продукт для любого из брендов.

Разобьем весь процесс на несколько этапов:

1. Создание объектов в Salesforce;
2. Вывод данных на страницу;
3. Создание объекта на странице;

Страница Visualforce:

<apex:page id="PCBrandsList" controller="PCBrandsListController">
    <apex:sectionHeader title="PC Brands" subtitle="All brands"/>
    <apex:form>
    <apex:pageBlock title="List PC Brands">
        <apex:pageBlockSection columns="1">
            <apex:pageBlockTable value="{!pcBrands}" var="brand">
                <apex:column headerValue="Product">
                    <apex:commandLink action="{!retrieveProducts}" value="{!brand.Name}" reRender="bProdacts">
                        <apex:param name="bParam" value="{!brand.id}" assignTo="{!brandId}"/>
                    </apex:commandLink>
                </apex:column>
                <apex:column headerValue="Description">
                    <apex:outputText value="{!brand.About_Brand__c}"/>
                </apex:column>
            </apex:pageBlockTable>
        </apex:pageBlockSection>
    </apex:pageBlock>
    </apex:form>


    <apex:pageBlock title="List Brand Products">
        <apex:pageBlockSection columns="1">
            <apex:pageBlockTable value="{!brandProducts}" var="product" id="bProdacts">
                <apex:column headerValue="Product">
                    <apex:outputText value="{!product.Name}"/>
                </apex:column>
                <apex:column headerValue="Motherboard">
                    <apex:outputText value="{!product.Motherboard__c}"/>
                </apex:column>
                <apex:column headerValue="HDD Size">
                    <apex:outputText value="{!product.HDD_Size__c}"/>
                </apex:column>
                <apex:column headerValue="Ram">
                    <apex:outputText value="{!product.Ram__c}"/>
                </apex:column>
                <apex:column headerValue="Video Card">
                    <apex:outputText value="{!product.Video_card__c}"/>
                </apex:column>
                <apex:column headerValue="Video Card Size">
                    <apex:outputText value="{!product.Video_card_size__c}"/>
                </apex:column>
            </apex:pageBlockTable>
        </apex:pageBlockSection>
    </apex:pageBlock>

    <apex:form id="saveBrand">
    <apex:pageBlock title="Add Product">
            <apex:pageMessages id="showmsg"></apex:pageMessages>
        <apex:pageBlockSection columns="1">
            <apex:selectList value="{!bProduct.PC_Brand__c}" size="1" multiselect="false">
                <apex:selectOptions value="{!selectValues}"/>
            </apex:selectList>
            <apex:inputText value="{!bProduct.Name}" required="true"/>
            <apex:inputText value="{!bProduct.Motherboard__c}" />
            <apex:inputText value="{!bProduct.HDD_Size__c}" />
            <apex:inputText value="{!bProduct.Ram__c}" />
            <apex:inputText value="{!bProduct.Video_card__c}" />
            <apex:inputText value="{!bProduct.Video_card_size__c}" />
            <apex:commandButton value="Add product" action="{!save}" reRender="saveBrand"/>
        </apex:pageBlockSection>
    </apex:pageBlock>
    </apex:form>
</apex:page>

Дополнительно про Visualforce компоненты и как они работают можно прочитать здесь.

Контроллер на Apex:

public with sharing class PCBrandsListController {

    public Brand_Product__c bProduct{get; set;}
    public List<PC_Brand__c> pcBrands{get; set;}
    public List<Brand_Product__c> brandProducts{get; set;}
    public String brandId{get; set;}
    public String selectedvalue{get; set;}

    public PCBrandsListController(){
        bProduct = new Brand_Product__c();
        pcBrands = getPCBrangs();
    }

    private List<PC_Brand__c> getPCBrangs(){
        List<PC_Brand__c> listBrands = [SELECT Id, Name, About_Brand__c FROM PC_Brand__c];
        return listBrands;
    }

    public void retrieveProducts(){
        brandProducts = [SELECT Id, Name, Motherboard__c, HDD_Size__c, Ram__c, Video_card__c, Video_card_size__c, PC_Brand__c FROM Brand_Product__c WHERE PC_Brand__c = :brandId];
    }

    public List<SelectOption> getselectValues(){
        List<SelectOption> lOptions = new List<SelectOption>();
        for (PC_Brand__c brand : pcBrands){
            lOptions.add(new SelectOption(brand.Id, brand.Name));
        }
        return lOptions;
    }

    public PageReference save(){
        PageReference pageRef = Page.PCBrandsList;
        pageRef.setRedirect(true);
        try {
            insert bProduct;
        }catch (Exception e){
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR, '"Something went wrong !"'));
        }
        return pageRef;
    }
}

Про Apex контроллер можно почитать здесь.
Подробно что как работает опишу ниже.

Создание объектов в Salesforce.

Создадим два объекта «PC Brand» и «Brand Product».
Описание объектов:
PC Brand
image

Brand Product

На объекте «Brand Product» будет Lookup поле которое будет ссылаться на объект «PC Brand».

Вывод данных на страницу

Чтобы связать Visualforce страницу с Apex контроллером нужно это прописать в теге apex:page,
где "PCBrandsListController" - это имя Apex контроллера.

<apex:page id="PCBrandsList" controller="PCBrandsListController">

Теперь мы сможем обращаться к переменным и методам Apex контроллера.
Данные выводятся в виде таблицы. Для этого используется тег apex:pageBlockTable :

<apex:pageBlockTable value="{!pcBrands}" var="brand">
  <apex:column headerValue="Product">
       <apex:commandLink action="{!retrieveProducts}" 
                         value="{!brand.Name}" 
                         reRender="bProdacts">
            <apex:param name="bParam" value="{!brand.id}" assignTo="{!brandId}"/>
       </apex:commandLink>
  </apex:column>

  <apex:column headerValue="Description">
        <apex:outputText value="{!brand.About_Brand__c}"/>
  </apex:column>
 </apex:pageBlockTable>

В теге apex:pageBlockTable атрибут value="{!pcBrands}" ссылается на переменную из Apex контроллера public List<PC_Brand__c> pcBrands{get; set;} которая инициализируется в конструкторе контроллера.
Для того чтобы сделать имя бренда кликабельным используем тег apex:commandLink, где в атрибуте action="{!retrieveProducts}" ссылаемся на функцию контроллера retrieveProducts(). Которая выполняется по нажатию на имя бренда. Тег apex:commandLink имеет дочерний тег apex:param где Id бренда value="{!brand.id}" передается в переменную контроллера assignTo="{!brandId}" вот таким образом.
Теперь чтобы после нажатия на имя бренда у нас обновилась таблица с зависимыми продуктами мы используем атрибут reRender="bProdacts" тега apex:commandLink где bProdacts это значение атрибута Id из тега <apex:pageBlockTable value="{!brandProducts}" var="product" id="bProdacts"> - таблицы, где выводятся продукты выбранного бренда.
И наконец сама таблица продуктов:

            <apex:pageBlockTable value="{!brandProducts}" var="product" id="bProdacts">
                <apex:column headerValue="Product">
                    <apex:outputText value="{!product.Name}"/>
                </apex:column>
                <apex:column headerValue="Motherboard">
                    <apex:outputText value="{!product.Motherboard__c}"/>
                </apex:column>
                <apex:column headerValue="HDD Size">
                    <apex:outputText value="{!product.HDD_Size__c}"/>
                </apex:column>
                <apex:column headerValue="Ram">
                    <apex:outputText value="{!product.Ram__c}"/>
                </apex:column>
                <apex:column headerValue="Video Card">
                    <apex:outputText value="{!product.Video_card__c}"/>
                </apex:column>
                <apex:column headerValue="Video Card Size">
                    <apex:outputText value="{!product.Video_card_size__c}"/>
                </apex:column>
            </apex:pageBlockTable>

Здесь в теге apex:pageBlockTable мы обращаемся к переменной контроллера value="{!brandProducts}". Которая устанавливается после нажатия на имя бренда в методе

    public void retrieveProducts(){
        brandProducts = [SELECT Id, Name, Motherboard__c, HDD_Size__c, Ram__c, Video_card__c, Video_card_size__c, PC_Brand__c FROM Brand_Product__c WHERE PC_Brand__c = :brandId];
    }

Создание объекта на странице

Для создания объекта создадим еще одну форму на странице Visualforce:

    <apex:form id="saveBrand">
    <apex:pageBlock title="Add Product">
            <apex:pageMessages id="showmsg"></apex:pageMessages>
        <apex:pageBlockSection columns="1">
            <apex:selectList value="{!bProduct.PC_Brand__c}" size="1" multiselect="false">
                <apex:selectOptions value="{!selectValues}"/>
            </apex:selectList>
            <apex:inputText value="{!bProduct.Name}" required="true"/>
            <apex:inputText value="{!bProduct.Motherboard__c}" />
            <apex:inputText value="{!bProduct.HDD_Size__c}" />
            <apex:inputText value="{!bProduct.Ram__c}" />
            <apex:inputText value="{!bProduct.Video_card__c}" />
            <apex:inputText value="{!bProduct.Video_card_size__c}" />
            <apex:commandButton value="Add product" action="{!save}" reRender="saveBrand"/>
        </apex:pageBlockSection>
    </apex:pageBlock>
    </apex:form>

Здесь в месте, где стоит тег apex:pageMessages будет выводиться сообщение об ошибке, если не получается сохранить запись в Salesforce. Сообщение об ошибке в контроллере на страницу Visualforce передается вот так: ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR, '"Something went wrong !"'));
Для инициализации выпадающего списка используется конструкция:

            <apex:selectList value="{!bProduct.PC_Brand__c}" size="1" multiselect="false">
                <apex:selectOptions value="{!selectValues}"/>
            </apex:selectList>

Здесь нужно отметить что в теге <apex:selectOptions value="{!selectValues}"/> мы обращаемся к функции контроллера getselectValues() указывая ее имя, но без префикса get вот так: {!selectValues}.
В теге apex:commandButton мы обращаемся к методу action="{!save}" контроллера страницы. Где и происходит сохранение продукта.
Для того чтобы можно было обращаться к переменным контроллера из Visualforce страницы, нужно чтоб переменные имели геттеры и сеттеры или их сокращенная запись как в нашем примере:

    public Brand_Product__c bProduct{get; set;}
    public List<PC_Brand__c> pcBrands{get; set;}
    public List<Brand_Product__c> brandProducts{get; set;}
    public String brandId{get; set;}
    public String selectedvalue{get; set;}

В итоге у нас получится вот такая форма:

4 Likes

Без каких то начальных знаний это не создать совсем новичку!

Без начальных знаний невозможно будет разобраться и понять

Просто скопировать может и получится

Не думаю)))
что где вставлять не понятно
и что где смотреть тоже
Но спс за материал все равно на русском его и так мало
так сказать если сильно надо то снимешь штаны