8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Salesforce Platform Developer I:Visualforceの基礎

Last updated at Posted at 2021-05-18

Visualforce

Visualforceは、Lightning Platformでホストできるモバイルおよびデスクトップアプリケーション用の高度なカスタムユーザインターフェースを、開発者が作成できるようにするWeb開発フレームワークです。
Visualforceページは標準Webページに似ていますが、組織のデータのアクセス、表示、更新を行うための強力な機能が含まれています。

Lightning ExperienceにVisualforceを使用できる場所

・アプリケーションランチャーから Visualforce ページを開く
  カスタムタブ作成
・Visualforce ページをナビゲーションバーに追加する
  カスタムタブ作成、応用対象アプリケーション選択
・標準ページレイアウト内に Visualforce ページを表示する
  標準ページレイアウト編集画面で、Visualforceページ追加可能
・Lightning アプリケーションビルダーで Visualforce ページをコンポーネントとして追加する
  Lightningアプリケーションビルダーに設定、指定箇所にドラッグ
・Visualforce ページをクイックアクションとして起動する
  クイックアクション作成して、ページレイアウト編集画面に指定箇所にドラッグ
・標準ボタンまたはリンクを上書きして Visualforce ページを表示する
  オブジェクトマネージャーから「ボタン、リンク、およびアクション」右の[▼]の編集から設定する
・カスタムボタンまたはリンクを使用して Visualforce ページを表示する
  Lightning Experience では JavaScript のボタンやリンクがサポートされていませんが、Visualforce (および URL) の項目はサポートされています。

※Lightning Experienceに利用したい場合以下の設定がチェック必要
image.png

Visualforce ページの作成と編集

・開発者コンソールで作成
・「設定」の「Visualforceページ」の新規ボタンまた、各VFPの編集リンクから

HelloWorld.vfp
<apex:page>
   <h1>Hello World</h1>
   <apex:pageBlock title="A Block Title">
       <apex:pageBlockSection title="A Section Title">
           I'm three components deep!
       </apex:pageBlockSection>
       <apex:pageBlockSection title="A New Section">
           This is another section.
       </apex:pageBlockSection>
   </apex:pageBlock>
</apex:page>

image.png
※<> タグは、親 <> タグ内に配置しない限り使用できません。

ブラウザの JavaScript コンソール入力して以下のエラーが出る場合、対応方法
Uncaught ReferenceError: $A is not defined
at :1:1

①Visualforceページの編集画面で、Lightning Experience利用可能チェック入れる
②Lightning Experience環境に該当VFPのタブ作成
③該当タブ移動
④[Ctrl]+[shift]+[J]でブラウザのJSコンソール呼び出し
⑤以下のコード実行

$A.get("e.force:navigateToURL").setParams(
    {"url": "/apex/AccountSummary?id=0015h000008rgKJAAY"}).fire();

⑥遷移可能になる確認

CHALLENGE

DisplayImage.vfp
<apex:page showHeader="false">
    <apex:image url="https://developer.salesforce.com/files/salesforce-developer-network-logo.png"/>
</apex:page>

グローバル変数、数式と条件式

{! $GlobalName.fieldName } という形式の式を使用します
よく使うグローバル変数
$ Label
カスタムラベルを参照するときに使用するグローバルマージフィールドタイプ。
$ Permission
現在のユーザーのカスタムアクセス許可アクセスに関する情報を参照するときに使用するグローバルマージフィールドタイプ。権限マージフィールドを使用して、組織のカスタム権限へのユーザーの現在のアクセスに関する情報を参照します。
$ Profile
現在のユーザーのプロファイルに関する情報を参照するときに使用するグローバルマージフィールドタイプ。プロファイルマージフィールドを使用して、ライセンスタイプや名前などのユーザーのプロファイルに関する情報を参照します。
$ User
現在のユーザーに関する情報を参照するときに使用するグローバルマージフィールドタイプ。ユーザーマージフィールドは、エイリアス、タイトル、IDなどのユーザーに関する情報を参照できます。User標準オブジェクトで使用できるフィールドのほとんどは、$ Userでも使用できます。
$ UserRole
現在のユーザーの役割に関する情報を参照するときに使用するグローバルマージフィールドタイプ。ロールマージフィールドは、ロール名、説明、IDなどの情報を参照できます。

そして、組織の詳細 ($Organization)、設定 ($Setup)、カスタムオブジェクトの詳細 ($ObjectType)、それらのオブジェクトで使用可能なアクション ($Action) などの取得にも役立ちます。
※Visualforce 式では大文字小文字は区別されず、{! ...} 内のスペースも無視されます。

