---
title: "ウォークスルー:連絡先情報を更新するカスタム送信アクションの作成"
slug: "walkthrough--creating-a-custom-submit-action-that-updates-contact-details"
abstract: "連絡先情報を更新するカスタム送信アクションの作成方法の例。"
---
# ウォークスルー:連絡先情報を更新するカスタム送信アクションの作成

ナビゲーションには送信ボタン(前回・次回ボタン)を使い、フォームの提出や送信アクションのトリガーにできます。すべての送信ボタン(ナビゲーション用またはフォーム送信用)には、送信アクションを追加できます。例えば、「送信アクション「次のボタンに追加されたデータを保存」は、連絡先が「次へ」をクリックしてフォームの次のページに進 [む際にフォーム](https://doc.sitecore.com/xp/en/developers/104/platform-administration-and-architecture/forms-database.html) データベースに保存されるようにします。

デフォルトでは、トリガー目標、トリガーキャンペーンアクティビティ、トリガーアウトカム、ページへのリダイレクト、データ送信アイテムの保存などを追加できます。このウォークスルーでは、連絡先情報を更新するために使うフォームフィールドを選択するカスタム送信アクションの作成方法を説明しています。

![Map form fields to contact details dialog box.](https://doc.sitecore.com/api/markdown-image/xp/ja/developers/103/sitecore-experience-manager/images/FORMS-map-form-fields.png)

> !注このウォークスルーでは、カスタム送信アクションを作成する一例を紹介します。あなたの経験や好みによっては、異なるやり方を望むかもしれません。

## サブミッション・アクションクラスを作成する

フォーム(ページ)を提出するには、連絡先が「送信」ボタンをクリックする必要があります。ユーザーが「送信」をクリックした際に行うさまざまなアクションを追加できます。例えば、「データを送信」アクションはデータがデータベースに保存されるようにし、「トリガーキャンペーンアクティビティ提出」アクションはあらかじめ設定されたキャンペーンアクティビティを選択します。

このウォークスルーでは、Contactを更新する送信アクションを作成します。

送信アクションは、アクションに渡されるJSONオブジェクトのパラメータを格納します。JSONオブジェクトはTParametersDataクラスで指定された型のインスタンスに解析されます。この場合はUpdateContactDataクラスです。したがって、この例ではUpdateContactDataパラメータを使ってSubmitActionBaseから継承する派生クラスUpdateContactを作成します。

アクションクラスを提出するには:

1.  UpdateContactDataクラスを作成する:
    
    using System;
    
    namespace Sitecore.ExperienceForms.Samples.SubmitActions
    {
     /// <summary>
     /// Data structure of the parameters for executing the update contact submit action.
     /// </summary>
     public class UpdateContactData
     {
     /// <summary>
     /// Gets or sets the email field identifier.
     /// </summary>
     public Guid EmailFieldId { get; set; }
    
     /// <summary>
     /// Gets or sets the first name field identifier.
     /// </summary>
     public Guid FirstNameFieldId { get; set; }
    
     /// <summary>
     /// Gets or sets the last name field identifier.
     /// </summary>
     public Guid LastNameFieldId { get; set; }
     }
    }
    
2.  UpdateContactクラスを作成する:
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Sitecore.Analytics;
    using Sitecore.Diagnostics;
    using Sitecore.ExperienceForms.Models;
    using Sitecore.ExperienceForms.Processing;
    using Sitecore.ExperienceForms.Processing.Actions;
    using Sitecore.XConnect;
    using Sitecore.XConnect.Client;
    using Sitecore.XConnect.Client.Configuration;
    using Sitecore.XConnect.Collection.Model;
    namespace Sitecore.ExperienceForms.Samples.SubmitActions
    {
     /// <summary>
     /// Submit action for updating <see cref="PersonalInformation"/> and <see cref="EmailAddressList"/> facets of a <see cref="XConnect.Contact"/>.
     /// </summary>
     /// <seealso cref="Sitecore.ExperienceForms.Processing.Actions.SubmitActionBase{UpdateContactData}" />
     public class UpdateContact : SubmitActionBase<UpdateContactData>
     {
     /// <summary>
     /// Initializes a new instance of the <see cref="UpdateContact"/> class.
     /// </summary>
     /// <param name="submitActionData">The submit action data.</param>
     public UpdateContact(ISubmitActionData submitActionData) : base(submitActionData)
     {
     }
     /// <summary>
     /// Gets the current tracker.
     /// </summary>
     protected virtual ITracker CurrentTracker => Tracker.Current;
     /// <summary>
     /// Executes the action with the specified <paramref name="data" />.
     /// </summary>
     /// <param name="data">The data.</param>
     /// <param name="formSubmitContext">The form submit context.</param>
     /// <returns><c>true</c> if the action is executed correctly; otherwise <c>false</c></returns>
     protected override bool Execute(UpdateContactData data, FormSubmitContext formSubmitContext)
     {
     Assert.ArgumentNotNull(data, nameof(data));
     Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));
     var firstNameField = GetFieldById(data.FirstNameFieldId, formSubmitContext.Fields);
     var lastNameField = GetFieldById(data.LastNameFieldId, formSubmitContext.Fields);
     var emailField = GetFieldById(data.EmailFieldId, formSubmitContext.Fields);
     if (firstNameField == null && lastNameField == null && emailField == null)
     {
     return false;
     }
     using (var client = CreateClient())
     {
     try
     {
     var source = "Subcribe.Form";
     var id = CurrentTracker.Contact.ContactId.ToString("N");
     var identificationManager = ServiceLocator.ServiceProvider.GetRequiredService<IContactIdentificationManager>();
     IdentificationResult result = identificationManager.IdentifyAs(new KnownContactIdentifier (source, id));
     if (!result.Success)
     {
     throw new Exception ($"{result.ErrorCode}: {result.ErrorMessage}");
     }
     CurrentTracker.Session.IdentifyAs(source, id);
     var trackerIdentifier = new IdentifiedContactReference(source, id);
     var expandOptions = new ContactExpandOptions(
     CollectionModel.FacetKeys.PersonalInformation,
     CollectionModel.FacetKeys.EmailAddressList);
     Contact contact = client.Get(trackerIdentifier, expandOptions);
     SetPersonalInformation(GetValue(firstNameField), GetValue(lastNameField), contact, client);
     SetEmail(GetValue(emailField), contact, client);
     client.Submit();
     return true;
     }
     catch (Exception ex)
     {
     Logger.LogError(ex.Message, ex);
     return false;
     }
     }
     }
     /// <summary>
     /// Creates the client.
     /// </summary>
     /// <returns>The <see cref="IXdbContext"/> instance.</returns>
     protected virtual IXdbContext CreateClient()
     {
     return SitecoreXConnectClientConfiguration.GetClient();
     }
     /// <summary>
     /// Gets the field by <paramref name="id" />.
     /// </summary>
     /// <param name="id">The identifier.</param>
     /// <param name="fields">The fields.</param>
     /// <returns>The field with the specified <paramref name="id" />.</returns>
     private static IViewModel GetFieldById(Guid id, IList<IViewModel> fields)
     {
     return fields.FirstOrDefault(f => Guid.Parse(f.ItemId) == id);
     }
     /// <summary>
     /// Gets the <paramref name="field" /> value.
     /// </summary>
     /// <param name="field">The field.</param>
     /// <returns>The field value.</returns>
     private static string GetValue(object field)
     {
     return field?.GetType().GetProperty("Value")?.GetValue(field, null)?.ToString() ?? string.Empty;
     }
     /// <summary>
     /// Sets the <see cref="PersonalInformation"/> facet of the specified <paramref name="contact" />.
     /// </summary>
     /// <param name="firstName">The first name.</param>
     /// <param name="lastName">The last name.</param>
     /// <param name="contact">The contact.</param>
     /// <param name="client">The client.</param>
     private static void SetPersonalInformation(string firstName, string lastName, Contact contact, IXdbContext client)
     {
     if (string.IsNullOrEmpty(firstName) && string.IsNullOrEmpty(lastName))
     {
     return;
     }
     PersonalInformation personalInfoFacet = contact.Personal() ?? new PersonalInformation();
     if (personalInfoFacet.FirstName == firstName && personalInfoFacet.LastName == lastName)
     {
     return;
     }
     personalInfoFacet.FirstName = firstName;
     personalInfoFacet.LastName = lastName;
     client.SetPersonal(contact, personalInfoFacet);
     }
     /// <summary>
     /// Sets the <see cref="EmailAddressList"/> facet of the specified <paramref name="contact" />.
     /// </summary>
     /// <param name="email">The email address.</param>
     /// <param name="contact">The contact.</param>
     /// <param name="client">The client.</param>
     private static void SetEmail(string email, Contact contact, IXdbContext client)
     {
     if (string.IsNullOrEmpty(email))
     {
     return;
     }
     EmailAddressList emailFacet = contact.Emails();
     if (emailFacet == null)
     {
     emailFacet = new EmailAddressList(new EmailAddress(email, false), "Preferred");
     }
     else
     {
     if (emailFacet.PreferredEmail?.SmtpAddress == email)
     {
     return;
     }
     emailFacet.PreferredEmail = new EmailAddress(email, false);
     }
     client.SetEmails(contact, emailFacet);
     }
     }
    }
    
