進行状況の追跡を始めよう
Trailhead のホーム
Trailhead のホーム

属性と式

学習の目的

この単元を完了すると、次のことができるようになります。
  • コンポーネントの属性を定義し、ネストされたコンポーネントに属性値を渡す。
  • コンポーネント定義とコンポーネントインスタンスの違いを理解し、コンポーネントの複数のインスタンスを作成する。
  • 変化する値と計算された値を表示する基本的式を作成する。
  • 動的出力の条件式を作成する。

コンポーネントの属性

これまでいくつかのコンポーネントを作成し、そのコンポーネントを使用した (高レベルの) アプリケーションの作成について多く学びましたが、記述したコードは単純な HTML で実行できることとあまり変わりません。つまり、作成した 2 つのコンポーネントの出力は、どんな方法を使用しても同じ静的テキストでしかありません。同じ画面内に何十個も配置できますが、常に同じ内容が表示されるだけです。

これは面白くありません。

それを変えるために、2 つのことを学習する必要があります。まずは、コンポーネントが作成されるときに入力を受け入れる方法を学習する必要があります。つまり、コンポーネントに値を設定する必要があります。これは属性を使用して行います。

(2 つ目の学習すべきことは、実際にそれらの値を使用してコンポーネントの動作と出力を変更する方法です。これは属性について理解した後に説明します。)

コンポーネントの属性は、オブジェクトのインスタンス変数のようなものです。変化する値を保存する方法であり、それらの値のプレースホルダに名前を付ける方法でもあります。たとえば、カスタムメッセージを出力する helloMessage コンポーネントを記述するとします。このコンポーネントに message 属性を追加し、出力をカスタマイズすることを想定します。次に、コンポーネントをアプリケーションに追加するときに、次のようにそのメッセージを設定します。
<aura:component>
    <c:helloMessage message="You look nice today."/>
</aura:component>
このコードはこの後数回使用するため、組織に追加してください。ただし、今追加するとエラーが表示されます。これはなぜでしょうか? helloMessage コンポーネントがまだ存在しないからです。Salesforce では、コードは記述時に検証されます。存在しないコンポーネントを参照するなど、無効であることがわかっているコードを保存しようとすると、エラーが表示されます。そのため、helloMessage の作成方法を最初に理解しましょう。

前述の例のように、コンポーネントを作成するときにその属性を設定できます。コンポーネントのライフサイクル中に、ユーザのアクションや他の場所で発生したイベントなどに応じて属性を変更することもできます。もちろん、さまざまな異なる方法で属性値を読み取ったり使用したりできます。それらについては式のトピックで説明します。

ここでは、コンポーネントの属性を定義する方法を見てみましょう。属性は <aura:attribute> タグを使用して定義され、name 属性と type 属性の値が必要です。さらに、省略可能な default 属性、description 属性、required 属性の値を受け入れます。

この一文の中にさまざまな「属性」が多数使用されています。混乱を招きがちですが、この理由は 3 つの異なる概念に同様の名前が使用されているためです。この概念を具体的に説明します。

  1. コンポーネント属性は、値を保存できる場所です。前述の例では、helloMessage コンポーネントに message というコンポーネント属性があります。ほとんどの場合、属性とはこのコンポーネント属性のことです。
  2. コンポーネント属性は <aura:attribute> タグを使用して定義します。このすぐ後にこの例を示します。これらは属性定義と呼ばれます。
  3. <aura:attribute> タグを使用するときに、このタグ自体の属性もあります。つまり、<aura:attribute> タグを使用してコンポーネント属性を定義するときに、定義するコンポーネント属性の「形状」を指定する属性を <aura:attribute> で設定します。言い替えると、属性の定義で属性を設定して、コンポーネント属性定義を追加する、ということです。コンポーネント属性の属性定義が属性を取る、とはどういうことでしょうか?

これだからライターは、と思われてしまいそうです。この用語の問題をいくつかのコードで解決してみましょう。

helloMessage コンポーネントを次の状態から開始します。

<aura:component>
    <aura:attribute name="message" type="String"/>
    <p>Hello! [ message goes here, soon ]</p>
</aura:component>

helloMessage コンポーネントに 1 つのコンポーネント属性があり、その属性は name 属性と type 属性を設定して定義されています。属性の名前は message です。式について学習するときにこの属性を参照します。ここでは静的テキストと HTML のみが出力されますが、役立つコードに近づいています。

?

ここでは他の属性 type が使用されています。これは属性定義に必要であるため設定しました。これは message 属性に文字列が含まれることを示しています。属性のデータ型、属性定義の他の部分については後で詳しく説明しますが、まずは式について学習し、helloMessage で実際に何かしてみましょう。

また言葉数が多すぎて混乱してしまう前に、直接 helloMessage を機能させてみましょう。