UserStatus.vfp
<apex:page>
    <apex:pageBlock title="User Status">
        <apex:pageBlockSection columns="1" title="ユーザ情報">
            {! $User.FirstName & ' ' & $User.LastName }
           ({! $User.Username })
        </apex:pageBlockSection>
        <apex:pageBlockSection columns="1" title="数式">
            <p> Today's Date is {! TODAY() } </p>
            <p> Next week it will be {! TODAY() + 7 } </p>
            <p>The year today is {! YEAR(TODAY()) }</p>
            <p>Tomorrow will be day number  {! DAY(TODAY() + 1) }</p>
            <p>Let's find a maximum: {! MAX(1,2,3,4,5,6,5,4,3,2,1) } </p>
            <p>The square root of 49 is {! SQRT(49) }</p>
            <p>Is it true?  {! CONTAINS('salesforce.com', 'force.com') }</p>
        </apex:pageBlockSection>
        <apex:pageBlockSection columns="1" title="条件式">
            <p>{! IF( CONTAINS('salesforce.com','force.com'), 'Yep', 'Nope') }</p>
            <p>{! IF( DAY(TODAY()) < 15, 'Before the 15th', 'The 15th or after') }</p>
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:page>

image.png

単一レコードのデータとリレーションの項目を表示する

AccountSummary.vfp
<apex:page standardController="Account">
    <apex:pageBlock title="Account Summary">
        <apex:pageBlockSection>
            Account owner: {! Account.Owner.Name } <br/>
            Name: {! Account.Name } <br/>
            Phone: {! Account.Phone } <br/>
            Industry: {! Account.Industry } <br/>
            Revenue: {! Account.AnnualRevenue } <br/>
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:page>

standardControllerにオブジェクトの「API参照名」指定、
その後は「{! Account.XXX }」で項目表示可能、そして「{! Account.Owner.XXX }」でリレーション関係の関連オブジェクト項目表示可能

レコード詳細と関連リストを表示する

レコード詳細表示(関連リスト付け)

<apex:page standardController="Account">
<apex:detail />
</apex:page>

image.png

レコード詳細表示(関連リスト付いていない)

取引先レコードの詳細はそのまま表示されますが、関連リストは表示されません。

<apex:page standardController="Account">
<apex:detail relatedList="false"/>
</apex:page>

image.png

レコード詳細表示(関連リスト自定義表示)

<apex:page standardController="Account">
<apex:detail relatedList="false"/>
<apex:relatedList list="Contacts"/>
<apex:relatedList list="Opportunities" pageSize="5"/>
</apex:page>

image.png

レコード詳細個別項目表示

<apex:page standardController="Account">
<apex:outputField value="{! Account.Name }"/><br/>
<apex:outputField value="{! Account.Phone }"/><br/>
<apex:outputField value="{! Account.Industry }"/><br/>
<apex:outputField value="{! Account.AnnualRevenue }"/><br/>
</apex:page>

image.png

テーブルを表示する

・「apex:pageBlock」:表示枠
・「apex:pageBlockTable」テーブル設定
  「value」:データ元
  「var」:列のカラムに設定レコードデータの略称
・「apex:column」:列
  「value」:レコードの項目

<apex:pageBlock title="Contacts">
   <apex:pageBlockTable value="{!Account.contacts}" var="contact">
      <apex:column value="{!contact.Name}"/>
      <apex:column value="{!contact.Title}"/>
      <apex:column value="{!contact.Phone}"/>
   </apex:pageBlockTable>
</apex:pageBlock>

image.png

その他

他のタグが下記のリンク参照

apex:enhancedListapex:listViews は、apex:relatedList と併用するかこの代わりに使用すると役立つ、別の大まかなコンポーネントです。
apex:dataTableapex:dataList は、スタイル設定なしのテーブルとリストを作成する反復コンポーネントです。

Visualforceフォーム

