Udemy 新コース: 作って学ぶAI Builder!

Power Apps オリジナルコントロール: 星印での評価コントロール (キャンバスアプリ & モデル駆動型アプリ) | PCFコントロール

本記事では以下のような星印で表示をするコントロールのコードを紹介します。

開発資産はGitHub に公開していますので、こちらをご確認ください。

geekfujiwara/PCF-StarRatingView: 星印で表示するPCFコントロール

ソリューションの作成やビルドの全体的な流れはこちらの記事を参考にしてください。

コーディングをするという意味では、開発する項目は以下の項目です。それぞれのディレクトリの階層関係は上記の関連記事を参照ください。

PCFプロジェクト

index.ts

コピーしました!

TypeScript
import { IInputs, IOutputs } from "./generated/ManifestTypes";

export class StarRatingControl implements ComponentFramework.StandardControl<IInputs, IOutputs> {
    private _container: HTMLDivElement;
    private _rating: number;
    private _color: number;
    private _styleColor: string;

    constructor() {}

    public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement) {
        this._container = container;
        this._rating = context.parameters.Rating.raw || 0;
        this._color = context.parameters.Color.raw || 0;
        this._styleColor = this.getColor(this._color);
        this.renderStars(this._styleColor);
    }

    public updateView(context: ComponentFramework.Context<IInputs>): void {
        this._color = context.parameters.Color.raw || 0;
        this._rating = context.parameters.Rating.raw || 0;
        this._styleColor = this.getColor(this._color);
        this.renderStars(this._styleColor);
    }

    private getColor(ColorValue: number | null) {
        if (ColorValue === null) {
            ColorValue = 1; // デフォルトの色を設定(ここではGold)
        }
        switch (ColorValue) {
            case 1:
                return "#FFD700"; // Gold
            case 2:
                return "#2dc925"; // Lime Green
            case 3:
                return "#0078D6"; // True Blue
            case 4:
                return "#C6095D"; // Royal Red
            case 5:
                return "#FD7E21"; // Princeton Orange
            case 6:
                return "#0F7926"; // La Salle Green
            case 7:
                return "#790053"; // French Plum
            case 8:
                return "#510060"; // Deep Violet
            case 9:
                return "#ADC653"; // Middle Green Yellow
            case 10:
                return "#D1E069"; // Chinese Green   
            case 11:
                return "#082139"; // Maastricht Blue 
            case 12:
                return "#003366"; // Dark Midnight Blue   
            default:
                return "#FFD700"; // Default to Gold
        }
    }

    private renderStars(ColoredStar : string): void {
        this._container.innerHTML = "";
        for (let i = 1; i <= 5; i++) {
            const star = document.createElement("span");
            star.textContent = i <= this._rating ? "★" : "★";
            star.className = "star";
            star.style.color = i <= this._rating ? ColoredStar : "gray";

            this._container.appendChild(star);
        }
    }

    public getOutputs(): IOutputs {
        return {};
    }

    public destroy(): void {}
}

ControlManifest.Input.xml

XMLの項目は、Power Apps コントロールの以下のプロパティに対応しています。

モデル駆動型アプリでもこのように説明の情報が見えます。

コピーしました!