<aura:component>
    <aura:attribute name="message" type="String"/>
    <p>Hello! {!v.message}</p>
</aura:component>

拍子抜けしましたか?

ここでは式 {!v.message} を使用して message のコンテンツを出力しています。つまり、この式は message 属性を参照しています。この式が評価され、message に現在保存されているテキスト文字列に解決されます。この文字列がコンポーネントのボディに出力されます。

それでは「式」とは何でしょうか?

式は、基本的に式区切り文字 (「{!」と「}」) 内に配置する数式または計算です。そのため、式は次のように表記されます。

{!<expression>}

式の正式な定義は、「式はリテラル値、変数、サブ式、演算子などで構成され、1 つの値に解決されます」となっています。やや難しく感じるかもしれませんが、具体的に説明します。

基本的に、計算項目、検索条件、または Visualforce で記述するような数式のことです。数式、または式には、さまざまな内容を含めることができます。その明らかなものとしてリテラル値があります。リテラル値は、数値の 42 や文字列 Hello などです。変数は、message 属性などです。演算子は、+、- などです。サブ式は、基本的に括弧を使用して内容をグループ化できることを意味します。

式をもう少し複雑にしてみましょう。

<aura:component>
    <aura:attribute name="message" type="String"/>
    <p>{!'Hello! ' + v.message}</p>
</aura:component>

ここでは、式の外部の静的テキストから「Hello」部分を式の内部のリテラルテキストに移動しただけです。「+」演算子を使用して 2 つの文字列を連結しています。これは小さな違いに見えるかもしれませんが、挨拶のテキストを式の内部に移動することで、リテラルテキストの代わりに表示ラベルを使用できます。これにより、コンポーネントの更新 (および翻訳) を簡単に行うことができます。次に例を示します。

{!$Label.c.Greeting + v.message}

式のこの正式な定義では何が抜けているか気づきましたか? JavaScript 関数コールです。Aura コンポーネントマークアップの式には JavaScript を使用できません。

次に進む前に、式についてもう 1 つ行うことがあります。式を他のコンポーネントに渡してそのコンポーネントで値を設定できます。以下は、カスタム値を helloMessage コンポーネントに渡す新しいコンポーネントです。値を他のコンポーネントに渡すと、そのコンポーネントの値が上書きされます
<aura:component>
    <aura:attribute name="customMessage" type="String"/>
    <p> <c:helloMessage message="{!v.customMessage}"/> </p>
</aura:component>
...

値プロバイダ

実のところ、式の別の側面について話す必要があります。前述の例では、helloMessage コンポーネントの message 属性を v.message で参照しました。「v.」の部分は何を表しているでしょうか?

v は値プロバイダと呼ばれるものです。値プロバイダは、関連データのグループ化とカプセル化を行い、そのデータにアクセスする方法です。値プロバイダのトピックは複雑であるため、ここでは v を使用可能な自動変数として考えます。この例のコンポーネントでは、v は表示コンポーネント (helloMessage コンポーネント) 用の値プロバイダです。

v はコンポーネントの message 属性にアクセスする「フック」となり、この方法でコンポーネントの属性すべてにアクセスします。

値プロバイダの値には、指定したプロパティとしてアクセスします。値を使用するには、値プロバイダとプロパティ名をドット (ピリオド) で区切ります。たとえば、これまでの例にあるように v.message とします。

コンポーネントの属性がオブジェクトやその他の構造化されたデータ (プリミティブ値ではない) の場合は、同じドット表記を使用してその属性の値にアクセスします。たとえば、{!v.account.Id} は、取引先レコードの ID 項目にアクセスします。ネストが深いオブジェクトまたは属性については、ドットを繰り返し追加して構造をトラバースし、ネストされた値にアクセスします。

属性のデータ型

構造化されたデータへのアクセスからの流れで、属性、特に非プリミティブ属性型の話に戻ります。message は String ですが、他にも多数の属性型があります。

  • Boolean、Date、DateTime、Decimal、Double、Integer、Long、String などのプリミティブデータ型。すべてのプログラミング言語で一般的に使用されます。
  • Account、MyCustomObject__c などの標準オブジェクト型とカスタム Salesforce オブジェクト型。
  • List、Map、Set などのコレクション型
  • カスタム Apex クラス
  • Aura.Component、Aura.Component[] などのフレームワーク固有の型。これらはこのモジュールで説明する内容よりも高度ですが、存在することだけ覚えておいてください。

expenseItem コンポーネントの抜粋を次に示します。詳細は後ほど説明します。カスタムオブジェクトの属性を定義する方法と、レコードの項目にアクセスする方法が示されています。

