1. Sitecore Formsのチュートリアル

チュートリアル: 連絡先の詳細を更新するカスタム送信アクションの作成

Version:
日本語翻訳に関する免責事項

このページの翻訳はAIによって自動的に行われました。可能な限り正確な翻訳を心掛けていますが、原文と異なる表現や解釈が含まれる場合があります。正確で公式な情報については、必ず英語の原文をご参照ください。

送信ボタンは、ナビゲーション(「前へ」ボタンと「次へ」ボタン)に使用したり、フォームを送信したり、送信アクションをトリガーしたりするために使用できます。ナビゲーションに使用するか、フォームを送信するために使用するかに関係なく、すべての送信ボタンに送信アクションを追加できます。たとえば、送信アクションの「次のボタンにデータを保存する」を追加すると、連絡先が「次へ」をクリックしてフォームの次のページに移動したときに、データがFormsデータベース に保存されるようになります。

デフォルトでは、トリガーゴール、トリガーキャンペーンアクティビティ、トリガー結果、ページにリダイレクト、およびデータの保存送信アイテムを追加できます。このチュートリアルでは、連絡先の詳細の更新に使用するフォーム フィールドを選択できるカスタム送信アクションを作成する方法について説明します。

Map form fields to contact details dialog box.
メモ

このチュートリアルでは、カスタム送信アクションを作成する一例について説明します。あなたの経験や好みによっては、物事を違った方法で行うことを好むかもしれません。

submitアクション クラスを作成する

フォーム(ページ)を送信するには、コンタクトが「送信」ボタンをクリックする必要があります。ユーザーが 送信 をクリックしたときに実行するさまざまな種類のアクションを追加できます。たとえば、「データの保存」送信アクションでは、データがデータベースに保存され、「キャンペーン活動のトリガー」送信アクションでは、事前設定されたキャンペーン活動が選択されます。

このチュートリアルでは、連絡先の更新 送信アクションを作成します。

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

submitアクションクラスを作成するには:

  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 Formsの場合、送信アクション エディターはcoreデータベースにあります。

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

手記

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

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

  1. コア・データベースで、/sitecore/client/Applications/FormsBuilder/Components/Layouts/Actions

  2. Actionsを右クリックし、Addをクリックして、New Itemをクリックします。

  3. /sitecore/client/Speak/Templates/Pages/Speak-BasePageテンプレートを選択し、新しい品目の名前を入力してください フィールドに「UpdateContact」と入力してOKをクリックします。

  4. BrowserTitle__Display nameUpdate contactに設定します。

  5. 作成したUpdateContactアイテムを右クリックしてTasksをクリックし、Design Layoutをクリックします。

  6. Layoutダイアログボックスで、/sitecore/client/Speak/Layouts/Layoutsに移動してSpeak-FlexLayoutレイアウトを選択し、OKをクリックします。

  7. 左上隅のAdd Renderingをクリックし、Select Renderingsダイアログ ボックスでAllをクリックしてPageCode (/sitecore/client/Speak/Layouts/Renderings/Common/PageCode) を検索します。

    Forms Select renderings
  8. PageCodeを選択し、OKをクリックします。

  9. PageCodeプロパティで、PageCodeScriptFileNameプロパティを、ページ コード スクリプトを含むJavaScriptパスに設定します。 /sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions/UpdateContact.js

    PageCodeScriptFileName property
  10. SpeakCoreVersion プロパティをSpeak 2-xに設定します。

  11. Textビュー レンダリング(/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Common/Text)を検索して選択し、Addをクリックして、各レンダリング プロパティのIdフィールドにHeaderTitle, HeaderSubtitle, and ValueNotInListTextアイテムを追加します。

  12. 3つの項目について、Propertiesセクションで、次のIDプロパティを設定します。

    • IsVisibleFalse

    • PlaceholderKeyPage.Body

    手記

    これらのアイテムは、アクション エディターのダイアログ タイトル、サブタイトル、および見つからない値を設定するテキストとして使用されます。ここでtextプロパティを入力すると、テキストはすべての言語で表示されますが、ローカライズはできません。

  13. 次のレンダリングを追加します。

    • MainBorderタイプBorder (/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Containers/Border)の

    • MapContactFormタイプForm (/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Forms/Form)のFieldsLayoutプロパティを1-1-1-1に設定し、PlaceholderKeyプロパティをMainBorder.Contentに設定します。

    レンダリングリストは次のようになります。

    Renderings and Placeholders