3.  DLLをビルドして、Sitecoreインスタンスの <root>/binディレクトリにコピーしてください。
    

## SPEAKエディターコントロールを作成する

次のステップは、フォームフィールドを連絡先情報フィールドにマッピングできるUIを作成することです。Sitecoreフォームの場合、送信アクションエディタは *コア* データベース内にあります:

*/sitecore/client/Applications/FormsBuilder/Components/Layouts/Actions*

> !注この例では、Sitecore Rocks Visual Studioプラグインが必要です。このプラグインはVisual Studio 2019以前のバージョンと互換性があります。

コントロールを作成するには:

1.  コアデータベース内で、次のサイトへ移動します。 */sitecore/client/Applications/FormsBuilder/Components/Layouts/Actions*
    
2.  **右クリックでアクション**を選び、**追加**をクリックしてから**新しいアイテム**をクリックします。
    
3.  */sitecore/client/Speak/Templates/Pages/Speak-BasePage*テンプレートを選択し、「新しいアイテム名を入力し」フィールドで「Entering the new item name」欄に*UpdateContact*を入力し、「**OK」**をクリックします。
    
4.  **BrowserTitle**と**\_\_Display名前**を*Update contact*に設定してください。
    
5.  作成した**UpdateContact**アイテムを右クリックし、「 **タスク**」をクリックし、「 **デザインレイアウト**」をクリックしてください。
    