XML
<?xml version="1.0" encoding="utf-8" ?>
<manifest>
  <control namespace="GeekNamespace" constructor="StarRatingControl" version="1.0.0" display-name-key="StarRatingControl" description-key="1-5の数字をカラフルな星で表示するコントロールです。" control-type="standard" >
    <!--external-service-usage node declares whether this 3rd party PCF control is using external service or not, if yes, this control will be considered as premium and please also add the external domain it is using.
    If it is not using any external service, please set the enabled="false" and DO NOT add any domain below. The "enabled" will be false by default.
    Example1:
      <external-service-usage enabled="true">
        <domain>www.Microsoft.com</domain>
      </external-service-usage>
    Example2:
      <external-service-usage enabled="false">
      </external-service-usage>
    -->
    <external-service-usage enabled="false">
      <!--UNCOMMENT TO ADD EXTERNAL DOMAINS
      <domain></domain>
      <domain></domain>
      -->
    </external-service-usage>
    <!-- property node identifies a specific, configurable piece of data that the control expects from CDS -->
    <property name="Rating" display-name-key="Rating" description-key="星の数を数字形式で指定します。1-5の値に対応しています。" of-type="Whole.None" usage="bound" required="true" />
    <property name="Color" display-name-key="Color" description-key="★の色を番号で指定します。1-12の値に対応しています。1 Gold, 2 Lime Green, 3 True Blue, 4 Royal Red, 5 Princeton Orange, 6 La Salle Green, 7 French Plum, 8 Deep Violet, 9 Middle Green Yellow, 10 Chinese Green, 11 Maastricht Blue, 12 Dark Midnight Blue." of-type="Whole.None" usage="input" required="true" />
    <!--
      Property node's of-type attribute can be of-type-group attribute.
      Example:
      <type-group name="numbers">
        <type>Whole.None</type>
        <type>Currency</type>
        <type>FP</type>
        <type>Decimal</type>
      </type-group>
      <property name="sampleProperty" display-name-key="Property_Display_Key" description-key="Property_Desc_Key" of-type-group="numbers" usage="bound" required="true" />
    -->
    <resources>
      <code path="index.ts" order="1"/>
<css path="css/styles.css" order="1" />
      <!-- UNCOMMENT TO ADD MORE RESOURCES
      <css path="css/StarRatingControl.css" order="1" />
      <resx path="strings/StarRatingControl.1033.resx" version="1.0.0" />
      -->
    </resources>
    <!-- UNCOMMENT TO ENABLE THE SPECIFIED API
    <feature-usage>
      <uses-feature name="Device.captureAudio" required="true" />
      <uses-feature name="Device.captureImage" required="true" />
      <uses-feature name="Device.captureVideo" required="true" />
      <uses-feature name="Device.getBarcodeValue" required="true" />
      <uses-feature name="Device.getCurrentPosition" required="true" />
      <uses-feature name="Device.pickFile" required="true" />
      <uses-feature name="Utility" required="true" />
      <uses-feature name="WebAPI" required="true" />
    </feature-usage>
    -->
  </control>
</manifest>

index.html

コピーしました!

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Star Rating Control</title>
    <link rel="stylesheet" href="css/styles.css">
</head>
<body>
    <div id="starRatingContainer"></div>
    <script src="index.ts"></script>
</body>
</html>

styles.css

コピーしました!

css
.star {
    font-size: 24px;
    color: gray; /* デフォルトの色 */
}

.star.filled {
    color: gold; /* ★の色 */
}

CDS プロジェクト

Solution.xml

コピーしました!

