Tutorial: Eine Feldkomponente für modellgesteuerte Apps erstellen
In diesem Tutorial erstellen Sie eine field
-Komponente für modellgesteuerte Apps und stellen sie bereit, konfigurieren sie und testen die Komponente in einem Formular mit Visual Studio Code. Diese Codekomponente zeigt eine Reihe von Auswahlmöglichkeiten im Formular mit einem Symbol neben jedem Auswahlwert an. Die Komponente verwendet einige der erweiterten Funktionen modellgesteuerter Apps, z. B. Auswahlspaltendefinitionen (Metadaten) und Sicherheit auf Spaltenebene.
Darüber hinaus stellen Sie sicher, dass die Codekomponente den Best-Practice-Leitlinien folgt:
- Einsatz von Microsoft Fluent UI für Konsistenz und Barrierefreiheit
- Lokalisierung der Codekomponentenbezeichnungen sowohl beim Entwurf als auch zur Runtime
- Sicherstellung, dass die Codekomponente im Interesse besserer Wiederverwendbarkeit metadatengesteuert ist
- Sicherstellung, dass die Codekomponente gemäß dem Formfaktor und verfügbarer Breite rendert und ein kompaktes Dropdownmenü mit Symbolen anzeigt, wenn der Platz begrenzt ist.
Code
Sie können den vollständigen Code für das Beispiel hier herunterladen: PowerApps-Samples/component-framework/ChoicesPickerControl/.
Ein neues pcfproj
-Projekt anlegen
Hinweis
Bevor Sie beginnen, stellen Sie sicher, dass Sie alle Voraussetzungskomponenten installiert haben.
Um ein neues pcfproj
zu erstellen:
Erstellen Sie einen neuen Ordner für Ihre Codekomponente. Zum Beispiel:
C:\repos\ChoicesPicker
.Öffnen Sie Visual Studio Code und gehen Sie dann zu Datei > Ordner öffnen und wählen Sie den im vorherigen Schritt erstellten
ChoicesPicker
-Ordner aus. Wenn Sie die Windows-Explorer-Erweiterungen während der Installation von Visual Studio Code hinzugefügt haben, können Sie auch die Kontextmenüoption Mit Code öffnen im Ordner verwenden. Sie können auch einen beliebigen Ordner in Visual Studio Code mitcode .
bei der Eingabeaufforderung hinzufügen, wenn das aktuelle Verzeichnis auf diesen Speicherort festgelegt ist.In dem neuen Visual Studio Code PowerShell-Terminal (Terminal > Neues Terminal) verwenden Sie den pac pcf init Befehl, um ein neues Codekomponentenprojekt zu erstellen:
pac pcf init ` --namespace SampleNamespace ` --name ChoicesPicker ` --template field ` --run-npm-install
Alternativ verwenden Sie die Kurzform:
pac pcf init -ns SampleNamespace -n ChoicesPicker -t field -npm
Dies fügt dem aktuellen Ordner ein neues ChoicesPicker.pcfproj
und die dazugehörigen Dateien hinzu, einschließlich ein package.json
, dass die erforderlichen Module festlegt. Der obige Befehl wird auch den Befehl npm install
ausführen, um die erforderlichen Module zu installieren.
Running 'npm install' for you...
Hinweis
Wenn Sie den Fehler The term 'npm' is not recognized as the name of a cmdlet, function, script file, or operable program.
erhalten, stellen Sie sicher, dass Sie Node.js (LTS-Version wird empfohlen) und alle anderen Voraussetzungen installiert haben.
Wie Sie sehen, enthält die Vorlage eine index.ts
-Datei sowie verschiedene Konfigurationsdateien. Dies ist der Ausgangspunkt Ihrer Codekomponente und enthält die in Komponentenimplementierung beschriebenen Lebenszyklusmethoden.
Microsoft Fluent UI installieren
Sie verwenden die Microsoft Fluent UI und React zum Erstellen der Benutzeroberfläche, daher müssen Sie diese als Abhängigkeiten installieren. Um die Abhängigkeiten zu installieren, verwenden Sie:
npm install react react-dom @fluentui/react
Dadurch werden die Module zu den packages.json
hinzugefügt und sie im node_modules
-Ordner installiert. node_modules
wird nicht in die Quellcodeverwaltung eingeschrieben, da alle erforderlichen Module später mit npm install
wiederhergestellt werden können.
Einer der Vorteile der Microsoft Fluent UI ist, dass sie eine konsistente und extrem barrierefreie Benutzeroberfläche ist.
Konfiguration von eslint
Die von pac pcf init verwendete Vorlage installiert die eslint
-Module in Ihrem Projekt und konfiguriert es durch Hinzufügen einer .eslintrc.json
-Datei. Eslint
erfordert die Konfiguration für die Codierungsstile TypeScript und React. Weitere Informationen: Linting – Best Practices und Anleitungen für Codekomponenten.
Das Manifest bearbeiten
Die ChoicesPicker\ControlManifest.Input.xml
-Datei legt die Metadaten fest, die das Verhalten der Codekomponente beschreiben. Die Steuerelement-Attribute hat bereits den Namenspace und den Namen Ihrer Komponente.
Sie müssen die folgenden gebundenen und Eingabeeigenschaften festlegen:
Name des Dataflows | Verbrauch | Type | Beschreibung |
---|---|---|---|
Wert | bound |
OptionSet | Diese Eigenschaft wird mit der Auswahlspalte verknüpft. Die Codekomponente empfängt den aktuellen Wert und benachrichtigt dann den übergeordneten Kontext, wenn sich der Wert geändert hat. |
Symbolzuordnung | input |
Mehrere Textzeilen | Der Wert dieser Eigenschaft wird festgelegt, wenn die die App erstellende Person die Codekomponente zum Formular hinzufügt. Sie enthält eine JSON-Zeichenfolge, um zu konfigurieren, welche Symbole für die einzelnen Auswahlwert verwendet werden können. |
Weitere Informationen: Eigenschaftenelement
Tipp
Sie können das XML leichter lesen, wenn Sie es so formatieren, dass die Attribute in separaten Zeilen erscheinen. Suchen und installieren Sie ein XML-Formatierungstool Ihrer Wahl auf dem Visual Studio Code Marketplace: Nach XML-Formatierungserweiterungen suchen.
Die folgenden Beispiele wurden so formatiert, dass die Attribute in separaten Zeilen stehen, um sie besser lesbar zu machen.
Das vorhandene sampleProperty durch neue Eigenschaften ersetzen
Öffnen Sie ChoicesPicker\ControlManifest.Input.xml
und fügen Sie die folgende Eigenschaftendefinition in das Steuerelement ein, wobei Sie das vorhandene sampleProperty
ersetzen:
<property name="sampleProperty"
display-name-key="Property_Display_Key"
description-key="Property_Desc_Key"
of-type="SingleLine.Text"
usage="bound"
required="true" />
Speichern Sie die Änderungen und verwenden Sie dann den folgenden Befehl, um die Komponente zu erstellen:
npm run build
Nachdem die Komponente erstellt wurde, sehen Sie Folgendes:
Eine automatisch generierte Datei
ChoicesPicker\generated\ManifestTypes.d.ts
wird Ihrem Projekt hinzugefügt. Diese wird im Rahmen des Erstellen-Prozesses aus demControlManifest.Input.xml
und stellt die Typen für die Interaktion mit den Eingabe-/Ausgabeeigenschaften bereit.Die Erstellen-Ausgabe wird dem
out
-Ordner hinzugefügt. Diebundle.js
ist das transpilierte JavaScript, das im Browser ausgeführt wird. DieControlManifest.xml
ist eine neu formatierte Version derControlManifest.Input.xml
-Datei, die während der Bereitstellung verwendet wird.Hinweis
Ändern Sie die Inhalte der
generated
- undout
-Ordner nicht direkt. Sie werden im Rahmen des Build-Prozesses überschrieben.
Die React-Komponente ChoicesPicker der Fluent-Benutzeroberfläche implementieren
Wenn die Codekomponente React verwendet, muss es eine einzelne Stammkomponente geben, die innerhalb der updateView
-Methode gerendert wird. Innerhalb des ChoicesPicker
-Ordners fügen Sie eine neue TypeScript-Datei mit dem Namen ChoicesPickerComponent.tsx
hinzu und den folgenden Inhalt hinzu:
import { ChoiceGroup, IChoiceGroupOption } from '@fluentui/react/lib/ChoiceGroup';
import * as React from 'react';
export interface ChoicesPickerComponentProps {
label: string;
value: number | null;
options: ComponentFramework.PropertyHelper.OptionMetadata[];
configuration: string | null;
onChange: (newValue: number | undefined) => void;
}
export const ChoicesPickerComponent = React.memo((props: ChoicesPickerComponentProps) => {
const { label, value, options, configuration, onChange } = props;
const valueKey = value != null ? value.toString() : undefined;
const items = React.useMemo(() => {
let iconMapping: Record<number, string> = {};
let configError: string | undefined;
if (configuration) {
try {
iconMapping = JSON.parse(configuration) as Record<number, string>;
} catch {
configError = `Invalid configuration: '${configuration}'`;
}
}
return {
error: configError,
choices: options.map((item) => {
return {
key: item.Value.toString(),
value: item.Value,
text: item.Label,
iconProps: { iconName: iconMapping[item.Value] },
} as IChoiceGroupOption;
}),
};
}, [options, configuration]);
const onChangeChoiceGroup = React.useCallback(
(ev?: unknown, option?: IChoiceGroupOption): void => {
onChange(option ? (option.value as number) : undefined);
},
[onChange],
);
return (
<>
{items.error}
<ChoiceGroup
label={label}
options={items.choices}
selectedKey={valueKey}
onChange={onChangeChoiceGroup}
/>
</>
);
});
ChoicesPickerComponent.displayName = 'ChoicesPickerComponent';
Hinweis
Die Datei hat die Erweiterung tsx
und ist eine TypeScript-Datei, die die von React verwendete Syntax im XML-Stil unterstützt. Sie wird durch den Erstellenprozess in Standard-JavaScript kompiliert.
Hinweise zum Design der ChoicesPickerComponent
Dieser Abschnitt enthält Anmerkungen zum Design der ChoicesPickerComponent
.
Es ist eine funktionale Komponente
Dies ist eine React-Funktionskomponente, könnte aber auch eine Klassenkomponente sein. Dies basiert auf Ihrem bevorzugten Codierungsstil. Klassenkomponenten und Funktionskomponenten können im selben Projekt auch gemischt werden. Sowohl Funktions- als auch Klassenkomponenten verwenden die von React verwendete tsx
-Syntax im XML-Stil. Weitere Informationen: Funktions- und Klassenkomponenten
Die Größe von bundle.js minimieren
Beim Importieren der Fluent-Benutzeroberflächenkomponente ChoiceGroup
mit pfadbasierten Importen anstelle von:
import { ChoiceGroup, IChoiceGroupOption } from '@fluentui/react';
Wir verwenden:
import { ChoiceGroup, IChoiceGroupOption } from '@fluentui/react/lib/ChoiceGroup';
Dadurch wird Ihre Paketgröße kleiner, was zu geringeren Kapazitätsanforderungen und einer besseren Runtimeleistung führt.
Eine Alternative wäre Tree Shaking.
Beschreibung der Eigenschaften
Die Eingabeeigenschaften haben die folgenden Attribute, die von index.ts
in der updateView
-Methode bereitgestellt werden:
prop |
Beschreibung |
---|---|
label |
Wird verwendet, um die Komponente zu beschriften. Ist an die vom übergeordneten Kontext bereitgestellte Metadatenfeldbeschriftung gebunden, wobei die in der modellgesteuerten App ausgewählte Benutzeroberflächensprache verwendet wird. |
value |
Mit der im Manifest definierten Eingabeeigenschaft verknüpft. Dies kann null sein, wenn der Datensatz neu oder das Feld nicht festgelegt ist. TypeScript null wird beim Übergeben/Zurückgeben von Eigenschaftswerten eher verwendet als undefined . |
options |
Wenn eine Codekomponente an eine Auswahlspalte in einer modellgesteuerten App gebunden ist, enthält die Eigenschaft die OptionMetadata , welche die verfügbaren Auswahlmöglichkeiten beschreibt. Sie übergeben dies an die Komponente, damit sie die einzelnen Element rendern kann. |
configuration |
Der Zweck der Komponente besteht darin, für jede verfügbare Auswahl ein Symbol anzuzeigen. Die Konfiguration wird von der die App erstellenden Person bereitgestellt, wenn er die Codekomponente zu einem Formular hinzufügt. Diese Eigenschaft akzeptiert eine JSON-Zeichenfolge, die jeden numerischen Auswahlwert einem Fluent UI-Symbolnamen zuordnet. Zum Beispiel: {"0":"ContactInfo","1":"Send","2":"Phone"} . |
onChange |
Wenn der Benutzer die Optionsauswahl ändert, löst die React-Komponente das onChange -Ereignis aus. Die Codekomponente ruft dann notifyOutputChanged auf, damit die modellgesteuerte App die Spalte mit dem neuen Wert aktualisieren kann. |
Gesteuerte React-Komponente
Es gibt zwei Typen von React-Komponenten:
Type | Beschreibung |
---|---|
Nicht gesteuert | Behalten ihren internen Status bei und verwenden die Eingabeeigenschaften nur als Standardwerte. |
Gesteuert | Rendern den von den Komponenteneigenschaften übergebenen Wert. Wenn das onChange -Ereignis die Eigenschaftenwerte nicht aktualisiert, wird dem Benutzer keine Änderung in der Benutzeroberfläche angezeigt. |
Die ChoicesPickerComponent
ist eine kontrollierte Komponente. Sobald die modellgesteuerte App den Wert aktualisiert hat (nach dem notifyOutputChanged
-Aufruf), wird die updateView
mit dem neuen Wert aufgerufen, der dann an die Komponenteneigenschaften übergeben wird, was zu einem erneuten Rendering führt, das den aktualisierten Wert anzeigt.
Destrukturierungszuweisung
Die Zuweisung der props
Konstante: const { label, value, options, onChange, configuration } = props;
verwendet Destrukturierungszuweisung. So extrahieren Sie die Attribute, die zum Rendern erforderlich sind, aus den Eigenschaften, anstatt ihnen jedes Mal das Präfix props
voranzustellen, wenn sie verwendet werden.
React-Komponenten und -Hooks verwenden
Im Folgenden wird erläutert, wie ChoicesPickerComponent.tsx
React-Komponenten und -Hooks verwendet:
Artikel | Erläuterung |
---|---|
React.memo | Um unsere Funktionskomponente so zu verpacken, dass sie nicht gerendert wird, es sei denn, die Eingabeeigenschaften werden geändert. |
React.useMemo | Um sicherzustellen, dass das erstellte Elementarray nur mutiert wird, wenn die Eingabeeigenschaften options oder configuration geändert werden. Dies ist eine bewährte Methode für Funktionskomponenten, die unnötiges Rendering der untergeordneten Komponenten reduziert. |
React.useCallback | Um eine Rückrufschließung zu erstellen, die aufgerufen wird, wenn sich der ChoiceGroup -Wert der Fluent-Benutzeroberfläche ändern. Dieser React-Hook sorgt dafür, dass die Rückrufschließung nur mutiert wird, wenn sich die Eingabeeigenschaft onChange geändert hat. Dies ist eine bewährte Methode für die Leistung, ähnlich wie useMemo . |
Fehlerverhalten für Konfigurationseingabeeigenschaft
Wenn die Analyse der Eingabeeigenschaft der JSON-Konfiguration fehlschlägt, wird der Fehler mit items.error
gerendert.
Index.ts aktualisieren, um die ChoicesPicker-Komponente zu rendern
Sie müssen die generierte index.ts file
aktualisieren, um die ChoicesPickerComponent zu rendern.
Wenn Sie React innerhalb einer Codekomponente verwenden, wird das Rendern der Stammkomponente innerhalb der Methode updateView
durchgeführt. Alle Werte, die zum Rendern der Komponente erforderlich sind, werden an die Komponente übergeben, sodass sie geändert werden. Anschließend wird sie neu gerendert.
Importanweisungen hinzufügen und Symbole initialisieren
Bevor Sie die ChoicesPickerComponent
im index.ts
verwenden können, müssen Sie am Anfang der Datei Folgendes hinzufügen:
Hinweis
Der Import von initializeIcons
ist erforderlich, da Sie das Fluent UI-Symbolset verwenden. Sie müssen initializeIcons
aufrufen, um die Symbole im Testkabelbaum zu laden. In modellgesteuerten Apps sind sie bereits initialisiert.
Attribute zur ChoicesPicker-Klasse hinzufügen
Die Codekomponente behält ihren Instanzstatus mithilfe von Attributen bei. (Dies unterscheidet sich vom Zustand der React-Komponente). Fügen Sie in der index.ts
-ChoicesPicker
-Klasse folgende Attribute hinzu:
export class ChoicesPicker implements ComponentFramework.StandardControl<IInputs, IOutputs> {
Die folgende Tabelle erklärt diese Attribute:
Attribute | Beschreibung |
---|---|
notifyOutputChanged |
Enthält einen Verweis auf die Methode, die verwendet wird, um die modellgesteuerte App zu benachrichtigen, dass ein Benutzer einen Auswahlwert geändert hat und die Codekomponente bereit ist, ihn an den übergeordneten Kontext zurückzugeben. |
rootContainer |
HTML-DOM-Element, das erstellt wird, um die Codekomponente in der modellgesteuerten App zu speichern. |
selectedValue |
Hält den Status der vom Benutzer ausgewählten Auswahl, damit er in der getOutputs -Methode zurückgegeben werden kann. |
context |
Kontext des Power Apps Component Framework, der verwendet wird, um die im Manifest definierten Eigenschaften und andere Runtime-Eigenschaften zu lesen und auf API-Methoden zuzugreifen, wie z. B. trackContainerResize . |
Die init
-Methode aktualisieren
Um diese Attribute festzulegen, aktualisieren Sie die init
-Methode.
public init(
context: ComponentFramework.Context<IInputs>,
notifyOutputChanged: () => void,
state: ComponentFramework.Dictionary,
container: HTMLDivElement):
void {
// Add control initialization code
}
Die init
-Methode wird aufgerufen, wenn die Codekomponente zum ersten Mal auf einem App-Bildschirm initialisiert wird.
Die onChange
-Methode hinzufügen
Wenn der Benutzer den ausgewählten Wert ändert, müssen Sie notifyOutputChanged
aus dem onChange
-Ereignis abrufen.
Fügen Sie eine Funktion hinzu:
onChange = (newValue: number | undefined): void => {
this.selectedValue = newValue;
this.notifyOutputChanged();
};
Die getOutputs
-Methode aktualisieren
Tipp
Wenn Sie bereits Client-API-Skripts in modellgesteuerten Apps geschrieben haben, sind Sie möglicherweise daran gewöhnt, den Formularkontext zum Aktualisieren von Attributwerten zu verwenden. Codekomponenten sollten niemals auf diesen Kontext zugreifen. Verlassen Sie sich stattdessen auf notifyOutputChanged
und getOutputs
, um einen oder mehrere geänderte Werte bereitzustellen. Sie müssen nicht alle gebundenen Eigenschaften zurückgeben, die in der IOutput
-Schnittstelle, sondern nur diejenigen, die ihren Wert geändert haben.
Die updateView
-Methode aktualisieren
Aktualisieren Sie jetzt die updateView
um die ChoicesPickerComponent
zu rendern:
public updateView(context: ComponentFramework.Context<IInputs>): void {
// Add code to update control view
}
Beachten Sie, dass Sie die Beschriftung und die Optionen von context.parameters.value
abrufen und der value.raw
liefert die gewählte numerische Auswahl oder null
, wenn kein Wert ausgewählt ist.
Die destroy-Funktion bearbeiten
Schließlich müssen Sie eine Bereinigung durchführen, wenn die Codekomponente zerstört wird:
Weitere Informationen: ReactDOM.unmountComponentAtNode
Die Testumgebung starten
Stellen Sie sicher, dass alle Dateien gespeichert sind und am Terminal verwendet werden:
npm start watch
Sie sehen, dass die Testumgebung mit der Auswahl startet, die in einem neuen Browserfenster gerendert wird. Anfangs wird ein Fehler angezeigt, da die Zeichenfolgeneigenschaft configuration
den Standardwert val
hat. Legen Sie die Konfiguration so fest, dass sie die Standardoptionen der Testumgebung 0, 1 und 2 mit den folgenden Symbolen der Fluent UI abbildet:
{"0":"ContactInfo","1":"Send","2":"Phone"}
Wenn Sie die ausgewählte Option ändern, sehen Sie den Wert im Bereich Dateneingaben auf der rechten Seite. Wenn Sie den Wert ändern, zeigt die Komponente außerdem den zugehörigen Wert aktualisiert an.
Unterstützung des Schreibschutzes oder der Sicherheit auf Spaltenebene
Beim Erstellen von field
-Komponenten für modellgesteuerte Apps müssen Anwendungen den Steuerungsstatus respektieren, wenn sie aufgrund der Sicherheit auf Spaltenebene schreibgeschützt oder maskiert sind. Wenn die Codekomponente keine schreibgeschützte Benutzeroberfläche rendert, wenn die Spalte schreibgeschützt ist, es aber nicht sein sollte, kann eine Spalte unter bestimmten Umständen (z. B. wenn ein Datensatz inaktiv ist) vom Benutzer aktualisiert werden. Weitere Informationen: Sicherheit auf Spaltenebene, um den Zugriff zu steuern.
Bearbeiten Sie die updateView-Methode für schreibgeschützte Sicherheit und Sicherheit auf Spaltenebene
Bearbeiten Sie in index.ts
die updateView
-Methode, um den disabled
- und masked
-Kennzeichen den folgenden Code hinzuzufügen:
public updateView(context: ComponentFramework.Context<IInputs>): void {
const { value, configuration } = context.parameters;
if (value && value.attributes && configuration) {
ReactDOM.render(
React.createElement(ChoicesPickerComponent, {
label: value.attributes.DisplayName,
options: value.attributes.Options,
configuration: configuration.raw,
value: value.raw,
onChange: this.onChange,
}),
this.rootContainer,
);
}
}
value.security
wird in einer modellgesteuerten App nur dann ausgefüllt, wenn die Sicherheitskonfiguration auf Spaltenebene auf die gebundene Spalte angewendet wird.
Diese Werte können dann über ihre Eigenschaften an die React-Komponente übergeben werden.
ChoicesPickerComponent bearbeiten, um die deaktivierten und maskierten Eigenschaften hinzuzufügen
In ChoicesPickerComponent.tsx
können Sie die disabled
- und masked
-Eigenschaften akzeptieren, indem Sie sie zur ChoicesPickerComponentProps
-Schnittstelle hinzufügen:
export interface ChoicesPickerComponentProps {
label: string;
value: number | null;
options: ComponentFramework.PropertyHelper.OptionMetadata[];
configuration: string | null;
onChange: (newValue: number | undefined) => void;
}
ChoicesPickerComponent-Eigenschaften bearbeiten
Fügen Sie die neuen Attribute den Eigenschaften hinzu.
export const ChoicesPickerComponent = React.memo((props: ChoicesPickerComponentProps) => {
const { label, value, options, configuration, onChange } = props;
ChoicesPickerComponent-Rückgabeknoten bearbeiten
Sie können in der ChoicesPickerComponent
, bei Rückgabe der React-Knoten, diese neuen Eingabeeigenschaften verwenden, um sicherzustellen, dass die Auswahl deaktiviert oder maskiert ist
return (
<>
{items.error}
<ChoiceGroup
label={label}
options={items.choices}
selectedKey={valueKey}
onChange={onChangeChoiceGroup}
/>
</>
);
Hinweis
Sie dürften keinen Unterschied in der Testumgebung feststellen, da sie keine schreibgeschützten Felder oder Sicherheit auf Spaltenebene simulieren kann. Sie müssen dies testen, nachdem Sie das Steuerelement in einer modellgesteuerten Anwendung bereitgestellt haben.
Die Codekomponente reaktionsfähig machen
Codekomponenten können auf Web-, Tablet- und mobilen Apps gerendert werden. Es ist wichtig, den verfügbaren Platz zu berücksichtigen. Lassen Sie die Auswahlkomponente als Dropdownmenü rendern, wenn die verfügbare Breite eingeschränkt ist.
Die Dropdown-Komponente und -Symbole importieren
Die Komponente in ChoicesPickerComponent.tsx
rendert die kleine Version mit der Dropdown
-Komponente der Fluent-Benutzeroberfläche, also fügen Sie sie zu den Importen hinzu:
import { ChoiceGroup, IChoiceGroupOption } from '@fluentui/react/lib/ChoiceGroup';
import * as React from 'react';
FormFactor-Eigenschaft hinzufügen
Aktualisieren Sie die Codekomponente so, dass sie je nach einer neuen Eigenschaft formFactor
unterschiedlich gerendert wird. Fügen Sie der ChoicesPickerComponentProps
-Schnittstelle das folgende Attribut hinzu:
export interface ChoicesPickerComponentProps {
label: string;
value: number | null;
options: ComponentFramework.PropertyHelper.OptionMetadata[];
configuration: string | null;
onChange: (newValue: number | undefined) => void;
disabled: boolean;
masked: boolean;
}
FormFactor zu ChoicesPickerComponent-Eigenschaften hinzufügen
Fügen Sie formFactor
den Eigenschaften hinzu.
export const ChoicesPickerComponent = React.memo((props: ChoicesPickerComponentProps) => {
const { label, value, options, configuration, onChange, disabled, masked } = props;
Fügen Sie Methoden hinzu und ändern Sie sie, um Dropdown-Komponenten zu unterstützen
Die Dropdown-Komponente benötigt einige andere Rendering-Methoden.
Fügen Sie über der
ChoicesPickerComponent
Folgendes hinzu:const iconStyles = { marginRight: '8px' }; const onRenderOption = (option?: IDropdownOption): JSX.Element => { if (option) { return ( <div> {option.data && option.data.icon && ( <Icon style={iconStyles} iconName={option.data.icon} aria-hidden="true" title={option.data.icon} /> )} <span>{option.text}</span> </div> ); } return <></>; }; const onRenderTitle = (options?: IDropdownOption[]): JSX.Element => { if (options) { return onRenderOption(options[0]); } return <></>; };
Diese Methoden werden vom
Dropdown
verwendet, um das richtige Symbol neben dem Dropdownwert zu rendern.Fügen Sie eine neue
onChangeDropDown
-Methode hinzu.Wir brauchen eine
onChange
-Methode für dasDropdown
ähnlich desChoiceGroup
-Ereignishandlers. Fügen Sie direkt unter der vorhandenenonChangeChoiceGroup
die neueDropdown
-Version hinzu:const onChangeDropDown = React.useCallback( (ev: unknown, option?: IDropdownOption): void => { onChange(option ? (option.data.value as number) : undefined); }, [onChange], );
Die gerenderte Ausgabe hinzufügen
Nehmen Sie die folgenden Änderungen vor, um die neue formFactor
-Eigenschaft zu verwenden.
return (
<>
{items.error}
{masked && '****'}
{!items.error && !masked && (
<ChoiceGroup
label={label}
options={items.choices}
selectedKey={valueKey}
disabled={disabled}
onChange={onChangeChoiceGroup}
/>
)}
</>
);
Sie sehen, dass die ChoiceGroup
-Komponente ausgegeben wird, wenn formFactor
groß ist, und das Dropdown
genutzt wird, wenn er klein ist.
DropdownOptions zurückgeben
Als Letztes müssen Sie in ChoicesPickerComponent.tsx
die Optionsmetadaten ein wenig anders zuordnen als die, die von den ChoicesGroup
verwendet werden. Fügen Sie also im items
-Rückgabeblock unter den vorhandenen choices
options.map
Folgendes hinzu:
return {
error: configError,
choices: options.map((item) => {
return {
key: item.Value.toString(),
value: item.Value,
text: item.Label,
iconProps: { iconName: iconMapping[item.Value] },
} as IChoiceGroupOption;
}),
};
Index.ts bearbeiten
Jetzt, da die Auswahlkomponente basierend auf der formFactor
-Eigenschaft anders gerendert wird, müssen Sie den richtigen Wert aus dem Render-Aufruf in index.ts
übergeben.
Die Enumeration SmallFormFactorMaxWidth und FormFactors hinzufügen
Fügen Sie über der export class ChoicesPicker
-Klasse in index.ts
Folgendes hinzu.
const SmallFormFactorMaxWidth = 350;
const enum FormFactors {
Unknown = 0,
Desktop = 1,
Tablet = 2,
Phone = 3,
}
Die SmallFormFactorMaxWidth
ist die Breite bei Beginn des Renderns der Komponente mit der Dropdown
- anstatt der ChoiceGroup
-Komponente. Die FormFactors
enum
dient der Bequemlichkeit beim Abrufen von context.client.getFormFactor
.
Code hinzufügen, um formFactor zu erkennen
Fügen Sie Folgendes den React.createElement
-Eigenschaften Unterhalb der vorhandenen Eigenschaften hinzu:
React.createElement(ChoicesPickerComponent, {
label: value.attributes.DisplayName,
options: value.attributes.Options,
configuration: configuration.raw,
value: value.raw,
onChange: this.onChange,
disabled: disabled,
masked: masked,
}),
Updates für die Größenänderung anfordern
Da Sie context.mode.allocatedWidth
verwenden, müssen Sie der modellgesteuerten App mitteilen, dass Sie Updates erhalten möchten (über einen Aufruf an updateView
), wenn sich die verfügbare Breite ändert. Sie tun dies in der init
-Methode durch Hinzufügen eines Aufrufs zu context.mode.trackContainerResize
:
public init(
context: ComponentFramework.Context<IInputs>,
notifyOutputChanged: () => void,
state: ComponentFramework.Dictionary,
container: HTMLDivElement):
void {
this.notifyOutputChanged = notifyOutputChanged;
this.rootContainer = container;
this.context = context;
}
In der Testumgebung ausprobieren
Speichern Sie nun alle Änderungen, damit sie automatisch im Browserfenster der Testumgebung angezeigt werden (da npm start watch
noch von früher läuft). Sie können jetzt den Wert der Komponentencontainerbreite zwischen 349 und 350 umschalten. Sie sehen, wie sich das Rendering anders verhält. Sie können auch den Formfaktor von Web auf Telefon umstellen und sehe das gleiche Verhalten.
Lokalisierung
Wenn Sie mehrere Sprachen unterstützen möchten, kann Ihre Codekomponente eine Ressourcendatei enthalten, die Übersetzungen für Entwurfs- und Runtime-Zeichenfolgen bereitstellt.
Fügen Sie am Speicherort
ChoicesPicker\strings\ChoicesPicker.1033.resx
eine neue Datei hinzu. Wenn Sie Beschriftungen für ein anderes Gebietsschema hinzufügen möchten, ändern Sie die 1033 (en-us
) auf das Gebietsschema Ihrer Wahl.Verwenden Sie den Visual Studio Code-Ressourcen-Editor und geben Sie das Folgende ein:
Name des Dataflows Wert ChoicesPicker_Name
Choices Picker (modellbasiert) ChoicesPicker_Desc
Zeigt die Auswahlmöglichkeiten als Picker mit Symbolen an Value_Name
Wert Value_Desc
Das Feld choices, an das das Steuerelement gebunden werden soll Configuration_Name
Symbol Zuordnung Konfiguration Configuration_Desc
Konfiguration, die den Auswahlwert einem Fluent UI Symbol zuordnet. z. B. {"1":"ContactInfo","2":"Send"} Andernfalls legen Sie den Inhalt der .resx-Datei mit dem folgenden XML fest:
<?xml version="1.0" encoding="utf-8"?> <root> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/> <xsd:element name="root" msdata:IsDataSet="true"> <xsd:complexType> <xsd:choice maxOccurs="unbounded"> <xsd:element name="metadata"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="name" use="required" type="xsd:string"/> <xsd:attribute name="type" type="xsd:string"/> <xsd:attribute name="mimetype" type="xsd:string"/> <xsd:attribute ref="xml:space"/> </xsd:complexType> </xsd:element> <xsd:element name="assembly"> <xsd:complexType> <xsd:attribute name="alias" type="xsd:string"/> <xsd:attribute name="name" type="xsd:string"/> </xsd:complexType> </xsd:element> <xsd:element name="data"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/> <xsd:attribute ref="xml:space"/> </xsd:complexType> </xsd:element> <xsd:element name="resheader"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required"/> </xsd:complexType> </xsd:element> </xsd:choice> </xsd:complexType> </xsd:element> </xsd:schema> <resheader name="resmimetype"> <value>text/microsoft-resx</value> </resheader> <resheader name="version"> <value>2.0</value> </resheader> <resheader name="reader"> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <data name="ChoicesPicker_Name" xml:space="preserve"> <value>Choices Picker (Model Driven)</value> <comment/> </data> <data name="ChoicesPicker_Desc" xml:space="preserve"> <value>Shows choices as a picker with icons</value> <comment/> </data> <data name="Value_Name" xml:space="preserve"> <value>Value</value> <comment/> </data> <data name="Value_Desc" xml:space="preserve"> <value>The choices field to bind the control to</value> <comment/> </data> <data name="Configuration_Name" xml:space="preserve"> <value>Icon Mapping Configuration</value> <comment/> </data> <data name="Configuration_Desc" xml:space="preserve"> <value>Configuration that maps the choice value to a fluent ui icon. E.g. {"1":"ContactInfo","2":"Send"}</value> <comment/> </data> </root>
Tipp
Es wird nicht empfohlen,
resx
-Dateien direkt zu bearbeiten. Der Ressourceneditor Visual Studio Code oder eine Erweiterung für Visual Studio Code erleichtert dies.
Das Manifest für Ressourcenzeichenfolgen aktualisieren
Nachdem Sie nun über die Ressourcenzeichenfolgen verfügen, können Sie darauf verweisen, indem Sie die ControlManifest.Input.xml
wie folgt aktualisieren:
<?xml version="1.0" encoding="utf-8" ?>
<manifest>
<control namespace="SampleNamespace"
constructor="ChoicesPicker"
version="0.0.1"
display-name-key="ChoicesPicker"
description-key="ChoicesPicker description"
control-type="standard">
<external-service-usage enabled="false">
</external-service-usage>
<property name="value"
display-name-key="Value"
description-key="Value of the Choices Control"
of-type="OptionSet"
usage="bound"
required="true"/>
<property name="configuration"
display-name-key="Icon Mapping"
description-key="Configuration that maps the choice value to a fluent ui icon."
of-type="Multiple"
usage="input"
required="true"/>
<resources>
<code path="index.ts"
order="1"/>
</resources>
</control>
</manifest>
Sie sehen, dass:
- Die
display-name-key
- unddescription-key
-Werte zeigen nun auf den entsprechenden Schlüssel in derresx
-Datei. - Es gibt einen zusätzlichen Eintrag im
resources
-Element, das angibt, dass die Codekomponente Ressourcen aus der referenzierten Datei laden soll.
Wenn Sie zusätzliche Zeichenfolgen für die Verwendung in Ihrer Komponente benötigen, können Sie diese zur resx
hinzufügen und dann die Zeichenfolgen zur Runtime mit getString hinzufügen. Weitere Informationen: Implementieren der Lokalisierungs-API-Komponente.
Hinweis
Eine der Einschränkungen der Testumgebung besteht darin, dass keine Ressourcendateien geladen werden, sodass Sie die Komponente an Microsoft Dataverse bereitstellen müssen, um Ihre Komponente vollständig zu testen.
In einer modellgesteuerten App bereitstellen und konfigurieren
Nachdem Sie die grundlegende Funktionalität mit der Testumgebung getestet haben, müssen Sie die Komponente an Microsoft Dataverse bereitstellen, damit die Codekomponente in einer modellgesteuerten App von Anfang bis Ende vollständig getestet werden kann.
Stellen Sie in Ihrer Dataverse-Umgebung sicher, dass ein Herausgeber mit dem Präfix
samples
erstellt wurde:Dies könnte auch Ihr Herausgeber sein, vorausgesetzt, Sie aktualisieren den Herausgeber-Präfix-Parameter im Aufruf von pac pcf push unten. Weitere Informationen: Erstellen eines Lösungsherausgebers.
Nachdem Sie den Herausgeber gespeichert haben, können Sie die Microsoft Power Platform CLI für Ihre Umgebung autorisieren, damit Sie die kompilierte Codekomponente pushen können. Verwenden Sie Folgendes in der Befehlszeile:
pac auth create --url https://myorg.crm.dynamics.com
Ersetzen Sie
myorg.crm.dynamics.com
mit der URL Ihrer Dataverse-Umgebung. Melden Sie sich mit Systemadministrator oder Anpasserprivilegien an, wenn Sie dazu aufgefordert werden. Die von diesen Rollen bereitgestellten Berechtigungen werden benötigt, um Codekomponenten für Dataverse bereitzustellen.Verwenden Sie zum Bereitstellen Ihrer Codekomponente:
pac pcf push --publisher-prefix samples
Hinweis
Wenn Sie den Fehler
Missing required tool: MSBuild.exe/dotnet.exe
erhalten, fügen SieMSBuild.exe/dotnet.exe
in Path-Umgebungsvariable hinzu oder verwenden SieDeveloper Command Prompt for Visual Studio Code
. Sie müssen entweder Visual Studio 2019 für Windows & Mac oder Build-Tools für Visual Studio 2019 installieren. Stellen Sie sicher, dass Sie den Workload.NET build tools
verwenden, wie in den Voraussetzungen beschrieben.Nach Abschluss erstellt dieser Vorgang eine temporäre Lösung namens PowerAppTools_Samples in Ihrer Umgebung bereit. Die
ChoicesPicker
Codekomponente wird dieser Lösung hinzugefügt. Sie können die Codekomponente bei Bedarf später in Ihre Lösung verschieben. Weitere Informationen: Application Lifecycle Management (ALM) für Codekomponenten.Fügen Sie als Nächstes die Codekomponente zum Formular Kontakte hinzu, indem Sie zum Hauptformular im Klassischen Editor navigieren, wählen Sie Bevorzugte Kontaktmethode > Eigenschaften ändern > Registerkarte „Steuerelemente“ > Steuerelement hinzufügen > Auswahl auswählen > Hinzufügen aus.
Hinweis
Zukünftig wird der klassische Editor nicht benötigt, um Codekomponenten auf modellgesteuerten App-Formularen zu konfigurieren.
Legen Sie die folgenden Eigenschaften für die Komponente fest:
Legen Sie die Auswahl als Standard für Web, Telefon und Tablet fest.
Geben Sie die folgende Zeichenfolge für die Konfiguration der Symbolzuordnung indem Sie das Bearbeiten-Symbol und An einen statischen Wert binden auswählen.
{ "1":"ContactInfo", "2":"Send", "3":"Phone", "4":"Fax", "5":"DeliveryTruck" }
Dies sind die Fluent UI-Symbole, die für jeden Auswahlwert verwendet werden.
Wählen Sie die Registerkarte „Anzeigen“ aus und deaktivieren Sie Beschriftung im Formular anzeigen, da Sie die Beschriftung über der Auswahl anzeigen.
Speichern und veröffentlichen des Formulars.
Öffnen Sie einen Kontaktdatensatz in der modellgesteuerten App mit dem richtigen ausgewählten Formular. Sie sehen jetzt die
ChoicesPicker
Codekomponente anstelle des standardmäßigen Dropdown-Steuerelements. (Möglicherweise müssen Sie die Seite neu laden, damit die Komponente angezeigt wird).Hinweis
Sie werden möglicherweise feststellen, dass sich die Textausrichtung in der Testumgebung geringfügig von modellgesteuerten Apps unterscheidet. Dies liegt daran, dass die Testumgebung andere CSS-Regeln hat als modellgesteuerte Apps. Deshalb sollten Sie Ihre Codekomponente nach der Bereitstellung immer vollständig testen.
Nach der Bereitstellung an Dataverse debuggen
Wenn Sie weitere Änderungen an Ihrer Komponente vornehmen müssen, müssen Sie sie nicht jedes Mal bereitstellen. Verwenden Sie stattdessen die in Codekomponenten debuggen beschriebene Technik, um einen Fiddler AutoResponder zu erstellen, um die Datei von Ihrem lokalen Dateisystem zu laden, während npm start watch
läuft.
Hinweis
Möglicherweise müssen Sie nach der Bereitstellung in Dataverse kein Debuggung durchführen, wenn alle Funktionen mit dem Testkabelbaum getestet werden können. Es wird jedoch empfohlen, immer in Dataverse bereitzustellen und zu testen, bevor Sie Ihre Codekomponente verteilen.
Der AutoResponder würde ungefähr so aussehen:
REGEX:(.*?)((?'folder'css|html)(%252f|\/))?SampleNamespace\.ChoicesPicker[\.\/](?'fname'[^?]*\.*)(.*?)$
C:\repos\ChoicesPicker\out\controls\ChoicesPicker\${folder}\${fname}
Sie müssen in Ihrer Browsersitzung das Cache leeren und Aktualisieren erzwingen, damit die AutoResponder-Datei abgeholt wird. Nach dem Laden können Sie den Browser aktualisieren, da der Fiddler der Datei eine Cache-Steuerelementkopfzeile hinzufügt, um zu verhindern, dass sie zwischengespeichert wird.
Sobald Sie mit Ihren Änderungen fertig sind, können Sie die Patchversion im Manifest erhöhen und dann mit pac pcf push erneut bereitstellen.
Bisher haben Sie einen Entwicklungs-Build bereitgestellt, der nicht optimiert ist und zur Runtime langsamer ausgeführt wird. Sie können einen optimierten Build bereitstellen, indem Sie pac pcf push durch Bearbeiten der ChoicesPicker.pcfproj
verwenden. Fügen Sie unter dem OutputPath
Folgendes hinzu:
<PcfBuildMode>production</PcfBuildMode>
Ähnliche Artikel
Application Lifecycle Management (ALM) mit Microsoft Power Platform
Power Apps component framework-API-Referenz
Erstellen Sie Ihre erste Codekomponente
Debuggen von Code-Komponenten
Hinweis
Können Sie uns Ihre Präferenzen für die Dokumentationssprache mitteilen? Nehmen Sie an einer kurzen Umfrage teil. (Beachten Sie, dass diese Umfrage auf Englisch ist.)
Die Umfrage dauert etwa sieben Minuten. Es werden keine personenbezogenen Daten erhoben. (Datenschutzbestimmungen).