AccountEdit.vfp
<apex:page standardController="Account">
    <apex:form> <!-- その中に含まれるすべてをページアクションの一部としてサーバに戻すことができる -->
    <apex:pageBlock title="Edit Account">
		<apex:pageMessages/> <!-- フォーム処理エラー、メッセージを表示 -->
        <apex:pageBlockSection columns="1">
            <apex:inputField value="{! Account.Name }"/> <!-- レコードデータ入力項目 -->
            <apex:inputField value="{! Account.Phone }"/>
            <apex:inputField value="{! Account.Industry }"/>
            <apex:inputField value="{! Account.AnnualRevenue }"/>
        </apex:pageBlockSection>
        <apex:pageBlockButtons>
            <apex:commandButton action="{! save }" value="Save" /> <!-- ボタン、 標準saveアクションメソッド呼び出し -->
        </apex:pageBlockButtons>
    </apex:pageBlock>
    <apex:pageBlock title="Contacts">
        <apex:pageBlockTable value="{!Account.contacts}" var="contact">
            <apex:column>
                <apex:outputLink
                    value="{! URLFOR($Action.Contact.Edit, contact.Id) }"><!-- URLFOR()URL再設定、グローバル変数利用 -->
                    Edit
                </apex:outputLink>
                &nbsp;
                <apex:outputLink
                    value="{! URLFOR($Action.Contact.Delete, contact.Id) }">
                    Del
                </apex:outputLink>
            </apex:column>
            <apex:column value="{!contact.Name}"/>
            <apex:column value="{!contact.Title}"/>
            <apex:column value="{!contact.Phone}"/>
        </apex:pageBlockTable>
    </apex:pageBlock>
    </apex:form>
</apex:page>

image.png

標準リストコントローラ

ContactsList.vfp
<apex:page standardController="Contact" recordSetVar="contacts"><!-- recordSetVar:レコードのコレクションで作成される変数の名前 -->
    <apex:form >
        <apex:pageBlock title="Contacts List" id="contacts_list">
            Filter:
            <apex:selectList value="{! filterId }" size="1"><!-- 検索条件設定 -->
                <apex:selectOptions value="{! listViewOptions }"/>
                <apex:actionSupport event="onchange" reRender="contacts_list"/>
            </apex:selectList>
            <!-- Contacts List表示-->
            <apex:pageBlockTable value="{! contacts }" var="ct">
                <apex:column value="{! ct.FirstName }"/>
                <apex:column value="{! ct.LastName }"/>
                <apex:column value="{! ct.Email }"/>
                <apex:column value="{! ct.Account.Name }"/>
            </apex:pageBlockTable>
            <!-- page数 前後ページ追加 表示件数変更 -->
            <table style="width: 100%"><tr>
            <!-- ページ数/総ページ数 表示追加-->
                <td>
                    Page: <apex:outputText value=" {!PageNumber} of {! CEILING(ResultSize / PageSize) }"/>
                </td>
                <td align="center">
                    <!-- 前のページ-->
                    <!-- active -->
                    <apex:commandLink action="{! Previous }" value="« Previous"
                         rendered="{! HasPrevious }"/>
                    <!-- inactive (no earlier pages) -->
                    <apex:outputText style="color: #ccc;" value="« Previous"
                         rendered="{! NOT(HasPrevious) }"/>
                    &nbsp;&nbsp;
                    <!-- 次のページ-->
                    <!-- active -->
                    <apex:commandLink action="{! Next }" value="Next »"
                         rendered="{! HasNext }"/>
                    <!-- inactive (no more pages) -->
                    <apex:outputText style="color: #ccc;" value="Next »"
                         rendered="{! NOT(HasNext) }"/>
                </td>
                <!-- ページ表示件数設定-->
                <td align="right">
                    Records per page:
                    <apex:selectList value="{! PageSize }" size="1">
                        <apex:selectOption itemValue="5" itemLabel="5"/>
                        <apex:selectOption itemValue="20" itemLabel="20"/>
                        <apex:actionSupport event="onchange" reRender="contacts_list"/>
                    </apex:selectList>
                </td>
            </tr></table>
        </apex:pageBlock>
    </apex:form>
</apex:page>

image.png

CHALLENGE

AccountList.vfp
<apex:page standardController="Account" recordSetVar="accounts">
    <apex:repeat var="a" value="{!accounts}">
          <li>
              <apex:outputLink value="/{!a.id}">
                  {!a.name}
        </apex:outputLink>
        </li>
    </apex:repeat>
</apex:page>

結果:リンク作成、各取引先に遷移可能
image.png

静的リソースの使用

①下記のリンクから単純なjQueryダウンロード、また、jquerymobileのzipファイルダウンロード
https://jquery.com/download/
image.png
https://jquerymobile.com/download/
image.png

※jquerymobileの場合、zipファイル解凍して、demoフォルダ削除、そしてフォルダ名はjqueryに変更して、再圧縮する必要がある。