エディターのパラメーターを含むフォルダーを追加します

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

  1. コア・データベースで /sitecore/client/Applications/FormsBuilder/Components/Layouts/Actionsに移動し、前に作成したUpdateContactアイテムを右クリックしてAddをクリックし、New itemをクリックします。

  2. PageSettingsテンプレート(/sitecore/client/Speak/Templates/Pages/PageSettings)を検索して選択し、名前PageSettingsを入力してOKをクリックします。

  3. 作成したPageSettingsアイテムを右クリックし、AddNew Itemの順にクリックします。

  4. /sitecore/client/Business Component Library/version 2/Layouts/Renderings/Common/Text/Text Parametersテンプレートを選択し、Addを3回クリックして、前に作成したレイアウトのIDとまったく同じ名前をアイテムに付けます。

    • HeaderTitle – ダブルクリックし、Textフィールドに「 Map form fields to contact details」と入力します。

    • HeaderSubtitle – ダブルクリックし、Textフィールドに次のように入力します。 Map the fields in the form to the contact details that you want to update.

    • ValueNotInListText – ダブルクリックし、Textフィールドに次のように入力します。 value not in selection list.

  5. /sitecore/client/Applications/FormsBuilder/Components/Layouts/Actions/UpdateContactに移動し、作成したPageSettings項目を右クリックします。

  6. New Folder 」をクリックし、「 MapContactForm」という名前を付けます。

  7. MapContactFormフォルダーをクリックし、次のフィールド値を持つ3つのFormDropListパラメーター テンプレート (/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Forms/Form/Templates/FormDropList Parameters) を追加します。

    FormDropListパラメーター

    値フィールド名

    DisplayFieldName (ディスプレイフィールド名)

    フォームラベル

    バインディング構成

    FirstName

    itemId

    name

    First name

    firstNameFieldId/SelectedValue

    LastName

    itemId

    name

    Last name

    lastNameFieldId/SelectedValue

    Email

    itemId

    name

    Email

    emailFieldId/SelectedValue

  8. UpdateContactアイテムを右クリックし、タスク > デザイン レイアウト をクリックして、UpdateContactレイアウトに移動します。フォーム レンダリングのConfigurationItemプロパティを、FormDropListパラメーターを含むMapContactFormフォルダーのIDに設定します。

  9. /sitecore/client/Applications/FormsBuilder/Components/Layouts/Actions/UpdateContactに移動し、前に作成したPageSettings項目を右クリックします。

  10. Page-Stylesheet-File (/sitecore/client/Speak/Templates/Pages/Page-Stylesheet-File) のStylesheetという名前の新しいアイテムを追加します。

    Stylesheet
  11. 新しいスタイルシートアイテムをクリックし、スタイルシートの値を次のように設定します。 /sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions/Actions.css

エディターのクライアントスクリプトを作成する

次に、エディタのクライアントスクリプトを作成する必要があります。前の手順でUpdateContactアイテムを作成したときに、スクリプトへのパスを次のように設定しました。

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

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

  1. 基本のSubmitアクション エディター スクリプトを使用します。Submitアクション エディター スクリプトには、常に次の基本があります。

    (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フィールドにitemIdnameを入力しました。スクリプトは次のように機能します。

    • initialized – フィールドからデータを配列に収集します。次に、すべてのフォーム ドロップ リストを検索し、そのIsSelectionRequiredプロパティを false

    • loadDone – フォームコントロールを反復処理し、その動的データをfields配列に設定します。現在の送信アクションParametersプロパティ値がフィールドリストにない場合 (たとえば、フィールドが削除された場合やフォームがコピーされた場合)、配列の選択リスト項目にないid - 値が含まれます。次に、SPEAKフォームをParametersオブジェクトにバインドします。

    • getData – 送信ボタンをクリックすると、getData関数が呼び出されます。フォームデータを反復処理して、新しいParametersオブジェクトを収集します。空の選択 (フィールドマッピング) は省略されます。

    最終的なスクリプトは次のようになります。

    (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.bindingConfigObject[propKey].split(".")[0];
                        var component = this.MapContactForm[componentName];
    
                        var items = this.Fields.slice(0);
    
                        if (this.Parameters[propKey] &&
                            !_.findWhere(items, { itemId: this.Parameters[propKey] })) {
                            var currentField = {
                                itemId: this.Parameters[propKey],
                                name: this.Parameters[propKey] +
                                    " - " +
                                    (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 (formData[propKey] == null || formData[propKey].length === 0) {
                                if (this.Parameters.hasOwnProperty(propKey)) {
                                    delete this.Parameters[propKey];
                                }
                            } else {
                                this.Parameters[propKey] = formData[propKey];
                            }
                        }.bind(this));
    
                        return this.Parameters;
                    }
                };
            });
    })(Sitecore.Speak);

サブミットアクションアイテムを作成する

サブミットアクションアイテムを作成するには:

  1. Masterデータベースで、/sitecore/system/Settings/Forms/Submit Actions

  2. Submit Actionsを右クリックし、Insertをクリックして、Insert from templateをクリックします。

  3. /System/Forms/Submit Actionテンプレートを選択し、Item Nameフィールドに名前Update Contact Detailsを入力して、Insertをクリックします。

  4. 作成したアイテムに移動し、SettingsセクションのModel Typeフィールドで、値をクラス タイプ名に設定します。たとえば、Sitecore.ExperienceForms.Samples.SubmitActions.UpdateContact.

  5. Error Messageフィールドに、次のようなエラー メッセージを入力します。Update contact failed!

  6. Editorフィールドで、作成したばかりのエディタ (Update contactなど) を選択します。

  7. Appearanceセクションで、フォーム要素 ウィンドウに表示するアイコンを選択します。

フォーム要素 ウィンドウでAdd a submit actionをクリックすると、Update Contact Detailsアクションを選択できるようになりました。

Update contact action in Forms elements pane
この記事を改善するための提案がある場合は、 お知らせください!