<aura:component>
    <aura:attribute name="expense" type="Expense__c"/>
    <p>Amount:
        <lightning:formattedNumber value="{!v.expense.Amount__c}" style="currency"/>
    </p>
    <p>
        Client: {!v.expense.Client__c}
    </p>
    <p>
        <lightning:input type="toggle"
                         label="Reimbursed?"
                         name="reimbursed"
                         checked="{!v.expense.Reimbursed__c}" />
     </p>
    <!-- Other markup here -->
</aura:component>

このコンポーネントには 1 つの属性、expense があります。この属性は、このモジュールのかなり前に作成したカスタムオブジェクトです。このコンポーネントの目的は、{!v.expense.fieldName} 式を使用して Expense__c レコードの項目を 参照し、経費の詳細を表示することです。ここでは、切り替え形式のチェックボックスである type="toggle"< コンポーネントを使用しているため、後で UI から値を更新できます。

属性定義の他の側面

属性は <aura:attribute> タグで設定します。その他に知っておくべきことを次に示します。

  • default 属性は、デフォルト属性値を定義します。属性の値をまだ設定していないときに属性が参照される場合に使用されます。
  • required 属性は、属性が必須かどうかを定義します。デフォルトは false です。
  • description 属性は、属性およびその用途の簡単な概要を定義します。

複雑なデータ型の属性にデフォルト値を設定することは難しいかもしれません。ここでは説明しませんが、後でこの一例を示します。

属性と式で遊ぶ

属性と式について、さらにいくつかの概念を説明するため、次のマークアップを使用して遊び心のあるコンポーネント、helloPlayground を作成しましょう。

<aura:component>
    <aura:attribute name="messages" type="List"
        default="['You look nice today.',
            'Great weather we\'re having.',
            'How are you?']"/>
    <h1>Hello Playground</h1>
    <p>Silly fun with attributes and expressions.</p>
    <h2>List Items</h2>
    <p><c:helloMessage message="{!v.messages[0]}"/></p>
    <p><c:helloMessage message="{!v.messages[1]}"/></p>
    <p><c:helloMessage message="{!v.messages[2]}"/></p>
    <h2>List Iteration</h2>
    <aura:iteration items="{!v.messages}" var="msg">
        <p><c:helloMessage message="{!msg}"/></p>
    </aura:iteration>
    <h2>Conditional Expressions and Global Value Providers</h2>
    <aura:if isTrue="{!$Browser.isIPhone}">
        <p><c:helloMessage message="{!v.messages[0]}"/></p>
    <aura:set attribute="else">
        <p><c:helloMessage message="{!v.messages[1]}"/></p>
        </aura:set>
    </aura:if>
</aura:component>

次に、helloPlayground コンポーネントをハーネスアプリケーションに追加し、どのように実行されるか見てみましょう。

多数の新しい内容が含まれています。ここでは詳しく説明しませんが、後でまたこのすべてを使用します。

まず、helloPlayground には複雑な List データ型の 1 つの属性、messages があります。そのリストにはデフォルト値として、3 つの単一引用符で囲まれた文字列がカンマで区切られた配列があります。「List Items」(リスト項目) セクションでは、インデックスを使用して各文字列にアクセスする方法が記述されています。

誰かが 2 つのメッセージのみで <c:helloPlayground> を作成するとどうなるでしょうか? 3 つ目の項目へのアクセスに失敗します。ここではクラッシュすることはありませんが、より複雑なコンポーネントではクラッシュする可能性があります。

そのため、「List Iteration」(リスト反復) セクションでリスト内のすべての項目を処理する適切な方法が記述されています。<> コンポーネントはその items 属性の項目ごとにそのボディを 1 回繰り返すため、メッセージ数に応じてリストの増加や減少が行われます。

「Conditional Expressions and Global Value Providers」(条件式とグローバル値プロバイダ) セクションでは、考えられる 2 つの出力のいずれかを選択する方法が記述されています。これは JavaScript などではなくマークアップであるため洗練されていませんが、<aura:if> コンポーネントでは、たとえばユーザがオブジェクトに対する編集権限を持っている場合にのみ編集ボタンを追加することができます。

最後にもう 1 つ、あまり目立たない点があります。オブジェクト指向プログラミングでは、クラスとそのクラスのインスタンスには違いがあります。コンポーネントにも同じような概念があります。.cmp リソースを作成することで、そのコンポーネントの定義 (クラス) を指定します。.cmp にコンポーネントタグを追加することで、そのコンポーネント (のインスタンス) への参照を作成します。

もちろん、異なる属性を持つ同じコンポーネントのインスタンスを複数追加することもできます。前述の例では、messages にデフォルト値を使用すると、<c:helloMessage> コンポーネント (のインスタンス) の 8 個の参照が作成されます。より長いリストを渡すと、より多くの参照が作成されます。このたった 1 つのコンポーネントでこのすべてが行われます。

これで、実際の作業を行う準備ができました。