6.  *Layout*ダイアログボックスで*/sitecore/client/Speak/Layouts/Layouts*に移動し、**Speak-FlexLayout**レイアウトを選択して**OK**をクリックします。
    
7.  左上で**「レンダリングを追加**」をクリックし、*Select Renderings*ダイアログボックスで「すべて」をクリックして「***PageCode***(/sitecore/client/Speak/Layouts/Renderings/Common/PageCode)を検索してください。」
    
    ![Forms Select renderings](https://doc.sitecore.com/api/markdown-image/xp/ja/developers/103/sitecore-experience-manager/images/FORMS-Select-renderings.png)
    
8.  PageCodeを選択して**OK**をクリックします。
    
9.  PageCodeプロパティで、PageCodeScriptFileNameプロパティをページコードスクリプトを含むJavaScriptパスに設定します: */sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions/UpdateContact.js*
    
    ![PageCodeScriptFileName property](https://doc.sitecore.com/api/markdown-image/xp/ja/developers/103/sitecore-experience-manager/images/FORMS-PageCodeScriptFileName-property.png)
    
10.  *SpeakCoreVersion*プロパティをSpeak 2-xに設定してください。
     
11.  Searchして*Text*を選択してください。レンダリング(/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Common/Text)を表示し、「**追加**」をクリックして、各レンダリングプロパティの**ID**フィールドに*HeaderTitle、HeaderSubtitle、ValueNotInListText*項目を追加してください。
     
12.  3つの項目については、*Properties*セクションで以下のIDプロパティを設定します。
     
     -   **IsVisible** – *False*
     -   **プレースホルダーキー** – *Page.Body*
     
     > !注これらのアイテムは、アクションエディターのダイアログタイトル、サブタイトル、未発見値を設定するテキストとして使われます。ここでテキストプロパティを入力すると、テキストはすべての言語で表示されますが、ローカライズはできません。
     
13.  以下のレンダリングを追加してください:
     
     -   *Border***のメインボーダー**/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Containers/Border
     -   *Form***のMapContactForm**/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Forms/Form*FieldsLayout**プロパティを1-1-1-1**PlaceholderKey**プロパティをMainBorder.Contentに設定します。*
     
     レンダリングリストは以下のようになります:
     
     ![Renderings and Placeholders](https://doc.sitecore.com/api/markdown-image/xp/ja/developers/103/sitecore-experience-manager/images/FORMS-Renderings-and-placeholders.png)
     

## エディター用のパラメータを含むフォルダを追加してください

次に、エディターのパラメータを含むフォルダを追加する必要があります。 *PageSettings*フォルダを追加するには:

1.  コアデータベースで */sitecore/client/Applications/FormsBuilder/Components/Layouts/Actions*に移動し、先に作成した*UpdateContact*アイテムを右クリックして「 **追加**」をクリックし、「 **新しいアイテム**」をクリックします。
    
2.  Searchして*PageSettings*テンプレート(/sitecore/client/Speak/Templates/Pages/PageSettings)を選択し、名前*PageSettings*を入力して**OK**をクリックします。
    
3.  作成した*PageSettings*アイテムを右クリックして「 **追加**、**新しいアイテム**」をクリックします。
    
4.  */sitecore/client/Business Component Library/version 2/Layouts/Renderings/Common/Text/Text Parameters*テンプレートを選択し、追加**を3回**クリックして、以前作成したレイアウトのIDと全く同じ名前で項目名を付けます:
    
    -   **HeaderTitle** – ダブルクリックして **テキスト** 欄に「 *Mapフォーム欄」を入力して連絡先情報を入力し*てください。
    -   **ヘッダーサブタイトル** – ダブルクリックして **テキスト** 欄で入力: *フォーム内のフィールドを更新したい連絡先情報にマッピングしてください。*
    -   **ValueNotInListText** – ダブルクリックして **テキスト** 欄に「 *Enter: value not in select list」を入力してください。*
5.  */sitecore/client/Applications/FormsBuilder/Components/Layouts/Actions/UpdateContact*に移動し、作成した**PageSettings**項目を右クリックします。
    
6.  **「新しいフォルダ**」をクリックして「*MapContactForm*」と名付けてください。
    
7.  *MapContactForm*フォルダをクリックし、以下のフィールド値を持つ3つのFormDropListパラメータテンプレート(/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Forms/Form/Templates/FormDropList Parameters)を追加します。
    
    FormDropList パラメータ
    
    ValueFieldName
    
    ディスプレイフィールドネーム
    
    フォームラベル
    
    BindingConfiguration
    
    FirstName
    
    *itemId*
    
    *名称*
    
    *First name*
    
    *firstNameFieldId/SelectedValue*
    
    LastName
    
    *itemId*
    
    *名称*
    
    *Last name*
    
    *lastNameFieldId/SelectedValue*
    
    Email
    
    *itemId*
    
    *名称*
    
    *Email*
    
    *emailFieldId/SelectedValue*
    
8.  UpdateContact項目を右クリックし、デザインレイアウト>タスクをクリックすると、*UpdateContact*レイアウトに移動します。Form rendering ConfigurationItemプロパティをFormDropListパラメータを含むMapContactFormフォルダのIDに設定します。
    
    > !注エディタUIでDropListフィールドを埋めるには、パラメータテンプレートのDataSourceプロパティを */sitecore/system/Marketing Control Panel/Automation Plans*やキャンペーンアイテムを含むフォルダのようなパスに設定してください。
    
9.  */sitecore/client/Applications/FormsBuilder/Components/Layouts/Actions/UpdateContact*に移動し、先ほど作成した**PageSettings**項目を右クリックしてください。
    
10.  *Page-Stylesheet-File* (/sitecore/client/Speak/Templates/Pages/Page-Stylesheet-Fileの型の新しいアイテム*Stylesheet*を追加してください):
     
     ![Stylesheet](https://doc.sitecore.com/api/markdown-image/xp/ja/developers/103/sitecore-experience-manager/images/FORMS-add-new-item-stylesheet.png)
     
11.  *新しいスタイルシート項目をクリックし、スタイルシートの値を /sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions/Actions.css に設定します。*
     

## 編集者用のクライアントスクリプトを作成します

次にエディター用のクライアントスクリプトを作成しなければなりません。前のステップで、UpdateContact項目を作成する際にスクリプトへのパスを次のように設定しました。

/sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions/UpdateContact.js

スクリプトを作成するには:

1.  基本のSubmit Actions編集スクリプトを使用してください。Submit actions編集スクリプトは常に以下の基本を持っています:
    
    (function (speak) {
     var parentApp = window.parent.Sitecore.Speak.app.findApplication('EditActionSubAppRenderer');
    
     speak.pageCode("underscore",
     function (\_) {
     return {
     initialized: function () {
     this.on({
     "loaded": this.loadDone
     },
     this);
    
     if (parentApp) {
     parentApp.loadDone(this, this.HeaderTitle.Text, this.HeaderSubtitle.Text);
     parentApp.setSelectability(this, true);
     }
     },
    
     loadDone: function (parameters) {
     this.Parameters = parameters || {};
     },
    
     getData: function () {
     return this.Parameters;
     }
     };
     });
    })(Sitecore.Speak);
    
2.  EditActionSubAppRendererコンポーネントを使いましょう。編集者は、EditActionSubAppRendererコンポーネントによってSpeakダイアログのフレーム内に読み込まれます。ダイアログヘッダーのタイトルとサブタイトルを親に渡し、送信ボタンが有効になったときに設定しなければなりません。
    
    この例では、連絡先情報を更新する送信アクションを作成するために、キャンバスコンポーネントFormDesignBoardを見つけ、フォームキャンバスのフィールドからデータを取得し、それらを単純な配列に変換します:空のアイテム、その後にitemIdとnameプロパティを持つアイテムです。そのため、*FormDropList Parameters*アイテムの**ValueFieldName**と**DisplayFieldName**のフィールドに*itemId*と*name*を入力したのです。スクリプトの動作は以下の通りです:
    
    -   initialized*IsSelectionRequired**プロパティをfalseに設定します*
    -   loadDone – フォームコントロールを反復し、動的データをフィールド配列に設定します。現在の送信アクション *Parameters* プロパティ値がフィールドリストに含まれていない場合(例えばフィールドが削除されたりフォームがコピーされた場合)、配列内の選択リスト項目に含まれていないid - 値が含まれます。その後、SPEAKフォームをパラメータオブジェクトにバインドします。
    -   getData – 送信ボタンをクリックすると、 getData 関数が呼び出されます。フォームデータを反復して新しいパラメータオブジェクトを収集します。空の選択(フィールドマッピング)は省略されます。
    
    最終的なスクリプトは次のようになります:
    
    (function (speak) {
     var parentApp = window.parent.Sitecore.Speak.app.findApplication('EditActionSubAppRenderer'),
     designBoardApp = window.parent.Sitecore.Speak.app.findComponent('FormDesignBoard');
    
     var getFields = function () {
     var fields = designBoardApp.getFieldsData();
    
     return \_.reduce(fields,
     function (memo, item) {
     if (item && item.model && item.model.hasOwnProperty("value")) {
     memo.push({
     itemId: item.itemId,
     name: item.model.name
     });
     }
     return memo;
     },
     
     {
     itemId: '',
     name: ''
     }
     ,
     this);
     };
    
     speak.pageCode("underscore",
     function (\_) {
     return {
     initialized: function () {
     this.on({
     "loaded": this.loadDone
     },
     this);
    
     this.Fields = getFields();
    
     this.MapContactForm.children.forEach(function (control) {
     if (control.deps && control.deps.indexOf("bclSelection") !== -1) {
     control.IsSelectionRequired = false;
     }
     });
    
     if (parentApp) {
     parentApp.loadDone(this, this.HeaderTitle.Text, this.HeaderSubtitle.Text);
     parentApp.setSelectability(this, true);
     }
     },
    
     setDynamicData: function (propKey) {
     var componentName = this.MapContactForm.bindingConfigObjectpropKey.split(".")0;
     var component = this.MapContactFormcomponentName;
    
     var items = this.Fields.slice(0);
    
     if (this.ParameterspropKey &&
     !\_.findWhere(items, { itemId: this.ParameterspropKey })) {
     var currentField = {
     itemId: this.ParameterspropKey,
     name: this.ParameterspropKey +
     " - " +
     (this.ValueNotInListText.Text || "value not in the selection list")
     };
    
     items.splice(1, 0, currentField);
    
     component.DynamicData = items;
     $(component.el).find('option').eq(1).css("font-style", "italic");
     } else {
     component.DynamicData = items;
     }
     },
    
     loadDone: function (parameters) {
     this.Parameters = parameters || {};
     \_.keys(this.MapContactForm.bindingConfigObject).forEach(this.setDynamicData.bind(this));
     this.MapContactForm.BindingTarget = this.Parameters;
     },
    
     getData: function () {
     var formData = this.MapContactForm.getFormData(),
     keys = \_.keys(formData);
    
     keys.forEach(function (propKey) {
     if (formDatapropKey == null || formDatapropKey.length === 0) {
     if (this.Parameters.hasOwnProperty(propKey)) {
     delete this.ParameterspropKey;
     }
     } else {
     this.ParameterspropKey = formDatapropKey;
     }
     }.bind(this));
    
     return this.Parameters;
     }
     };
     });
    })(Sitecore.Speak);

## アクションアイテムを提出する

アクションアイテムを提出するには:

1.  *Master*データベースで、次のサイトへ移動します*/sitecore/system/Settings/Forms/Submit Actions*
2.  右クリックで **「アクションを送信**」をクリックし、「 **挿入**」をクリックし、「 **テンプレートから挿入**」をクリックします。
3.  */System/Forms/Submit Action*テンプレートを選択し、**アイテム名**欄で名前*Update Contact Details*を入力し、「**挿入**」をクリックします。
4.  作成したアイテムに移動し、 *Settings* セクションの **Model Type** フィールドで値をクラスタイプ名に設定します。例えば、 Sitecore.ExperienceForms.Samples.SubmitActions.UpdateContact.
5.  *Error Message*欄にエラーメッセージを入力してください。例えば、「*連絡更新に失敗しました!」などです。*
6.  **エディター**フィールドで、今作成したエディターを選択してください。例えば*Update contact*。
7.  *Appearance*セクションで、フォーム要素ペインで表示したいアイコンを選択します。

フォーム要素のペインで「 **送信を追加」**アクションをクリックすると、「 **連絡先情報の更新** 」アクションを選択できます。

![Update contact action in Forms elements pane](https://doc.sitecore.com/api/markdown-image/xp/ja/developers/103/sitecore-experience-manager/images/FORMS-Update-contact-action-in-Forms-elements-pane.png)