②静的リソース作成
image.png
また
image.png

③VFの利用

jQueryMobileResources.vfp
<apex:page showHeader="false" sidebar="false" standardStylesheets="false">
    <!-- 静的リソースからcss設定 -->
    <apex:stylesheet value="{!
        URLFOR($Resource.jQueryMobile,'jquery/jquery.mobile-1.4.5.css')}"/>
    <!-- Add static resources to page's <head> -->
    <apex:includeScript value="{! $Resource.jQueryMobile }"/>
    <!-- 静的リソースからjs設定 -->
    <apex:includeScript value="{!
        URLFOR($Resource.jQueryMobile,'jquery/jquery.mobile-1.4.5.js')}"/>
    <div style="margin-left: auto; margin-right: auto; width: 50%">
        <!-- Display images directly referenced in a static resource -->
        <h3>Images</h3>
        <p>A hidden message:
            <!-- 静的リソースから表示画像設定 -->
            <apex:image alt="eye" title="eye"
                url="{!URLFOR($Resource.jQueryMobile, 'jquery/images/icons-png/eye-black.png')}"/>
            <apex:image alt="heart" title="heart"
                url="{!URLFOR($Resource.jQueryMobile, 'jquery/images/icons-png/heart-black.png')}"/>
            <apex:image alt="cloud" title="cloud"
                url="{!URLFOR($Resource.jQueryMobile, 'jquery/images/icons-png/cloud-black.png')}"/>
        </p>
    <!-- Display images referenced by CSS styles, all from a static resource. -->
    <h3>Background Images on Buttons</h3>
    <button class="ui-btn ui-shadow ui-corner-all 
        ui-btn-icon-left ui-icon-action">action</button>
    <button class="ui-btn ui-shadow ui-corner-all 
        ui-btn-icon-left ui-icon-star">star</button>
    </div>
</apex:page>

image.png

カスタムコントローラの作成と使用

ページタグのcontroller項目の指定のカスタムコントローラ設定可能

ContactsListWithController.vfp
<apex:page controller="ContactsListWithController">
    <apex:form>
        <apex:pageBlock title="Contacts List" id="contacts_list">
            <!-- Contacts List -->
            <apex:pageBlockTable value="{! contacts }" var="ct">
                <apex:column value="{! ct.FirstName }">
                    <apex:facet name="header">
                        <apex:commandLink action="{! sortByFirstName }"
                            reRender="contacts_list">
                            <!-- カスタムオブジェクトには独自の翻訳指定 -->
                            <apex:outputText value="{! $ObjectType.Contact.Fields.FirstName.Label }"/>
                        </apex:commandLink>
                    </apex:facet>
                </apex:column>
                <apex:column value="{! ct.LastName }">
                    <apex:facet name="header">
                        <apex:commandLink action="{! sortByLastName }"
                            reRender="contacts_list"><apex:outputText value="{! $ObjectType.Contact.Fields.LastName.Label }"/>
                        </apex:commandLink>
                    </apex:facet>
                </apex:column>
                <apex:column value="{! ct.Title }"/>
                <apex:column value="{! ct.Email }"/>
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>
ContactsListWithController.cls
public class ContactsListWithController {
private String sortOrder = 'LastName';
//初期化の検索
public List<Contact> getContacts() {
    List<Contact> results = Database.query(
        'SELECT Id, FirstName, LastName, Title, Email ' +
        'FROM Contact ' +
        'ORDER BY ' + sortOrder + ' ASC ' +
        'LIMIT 10'
    );
    return results;
}
//姓でソート
public void sortByLastName() {
    this.sortOrder = 'LastName';
}
//名でソート
public void sortByFirstName() {
    this.sortOrder = 'FirstName';
}
}

image.png

標準コントローラとカスタムコントローラ

呼び出し文言 Apex
標準コントローラ standardController
カスタムコントローラ controller 必要
標準コントローラ拡張 standardControllerとextensions 拡張の部分必要

CHALLENGE

NewCaseList.vfp
<apex:page controller="NewCaseListController">
    <apex:repeat value="{!NewCases}" var="case">
        <li>
            <apex:outputLink value="/{!case.id}" target="_new">
                {!case.CaseNumber}
            </apex:outputLink>
        </li>
    </apex:repeat>
</apex:page>
NewCaseListController.cls
public class NewCaseListController {
    public List<Case> getNewCases(){
        List<Case> results = Database.query('SELECT Id,CaseNumber FROM Case where status=\'New\'');
        return results;
    }
}
8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?