Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Lernprogramm erstellen Sie eine modellgesteuerte App-Komponente field und stellen die Komponente mithilfe von Visual Studio Code auf einem Formular bereit, konfigurieren und testen. Diese Codekomponente zeigt eine Reihe von Auswahlmöglichkeiten auf dem Formular mit einem Symbol neben jedem Auswahlwert an. Die Komponente verwendet einige der erweiterten Features modellgesteuerter Apps, z. B. Auswahlspaltendefinitionen (Metadaten) und Sicherheit auf Spaltenebene.
Zusätzlich zu diesen stellen Sie sicher, dass die Codekomponente den bewährten Methodenleitfaden folgt:
- Verwendung der Microsoft Fluent-Benutzeroberfläche für Konsistenz und Barrierefreiheit
- Lokalisierung der Codekomponentenbeschriftungen sowohl bei der Entwurfs- als auch zur Laufzeit
- Sicherheit, dass die Codekomponente metadatengesteuert ist, um die Wiederverwertbarkeit zu verbessern
- Gewährleistung, dass die Codekomponente entsprechend dem Formfaktor und der verfügbaren Breite gerendert wird, wobei eine kompakte Dropdownliste mit Symbolen angezeigt wird, wenn der Platz begrenzt ist.
Code
Sie können das vollständige Beispiel aus PowerApps-Samples/component-framework/ChoicesPickerControl/herunterladen.
Erstellen eines neuen pcfproj Projekts
Hinweis
Bevor Sie beginnen, stellen Sie sicher, dass Sie alle erforderlichen Komponenten installiert haben.
Um ein neues pcfproj zu erstellen:
Erstellen Sie einen neuen Ordner, um die Codekomponente zu speichern. Beispiel:
C:\repos\ChoicesPicker.Öffnen Sie Visual Studio Code und navigieren Sie zu
Datei > Ordner öffnen und wählen Sie dann den Ordner aus, der im vorherigen Schritt erstellt wurde. 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 hinzufügen, indem Sie code .in der Eingabeaufforderung verwenden, wenn das aktuelle Verzeichnis auf diesen Speicherort eingestellt ist.Verwenden Sie im neuen Visual Studio Code PowerShell-Terminal (Terminal>New Terminal) den Befehl "pac pcf init ", um ein neues Codekomponentenprojekt zu erstellen:
pac pcf init ` --namespace SampleNamespace ` --name ChoicesPicker ` --template field ` --run-npm-installoder verwenden Sie die Kurzform:
pac pcf init -ns SampleNamespace -n ChoicesPicker -t field -npm
Dadurch werden dem aktuellen Ordner neue ChoicesPicker.pcfproj und verwandte Dateien hinzugefügt, einschließlich einer package.json , die die erforderlichen Module definiert. Der obige Befehl führt auch den Befehl aus npm install , mit dem Sie die erforderlichen Module installieren können.
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.
Sie können sehen, dass die Vorlage eine index.ts Datei zusammen mit verschiedenen Konfigurationsdateien enthält. Dies ist der Ausgangspunkt Ihrer Codekomponente und enthält die in der Komponentenimplementierung beschriebenen Lebenszyklusmethoden.
Installieren der Microsoft Fluent-Benutzeroberfläche
Sie verwenden die Microsoft Fluent-Benutzeroberfläche und React zum Erstellen der Benutzeroberfläche. Daher müssen Sie diese als Abhängigkeiten installieren. Verwenden Sie folgendes, um die Abhängigkeiten zu installieren:
npm install react react-dom @fluentui/react
Dadurch werden die Module dem packages.json-Ordner hinzugefügt und in den 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-Benutzeroberfläche besteht darin, dass sie eine konsistente und hochgradig barrierefreie Benutzeroberfläche bietet.
Konfigurieren 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 – Bewährte Methoden und Anleitungen für Codekomponenten.
Bearbeiten des Manifests
Die ChoicesPicker\ControlManifest.Input.xml Datei definiert die Metadaten, die das Verhalten der Codekomponente beschreiben. Die Kontrollattribute enthalten bereits den Namespace und den Namen der Komponente.
Sie müssen die folgenden gebundenen und Eingabeeigenschaften definieren.
| Name | Usage | Typ | Description |
|---|---|---|---|
| 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 der Anwendungsentwickler die Code-Komponente zum Formular hinzufügt. Sie enthält eine JSON-Zeichenfolge, um zu konfigurieren, welche Symbole für jeden Auswahlwert verwendet werden können. |
Weitere Informationen: Eigenschaftselement.
Tipp
Sie können das XML möglicherweise leichter lesen, wenn Sie es so formatieren, dass Attribute in eigenen Zeilen erscheinen. Suchen und installieren Sie ein XML-Formatierungstool Ihrer Wahl im Visual Studio Code Marketplace: Suchen Sie nach XML-Formatierungserweiterungen.
Die folgenden Beispiele wurden mit Attributen in separaten Zeilen formatiert, damit sie leichter lesbar sind.
Vorhandene SampleProperty durch neue Eigenschaften ersetzen
Öffnen Sie das ChoicesPicker\ControlManifest.Input.xml, fügen Sie die folgenden Eigenschaftendefinitionen in das Steuerelement ein und ersetzen Sie das vorhandene sampleProperty:
<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:
Ihrem Projekt wird eine automatisch generierte Datei
ChoicesPicker\generated\ManifestTypes.d.tshinzugefügt. Diese wird im Rahmen des Erstellen-Prozesses aus demControlManifest.Input.xmlund stellt die Typen für die Interaktion mit den Eingabe-/Ausgabeeigenschaften bereit.Die Buildausgabe wird dem
outOrdner hinzugefügt. Diesbundle.jsist das transpilierte JavaScript, das im Browser ausgeführt wird. DieControlManifest.xmlist eine neu formatierte Version derControlManifest.Input.xmlDatei, die während der Bereitstellung verwendet wird.Hinweis
Ändern Sie den Inhalt der Ordner
generatedundoutnicht direkt. Sie werden im Rahmen des Build-Prozesses überschrieben.
Implementieren der React-Komponente "ChoicesPicker Fluent UI"
Wenn die Codekomponente React verwendet, muss eine einzelne Stammkomponente vorhanden sein, die innerhalb der updateView Methode gerendert wird. Fügen Sie im ChoicesPicker Ordner eine neue TypeScript-Datei namens ChoicesPickerComponent.tsxhinzu, und fügen Sie 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 verfügt über die Erweiterung tsx, eine TypeScript-Datei, die xml-Stilsyntax unterstützt, die von React verwendet wird. Sie wird durch den Buildprozess in Standard-JavaScript kompiliert.
ChoicesPickerComponent-Entwurfsnotizen
Dieser Abschnitt enthält Kommentare zum Design der ChoicesPickerComponent.
Es handelt sich um eine funktionale Komponente
Dies ist eine React-Funktionskomponente, aber auch eine Klassenkomponente. Dies basiert auf Ihrem bevorzugten Codierungsstil. Klassenkomponenten und funktionsbezogene Komponenten können auch im selben Projekt gemischt werden. Sowohl Funktions- als auch Klassenkomponenten verwenden die tsx von React verwendete XML-Stilsyntax. Weitere Informationen: Funktions- und Klassenkomponenten
Minimieren Sie die Größe von bundle.js
Beim Importieren der Fluent UI-Komponente ChoiceGroup mit pfadbasierten Importen anstelle von:
import { ChoiceGroup, IChoiceGroupOption } from '@fluentui/react';
wir verwenden:
import { ChoiceGroup, IChoiceGroupOption } from '@fluentui/react/lib/ChoiceGroup';
Auf diese Weise wird die Größe des Bundles kleiner, was zu geringeren Kapazitätsanforderungen und einer besseren Laufzeitleistung 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 |
Description |
|---|---|
label |
Wird zum Bezeichnen der Komponente verwendet. Ist an die vom übergeordneten Kontext bereitgestellte Metadatenfeldbeschriftung gebunden, wobei die in der modellgesteuerten App ausgewählte Benutzeroberflächensprache verwendet wird. |
value |
Verknüpft mit der im Manifest definierten Eingabeeigenschaft. Dies kann null sein, wenn der Datensatz neu ist oder das Feld nicht festgelegt ist. TypeScript null wird anstelle von undefined bei der Übergabe/Rückgabe von Eigenschaftswerten verwendet. |
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 jedes Element gerendert werden kann. |
configuration |
Der Zweck der Komponente besteht darin, ein Symbol für jede verfügbare Auswahl anzuzeigen. Die Konfiguration wird vom App-Maker bereitgestellt, wenn sie die Codekomponente zu einem Formular hinzufügen. Diese Eigenschaft akzeptiert eine JSON-Zeichenfolge, die jedem numerischen Auswahlwert einen Fluent UI-Symbolnamen zuordnet. Beispiel: {"0":"ContactInfo","1":"Send","2":"Phone"}. |
onChange |
Wenn der Benutzer die Auswahl ändert, löst die React-Komponente das onChange Ereignis aus. Die Codekomponente ruft dann die notifyOutputChanged So auf, dass die modellgesteuerte App die Spalte mit dem neuen Wert aktualisieren kann. |
Kontrollierte React-Komponente
Es gibt zwei Arten von React-Komponenten:
| Typ | Description |
|---|---|
| Unkontrolliert | Behalten Sie ihren internen Zustand bei und verwenden Sie die Eingabeprops nur als Standardwerte. |
| Gesteuert | Rendern den von den Komponenteneigenschaften übergebenen Wert. Wenn das onChange Ereignis die Prop-Werte nicht aktualisiert, wird dem Benutzer keine Änderung in der Benutzeroberfläche angezeigt. |
Dies ChoicesPickerComponent ist eine kontrollierte Komponente. Sobald die modellgesteuerte App den Wert (nach dem notifyOutputChanged Aufruf) aktualisiert hat, ruft sie den updateView neuen Wert auf, der dann an die Komponentenprops übergeben wird, was zu einem erneuten Rendern führt, das den aktualisierten Wert anzeigt.
Destrukturierungszuweisung
Die Zuordnung der props Konstante: const { label, value, options, onChange, configuration } = props; verwendet destrukturierende Zuordnung. Auf diese Weise extrahieren Sie die zum Rendern erforderlichen Attribute aus den Props, anstatt diese bei jeder Verwendung mit props zu versehen.
Verwendung von React-Komponenten und Hooks
Im Folgenden wird erläutert, wie ChoicesPickerComponent.tsx React-Komponenten und Hooks verwendet werden:
| Artikel | Explanation |
|---|---|
| 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 verändert wird, wenn sich die Eingabeprops options oder configuration geändert haben. 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 UI ändern. Dieser React-Hook stellt sicher, dass die Callback-Closure nur verändert wird, wenn das Eingabe-Prop onChange geändert wird. Dies ist eine bewährte Praxis in Bezug auf die Leistung, ähnlich wie useMemo. |
Fehlerverhalten für Konfigurationseingabeeigenschaft
Wenn die Analyse der JSON-Konfigurationseingabeeigenschaft fehlschlägt, wird der Fehler mithilfe von items.error dargestellt.
Aktualisieren Sie die index.ts, um die ChoicesPicker-Komponente zu rendern.
Sie müssen die generierte index.ts file aktualisieren, um die ChoicesPickerComponent zu rendern.
Bei Verwendung von React innerhalb einer Codekomponente wird das Rendern der Stammkomponente innerhalb der updateView Methode ausgeführt. Alle Werte, die zum Rendern der Komponente erforderlich sind, werden an die Komponente übergeben, sodass die Komponente beim Ändern der Werte erneut gerendert wird.
Hinzufügen von Importanweisungen und Initialisieren von Symbolen
Bevor Sie ChoicesPickerComponent im index.ts verwenden können, müssen Sie Folgendes oben in der Datei hinzufügen:
Hinweis
Der Import von initializeIcons wird benötigt, da Sie den Fluent UI-Symbolsatz verwenden. Sie müssen initializeIcons aufrufen, um die Symbole im Testkabelbaum zu laden. Innerhalb modellgesteuerter Apps werden sie bereits initialisiert.
Hinzufügen von Attributen zur ChoicesPicker-Klasse
Die Codekomponente verwaltet ihren Instanzstatus mithilfe von Attributen. (Dies unterscheidet sich vom React-Komponentenstatus). Fügen Sie innerhalb der index.tsChoicesPicker Klasse die folgenden Attribute hinzu:
export class ChoicesPicker implements ComponentFramework.StandardControl<IInputs, IOutputs> {
In der folgenden Tabelle werden die folgenden Attribute erläutert:
| Merkmal | Description |
|---|---|
notifyOutputChanged |
Enthält einen Verweis auf die Methode, mit der die modellgesteuerte App benachrichtigt wird, dass ein Benutzer einen Auswahlwert geändert hat und die Codekomponente bereit ist, sie an den übergeordneten Kontext zurückzugeben. |
rootContainer |
HTML-DOM-Element, das erstellt wird, um die Codekomponente in der modellgesteuerten App zu speichern. |
selectedValue |
Enthält den Zustand der vom Benutzer ausgewählten Auswahl, sodass er innerhalb der getOutputs Methode zurückgegeben werden kann. |
context |
Power Apps-Komponentenframework-Kontext, der verwendet wird, um die im Manifest definierten Eigenschaften und andere Laufzeiteigenschaften zu lesen, und Zugriff auf API-Methoden wie z. B. trackContainerResize zu erhalten. |
Aktualisieren der init Methode
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 auf einem App-Bildschirm initialisiert wird.
Hinzufügen der onChange Methode
Wenn der Benutzer den ausgewählten Wert ändert, müssen Sie notifyOutputChanged aus dem onChange-Ereignis abrufen.
Funktion hinzufügen:
onChange = (newValue: number | undefined): void => {
this.selectedValue = newValue;
this.notifyOutputChanged();
};
Aktualisieren der getOutputs Methode
Tipp
Wenn Sie bereits Client-API-Skripte in modellgesteuerten Apps geschrieben haben, sind Sie möglicherweise daran gewöhnt, den Formularkontext zu nutzen, um Attributwerte zu aktualisieren. Codekomponenten sollten niemals auf diesen Kontext zugreifen. Stattdessen verlassen Sie sich 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 definiert sind, nur diejenigen, die ihren Wert geändert haben.
Aktualisieren der updateView Methode
Aktualisieren Sie nun updateView, um 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 aus context.parameters.value ziehen, und die value.raw die numerische Auswahl bereitstellt oder null, wenn kein Wert ausgewählt ist.
Bearbeiten der Vernichtungsfunktion
Schließlich müssen Sie aufräumen, wenn die Codekomponente zerstört wird:
Weitere Informationen: ReactDOM.unmountComponentAtNode
Starten des Testgerüsts
Stellen Sie sicher, dass alle Dateien gespeichert sind und verwenden Sie am Terminal Folgendes:
npm start watch
Sie sehen, dass die Testumgebung mit der Auswahl startet, die in einem neuen Browserfenster gerendert wird. Zunächst wird ein Fehler angezeigt, da die Zeichenfolgeneigenschaft configuration den Standardwert valaufweist. 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, wird der Wert im Bereich "Dateneingaben " auf der rechten Seite angezeigt. Wenn Sie den Wert ändern, zeigt die Komponente außerdem den zugeordneten Wert an, der aktualisiert wurde.
Unterstützung von schreibgeschütztem Zugriff und 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 zum Steuern des Zugriffs.
Bearbeiten Sie die UpdateView-Methode für Nur-Lese-Zugriff und die Sicherheit auf Spaltenebene
Bearbeiten Sie in index.ts die updateView-Methode, um den folgenden Code hinzuzufügen, damit die disabled- und masked-Flags abgerufen werden:
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,
);
}
}
Die value.security Datei wird nur innerhalb einer modellgesteuerten App aufgefüllt, wenn die Sicherheitskonfiguration auf Spaltenebene auf die gebundene Spalte angewendet wird.
Diese Werte können dann durch ihre Props an die React-Komponente übergeben werden.
Ändern Sie die ChoicesPickerComponent, um die Eigenschaften "disabled" und "masked" hinzuzufügen.
In ChoicesPickerComponent.tsx können Sie die Eigenschaften disabled und masked akzeptieren, indem Sie sie der ChoicesPickerComponentProps Schnittstelle hinzufügen.
export interface ChoicesPickerComponentProps {
label: string;
value: number | null;
options: ComponentFramework.PropertyHelper.OptionMetadata[];
configuration: string | null;
onChange: (newValue: number | undefined) => void;
}
Bearbeiten von ChoicesPickerComponent-Eigenschaften
Fügen Sie die neuen Attribute zu den Props 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 in Web-, Tablet- und mobilen Apps gerendert werden. Es ist wichtig, den verfügbaren Platz zu berücksichtigen. Legen Sie fest, dass die Auswahlkomponente als Dropdown gerendert wird, wenn die verfügbare Breite eingeschränkt ist.
Importieren der Dropdownkomponente und der Symbole
Die Komponente in ChoicesPickerComponent.tsx rendert die kleine Version mit der Dropdown-Komponente der Fluent UI, 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 neuer Eigenschaft formFactoranders 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;
}
Die Eigenschaft formFactor zu den Eigenschaften von ChoicesPickerComponent hinzufügen
Fügen Sie formFactor zu den Props hinzu.
export const ChoicesPickerComponent = React.memo((props: ChoicesPickerComponentProps) => {
const { label, value, options, configuration, onChange, disabled, masked } = props;
Hinzufügen von Methoden und Ändern zur Unterstützung der Dropdownkomponente
Die Dropdownkomponente benötigt einige verschiedene Renderingmethoden.
Fügen Sie Folgendes über dem
ChoicesPickerComponenthinzu: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
Dropdownverwendet, um das richtige Symbol neben dem Dropdownwert zu rendern.Neue
onChangeDropDownMethode hinzufügen.Wir benötigen eine
onChangeMethode fürDropdownähnlich demChoiceGroupEreignishandler. Fügen Sie direkt unterhalb der vorhandenenonChangeChoiceGroupVersion die neueDropdownVersion hinzu:const onChangeDropDown = React.useCallback( (ev: unknown, option?: IDropdownOption): void => { onChange(option ? (option.data.value as number) : undefined); }, [onChange], );
Ändern der gerenderten Ausgabe
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 können sehen, dass Sie die ChoiceGroup-Komponente ausgeben, wenn formFactor groß ist, und Dropdown verwenden, wenn es klein ist.
DropdownOptions zurückgeben
Das Letzte, was wir in ChoicesPickerComponent.tsx tun müssen, ist, die Optionsmetadaten ein wenig anders zuzuordnen, als es beim ChoicesGroup der Fall ist. Daher fügen Sie im items Rückgabeblock, unter dem 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;
}),
};
"Bearbeite index.ts"
Da die Auswahlkomponente nun je nach dem formFactor-Prop anders gerendert wird, müssen Sie den richtigen Wert aus dem Renderaufruf innerhalb index.ts übergeben.
Add SmallFormFactorMaxWidth and FormFactors enum
Fügen Sie folgendes direkt über der export class ChoicesPicker Klasse innerhalb der Klasse hinzu index.ts.
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. Dies FormFactorsenum wird für den Komfort beim Anrufen context.client.getFormFactorverwendet.
Hinzufügen von Code zum Erkennen von formFactor
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,
}),
Aktualisierungen für Größenanpassung anfordern
Da Sie verwenden context.mode.allocatedWidth, müssen Sie der modellgesteuerten App mitteilen, dass Sie Updates (über einen Aufruf an updateView) empfangen möchten, wenn sich die verfügbare Breite ändert. Dies erfolgt innerhalb der init Methode, indem Sie einen Aufruf zu context.mode.trackContainerResize hinzufügen:
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 nun den Wert der Komponentencontainerbreite zwischen 349 und 350 wechseln und sehen, dass sich das Rendering anders verhält. Sie können auch den Formfaktor zwischen Web und Telefon austauschen und dasselbe Verhalten sehen.
Lokalisierung
Wenn Sie mehrere Sprachen unterstützen möchten, kann Ihre Codekomponente eine Ressourcendatei enthalten, die Übersetzungen für Entwurfs- und Laufzeitzeichenfolgen bereitstellt.
Fügen Sie am Speicherort
ChoicesPicker\strings\ChoicesPicker.1033.resxeine 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.Geben Sie im Visual Studio Code-Ressourcen-Editor Folgendes ein:
Name Wert ChoicesPicker_NameAuswahlfeld (modellgesteuert) ChoicesPicker_DescZeigt Auswahlmöglichkeiten als Auswahlliste mit Symbolen an. Value_NameWert Value_DescDas Feld choices, an das das Steuerelement gebunden werden soll Configuration_NameSymbolzuordnungskonfiguration Configuration_DescKonfiguration, die den Auswahlwert einem Fluent Ui-Symbol zuordnet. Z. B. {"1":"ContactInfo","2":"Send"} Legen Sie andernfalls den Inhalt der RESX-Datei mit dem folgenden XML-Code 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,
resxDateien direkt zu bearbeiten. Der Visual Studio Code-Ressourcen-Editor 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 folgendes ControlManifest.Input.xml 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 können folgendes sehen:
- Die
display-name-key- unddescription-key-Werte verweisen nun auf den entsprechenden Schlüssel in derresx-Datei. - Es gibt einen zusätzlichen Eintrag im
resourcesElement, der angibt, dass die Codekomponente Ressourcen aus der referenzierten Datei laden soll.
Wenn Sie zusätzliche Zeichenfolgen für die resx Verwendung in Ihrer Komponente benötigen, können Sie sie der Komponente hinzufügen und dann die Zeichenfolgen zur Laufzeit mithilfe von getString laden. Weitere Informationen: Implementieren der Lokalisierungs-API-Komponente.
Hinweis
Eine der Einschränkungen der Testnutzung besteht darin, dass ressourcendateien nicht geladen werden. Daher müssen Sie die Komponente für Microsoft Dataverse bereitstellen, um Ihre Komponente vollständig zu testen.
Bereitstellen und Konfigurieren in einer modellgesteuerten App
Nachdem Sie die grundlegende Funktionalität mit der Testumgebung getestet haben, müssen Sie die Komponente in Microsoft Dataverse bereitstellen, damit die Codekomponente vollständig in einer modellgesteuerten App 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 Herausgeberpräfix-Parameter im unten stehenden Aufruf von `pac pcf push`. 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 an der Befehlszeile Folgendes:
pac auth create --url https://myorg.crm.dynamics.comErsetzen Sie
myorg.crm.dynamics.comdurch die URL Ihrer Dataverse-Umgebung. Melden Sie sich bei Aufforderung mit Systemadministrator- oder Customizer-Berechtigungen an. Die von diesen Rollen bereitgestellten Berechtigungen sind erforderlich, um Codekomponenten auf Dataverse bereitzustellen.Verwenden Sie Folgendes, um Ihre Codekomponente bereitzustellen:
pac pcf push --publisher-prefix samplesHinweis
Wenn Sie den Fehler
Missing required tool: MSBuild.exe/dotnet.exeerhalten, fügen SieMSBuild.exe/dotnet.exezur Umgebungsvariable "Path" hinzu oder verwenden SieDeveloper Command Prompt for Visual Studio Code. Sie müssen entweder Visual Studio 2019 für Windows & Mac oder Buildtools für Visual Studio 2019 installieren. Stellen Sie sicher, dass Sie die.NET build toolsArbeitslast gemäß den in den Voraussetzungen beschriebenen Anweisungen auswählen.Nach Abschluss dieses Vorgangs wird eine temporäre Lösung namens PowerAppTools_samples in Ihrer Umgebung erstellt. Die
ChoicesPickerCodekomponente wird dieser Lösung hinzugefügt. Sie können die Codekomponente bei Bedarf später in Ihre Lösung verschieben. Weitere Informationen: Code Component Application Lifecycle Management (ALM).
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
In Zukunft wird der klassische Editor nicht benötigt, um Codekomponenten in modellgesteuerten Apps-Formularen zu konfigurieren.
Legen Sie die folgenden Eigenschaften für die Komponente fest:
Legen Sie die Auswahlauswahl als Standardeinstellung für Web, Smartphone und Tablet fest.
Geben Sie die folgende Zeichenfolge für die Symbolzuordnungskonfiguration ein, indem Sie das Bearbeitungssymbol auswählen 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 innerhalb der modellgesteuerten App, wobei das richtige Formular ausgewählt ist. Nun wird die
ChoicesPicker-Codekomponente anstelle des standardmäßigen Dropdown-Steuerelements angezeigt. (Möglicherweise müssen Sie die Seite erneut laden, damit die Komponente angezeigt wird).Hinweis
Möglicherweise sehen Sie, dass sich die Textausrichtung im Vergleich zu modellgesteuerten Apps in der Testumgebung geringfügig unterscheidet. Dies liegt daran, dass die Testumgebung unterschiedliche CSS-Regeln für modellgesteuerte Apps aufweist. Aus diesem Grund wird empfohlen, die Codekomponente nach der Bereitstellung immer vollständig zu testen.
Debuggen nach der Bereitstellung in Dataverse
Wenn Sie weitere Änderungen an Ihrer Komponente vornehmen müssen, brauchen Sie sie nicht jedes Mal zu deployen. 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 auf Dataverse nicht debuggen, wenn alle Funktionen mithilfe der Testumgebung getestet werden können. Es wird jedoch empfohlen, Ihre Codekomponente immer zuerst im Dataverse zu Bereitstellen und Testen, bevor Sie sie verteilen.
Der AutoResponder sieht ähnlich wie folgt aus:
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 Fiddler der Datei einen Cache-Control-Header hinzufügt, um zu verhindern, dass sie zwischengespeichert wird.
Nachdem Sie ihre Änderungen vorgenommen haben, 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 mithilfe von pac pcf push bereitstellen, indem Sie die Datei ChoicesPicker.pcfproj bearbeiten. Fügen Sie Folgendes unterhalb des OutputPath hinzu:
<PcfBuildMode>production</PcfBuildMode>
Verwandte Artikel
Application Lifecycle Management (ALM) mit Microsoft Power Platform
Power Apps component framework – API-Referenz
Erstellen Sie Ihre erste Komponente
Debuggen von Code-Komponenten