XML
<?xml version="1.0" encoding="utf-8"?>
<ImportExportXml version="9.1.0.643" SolutionPackageVersion="9.1" languagecode="1033" generatedBy="CrmLive" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SolutionManifest>
    <!-- Unique Name of Cds Solution-->
    <UniqueName>StarRatingView</UniqueName>
    <LocalizedNames>
      <!-- Localized Solution Name in language code -->
      <LocalizedName description="StarRatingView" languagecode="1033" />
    </LocalizedNames>
    <Descriptions />
    <Version>1.0</Version>
    <!-- Solution Package Type: Unmanaged(0)/Managed(1)/Both(2)-->
    <Managed>2</Managed>
    <Publisher>
      <!-- Unique Publisher Name of Cds Solution -->
      <UniqueName>geekfujiwara</UniqueName>
      <LocalizedNames>
        <!-- Localized Cds Publisher Name in language code-->
        <LocalizedName description="geekfujiwara" languagecode="1033" />
      </LocalizedNames>
      <Descriptions>
        <!-- Description of Cds Publisher in language code -->
        <Description description="geekfujiwara" languagecode="1033" />
      </Descriptions>
      <EMailAddress xsi:nil="true"></EMailAddress>
      <SupportingWebsiteUrl xsi:nil="true"></SupportingWebsiteUrl>
      <!-- Customization Prefix for the Cds Publisher-->
      <CustomizationPrefix>geek</CustomizationPrefix>
      <!-- Derived Option Value Prefix for the Customization Prefix of Cds Publisher -->
      <CustomizationOptionValuePrefix>67469</CustomizationOptionValuePrefix>
      <Addresses>
        <!-- Address of the Publisher-->
        <Address>
          <AddressNumber>1</AddressNumber>
          <AddressTypeCode>1</AddressTypeCode>
          <City xsi:nil="true"></City>
          <County xsi:nil="true"></County>
          <Country xsi:nil="true"></Country>
          <Fax xsi:nil="true"></Fax>
          <FreightTermsCode xsi:nil="true"></FreightTermsCode>
          <ImportSequenceNumber xsi:nil="true"></ImportSequenceNumber>
          <Latitude xsi:nil="true"></Latitude>
          <Line1 xsi:nil="true"></Line1>
          <Line2 xsi:nil="true"></Line2>
          <Line3 xsi:nil="true"></Line3>
          <Longitude xsi:nil="true"></Longitude>
          <Name xsi:nil="true"></Name>
          <PostalCode xsi:nil="true"></PostalCode>
          <PostOfficeBox xsi:nil="true"></PostOfficeBox>
          <PrimaryContactName xsi:nil="true"></PrimaryContactName>
          <ShippingMethodCode>1</ShippingMethodCode>
          <StateOrProvince xsi:nil="true"></StateOrProvince>
          <Telephone1 xsi:nil="true"></Telephone1>
          <Telephone2 xsi:nil="true"></Telephone2>
          <Telephone3 xsi:nil="true"></Telephone3>
          <TimeZoneRuleVersionNumber xsi:nil="true"></TimeZoneRuleVersionNumber>
          <UPSZone xsi:nil="true"></UPSZone>
          <UTCOffset xsi:nil="true"></UTCOffset>
          <UTCConversionTimeZoneCode xsi:nil="true"></UTCConversionTimeZoneCode>
        </Address>
        <Address>
          <AddressNumber>2</AddressNumber>
          <AddressTypeCode>1</AddressTypeCode>
          <City xsi:nil="true"></City>
          <County xsi:nil="true"></County>
          <Country xsi:nil="true"></Country>
          <Fax xsi:nil="true"></Fax>
          <FreightTermsCode xsi:nil="true"></FreightTermsCode>
          <ImportSequenceNumber xsi:nil="true"></ImportSequenceNumber>
          <Latitude xsi:nil="true"></Latitude>
          <Line1 xsi:nil="true"></Line1>
          <Line2 xsi:nil="true"></Line2>
          <Line3 xsi:nil="true"></Line3>
          <Longitude xsi:nil="true"></Longitude>
          <Name xsi:nil="true"></Name>
          <PostalCode xsi:nil="true"></PostalCode>
          <PostOfficeBox xsi:nil="true"></PostOfficeBox>
          <PrimaryContactName xsi:nil="true"></PrimaryContactName>
          <ShippingMethodCode>1</ShippingMethodCode>
          <StateOrProvince xsi:nil="true"></StateOrProvince>
          <Telephone1 xsi:nil="true"></Telephone1>
          <Telephone2 xsi:nil="true"></Telephone2>
          <Telephone3 xsi:nil="true"></Telephone3>
          <TimeZoneRuleVersionNumber xsi:nil="true"></TimeZoneRuleVersionNumber>
          <UPSZone xsi:nil="true"></UPSZone>
          <UTCOffset xsi:nil="true"></UTCOffset>
          <UTCConversionTimeZoneCode xsi:nil="true"></UTCConversionTimeZoneCode>
        </Address>
      </Addresses>
    </Publisher>
    <RootComponents />
    <MissingDependencies />
  </SolutionManifest>
</ImportExportXml>

以上

ご参考になれば幸いです。

ソリューションのビルド方法はこちらで紹介しています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Index