Présentation de la création d’un composant de code

Effectué

Power Apps fournit de nombreuses fonctionnalités intégrées permettant aux créateurs d’applications de créer leurs applications, mais vous devrez parfois créer des expériences utilisateur personnalisées pour répondre à vos besoins uniques, par exemple en remplaçant une valeur en pourcentage par une jauge, en affichant un code-barres plutôt qu’un ID ou en remplaçant des contrôles existants par des contrôles dotés de plus de fonctionnalités, comme une vue de grille glisser-déplacer. Vous pouvez également envelopper Power Apps Component Framework autour des composants existants que vous avez écrits dans d’autres infrastructures web telles que React ou Angular.

La création de ces composants vous permet d’exploiter pleinement l’écosystème de développement web moderne, notamment les bibliothèques, les infrastructures et d’autres outils que vous connaissez peut-être, et de packager cette fonctionnalité sous une forme permettant aux créateurs d’applications de créer des applications avec votre code, comme s’il s’agissait d’un élément prêt à l’emploi de la plateforme.

Les composants Power Apps personnalisés sont souvent appelés composants de code, car leur création nécessite du code personnalisé. Ils se composent de trois éléments : un manifeste, une implémentation et des ressources.

Dans l’exercice suivant, vous allez créer un composant de code personnalisé pour gérer un scénario pour votre société. Votre société souhaite que certains champs du formulaire de l’application soient en lecture seule jusqu’à ce que l’utilisateur lance manuellement une modification de la valeur des données. L’équipe a identifié qu’aucun des contrôles intégrés ne fonctionnerait et vous a donc demandé de créer un composant de code personnalisé.

Pour répondre à ce besoin, vous allez créer un composant personnalisé de champ modifiable qui ressemblera à l’image suivante. La valeur sera en lecture seule jusqu’à ce que l’utilisateur clique sur Modifier.

Capture d’écran du composant de code personnalisé.

Ce composant va écouter les modifications provenant de l’application hôte et permettre à l’utilisateur d’apporter des changements qui seront ensuite transmis à l’application hôte. Les étapes suivantes vous permettront de créer ce composant :

Installer Power Platform CLI

Pour préparer votre ordinateur à créer des composants de code, procédez comme suit :

  1. Installez Node.js (fourni avec npm). Nous vous recommandons d’utiliser une version LTS (Long-Term Support) telle que celle située ici. Vous pouvez vérifier que Node/NPM n’est pas déjà installé. Vous pouvez le faire en accédant à une invite de commande et en tapant ce qui suit :

    // Launch a standard command prompt and type both of the following
    
    npm --version
    Node --version
    

    Si vous recevez une erreur lors de l’exécution de ces commandes, vous devez installer Node.js à l’aide des liens ci-dessus.

    Une installation réussie de Node renvoie les numéros de version dans la fenêtre de commande lors de la saisie des commandes ci-dessus, comme indiqué ci-dessous :

    // If installed properly you will see something like the output below. The version numbers may be slightly different based on the version installed.
    
    C:\npm --version
    10.5.0
    
    C:\Node --version
    v20.12.2
    
  2. Installez Visual Studio Code.

  3. Installez l’extension Power Platform Tools. Veillez à terminer l’installation de Visual Studio Code avant d’installer Power Platform Tools.

    Power Platform Tools ne vous permet pas d’exécuter des commandes CLI pour Power Platform dans une invite de commande en dehors de Visual Studio Code. Nous vous recommandons d’installer également la CLI MSI pour Power Platform.

    Pour installer la CLI au niveau de Windows, suivez ces instructions. Vous pouvez installer simultanément la CLI et l’extension Power Platform Tools.

Créer un projet de composant

Avant de démarrer la création de composants, vérifiez que les composants installés répertoriés ci-dessus fonctionnent correctement. Les commandes NPM et CLI fonctionnent à partir d’une fenêtre de terminal dans Visual Studio Code. Si vous rencontrez des problèmes pour les exécuter correctement à partir de VS Code, vous pouvez choisir d’exécuter les commandes de terminal indiquées dans les étapes ci-dessous dans une invite de commande si vous avez installé la CLI pour Power Platform.

Dans Visual Studio Code, accédez à Terminal > Nouveau terminal (ou appuyez sur CTRL + SHFT +`). Dans la fenêtre Terminal de VS Code, répétez les instructions de version npm et Node. Si tout renvoie les numéros de version appropriés, vous pouvez procéder à la création de la solution.

// Test installs from Steps 1-3 listed above

// This will verify NPM installation
C:\npm --version
10.5.0

// This will verify Node installation
C:\Node --version
v20.12.2

// This will launch Visual Studio Code from the command line.
C:\Code

Maintenant que vous êtes prêt à créer un projet de composant, procédez comme suit pour démarrer :

Créez un répertoire où vous allez créer votre composant. Dans cet exemple, vous allez placer le composant dans C:\source\Editable-pcf. Vous allez créer votre propre répertoire à l’aide de Visual Studio Code. Vous pouvez également créer les dossiers à l’aide de l’invite de commande si vous rencontrez des problèmes avec l’utilisation du terminal VS Code.

  1. Lancez Visual Studio Code.

  2. Cliquez sur Terminal, puis sur Nouveau terminal.

    Capture d’écran illustrant un clic sur le bouton Nouveau terminal dans Visual Studio Code.

  3. Le dossier de votre session de terminal est défini par défaut sur le dernier dossier que vous avez utilisé. Ceci est illustré dans la zone d’invite de commande TERMINAL comme indiqué ci-dessous :

    //Note Your PS will not list exactly what is seen below, but will be specific to your starting path.
    
    PS C:\Users\Name\Folder
    

    Redéfinissez le répertoire sur un emplacement où vous souhaitez créer cette solution. La commande CD vous permet d’accéder à un emplacement approprié.

    Remarque

    Sachez que le dossier dans lequel vous exécutez NPM ou d’autres commandes est important. Vérifiez toujours que vous vous trouvez dans votre dossier Projects avant d’exécuter des commandes build. Ne pas le faire peut corrompre la build et provoquer des problèmes empêchant de produire des résultats optimaux.

    Vous pouvez créer un dossier à l’emplacement par défaut à l’aide de la commande md (make directory, ou créer un répertoire), comme indiqué ci-dessous dans la fenêtre de votre terminal VS Code.

    md source
    cd source
    

    Un répertoire nommé source est alors créé et vous êtes redirigé vers ce répertoire à l’aide de la commande cd (change directory, ou changer de répertoire).

  4. À partir de votre répertoire source créé, créez un répertoire nommé editable-pcf. Il s’agit de votre répertoire PROJECT où tous vos fichiers de projet sont stockés. Nous allons également redéfinir le répertoire sur notre nouveau répertoire Project.

    md editable-pcf
    cd editable-pcf
    

    Capture d’écran illustrant l’onglet Terminal avec des commandes permettant de créer un répertoire et d’en changer.

  5. Initialisez votre projet de composant à l’aide de la Power Platform CLI avec la commande suivante :

    pac pcf init --namespace SampleNamespace --name EditablePCF --template field
    

    L’image suivante illustre un exemple du résultat que vous devriez obtenir :

    Attention

    Si la commande PAC PCF INIT ne s’exécute pas dans une fenêtre de terminal dans VS Code et que vous avez installé la Power Platform CLI, vous pouvez choisir d’exécuter une invite de commande et le CD sur votre répertoire editable-pcf. Une fois que vous y êtes, vous pouvez saisir la commande dans l’invite de commande et elle fonctionne correctement. Vous devriez voir le même résultat que celui indiqué ci-dessus.

  6. Installez les outils de création de projet à l’aide de la commande npm install. Il se peut que certains avertissements s’affichent ; cependant, vous pouvez les ignorer. Vérifiez que vous vous trouvez dans votre répertoire PROJECT avant d’émettre cette commande.

    npm install
    

    Attention

    Si la commande npm install ne s’exécute pas dans une fenêtre de terminal dans VS Code et que vous avez installé la Power Platform CLI, vous pouvez choisir d’exécuter une invite de commande et le CD sur votre répertoire editable-pcf. Une fois que vous y êtes, vous pouvez saisir la commande dans l’invite de commande et elle fonctionne correctement.

    Vous pouvez vérifier que tout fonctionne en exécutant une commande DIR dans la fenêtre de terminal dans VS Code ou dans l’invite de commande si vous avez choisi d’effectuer la création en dehors de Visual Studio Code. Vous devriez voir une série de fichiers et de dossiers dans votre répertoire editable-pcf. Il s’agit du projet que vous avez créé au cours des étapes ci-dessus et par rapport auquel nous allons effectuer la création à l’aide de VS Code.

  7. Exécutez la commande ci-dessous pour ouvrir le projet dans Visual Studio Code ou si vous utilisez une invite de commande dans la fenêtre d’invite de commande. Cela devrait lancer votre projet créé dans VS Code.

    code -a .
    
  8. Le contenu du projet devrait ressembler à l’image ci-dessous.

    Capture d’écran illustrant les fichiers du projet.

Mettre à jour le manifeste de votre composant de code

Mettez à jour le fichier manifeste pour représenter avec précision votre contrôle.

  1. Développez le dossier EditablePCF, puis ouvrez le fichier ControlManifest.Input.xml.

    Capture d’écran illustrant le fichier ControlManifest.Input.xml.

  2. Définissez les valeurs version sur 1.0.0 et description-key sur Edits project name.

  3. Recherchez le nœud property.

  4. Définissez les valeurs name sur Name, display-name-key sur Name et description-key sur A name.

  5. Recherchez le nœud resources.

  6. Incluez une référence à un fichier CSS nommé editable-pcf.css que vous allez créer dans les étapes ci-dessous.

    <css path="css/EditablePCF.css" order="1" />
    

    Capture d’écran illustrant les modifications apportées au nœud resources.

  7. Enregistrez vos modifications en sélectionnant Fichier, puis Enregistrer ou appuyez sur Ctrl + S pour enregistrer le fichier.

Ajouter un style à votre composant de code

Pour ajouter un style à votre composant de code, procédez comme suit :

  1. Vérifiez que le fichier ControlManifest.Input.xml est toujours sélectionné, puis cliquez sur Nouveau dossier.

    Capture d’écran illustrant le bouton Ajouter un nouveau dossier.

  2. Nommez le nouveau dossier css.

  3. Sélectionnez le dossier css que vous avez créé, puis cliquez sur Nouveau fichier.

  4. Nommez le nouveau fichier EditablePCF.css (ou quel que soit le nom que vous avez donné au fichier CSS à l’étape 6 ci-dessus).

  5. Ouvrez le fichier EditablePCF.css que vous avez créé, puis collez l’extrait de code CSS suivant : Il s’agit du nom de référence de ressource que vous avez utilisé précédemment lorsque vous avez ajouté le code de chemin d’accès CSS au fichier manifeste.

    .SampleNamespace\.HelloPCF {
          font-size: 1.5em;
        }
    
  6. Le contenu du fichier CSS devrait maintenant ressembler à l’image ci-dessous :

    Capture d’écran illustrant le contenu du fichier CSS.

  7. Sélectionnez Fichier, puis Enregistrer ou appuyez sur Ctrl + S pour enregistrer le fichier.

Créer votre composant de code

Avant de pouvoir implémenter la logique de votre composant, vous devez exécuter une build sur votre composant, afin de vous assurer que les types TypeScript adéquats sont générés pour correspondre aux propriétés de votre document ControlManifest.xml.

Revenez au terminal dans VS Code et créez votre projet à l’aide de la commande suivante : Si, pour une raison quelconque, vous rencontrez des problèmes lors de l’utilisation du terminal dans Visual Studio Code, vous pouvez accéder à votre dossier à l’aide de l’invite de commande et exécuter la commande à partir de là.

Attention

Vérifiez que vous vous trouvez dans votre dossier PROJECT dans votre terminal avant d’émettre cette commande.

npm run build

Le composant est compilé dans le répertoire out/controls/EditablePCF. Les artefacts de build comprennent les suivants :

  • Dossier css

  • bundle.js : code source des composants groupés

  • ControlManifest.xml : fichier manifeste de composant réel chargé dans l’organisation Microsoft Dataverse

    Capture d’écran illustrant le contenu du dossier out.

Avertissement

L’erreur la plus courante généralement reçue ici est une faute de frappe dans le nom du fichier CSS que vous avez créé précédemment. Si cela se produit, renommez simplement les fichiers en conséquence et réexécutez la commande npm run build jusqu’à ce qu’elle s’exécute complètement sans erreur. Vérifiez votre section RESOURCE dans le fichier COntrolManifest.Input.xml par rapport au fichier créé dans le dossier CSS. Ils doivent correspondre à 100 %.

Implémenter la logique de votre composant de code

Pour implémenter la logique de votre composant de code, procédez comme suit une fois la build terminée à partir des étapes ci-dessus : Dans Visual Studio Code, recherchez un fichier nommé index.ts dans l’EXPLORATEUR. Nous allons commencer à y écrire le code de notre composant.

  1. Ouvrez le fichier index.ts dans Visual Studio Code.

  2. Au-dessus de la méthode constructor, insérez les variables privées suivantes :

    // The PCF context object\
    private context: ComponentFramework.Context<IInputs>;
    // The wrapper div element for the component\
    private container: HTMLDivElement;
    // The callback function to call whenever your code has made a change to a bound or output property\
    private notifyOutputChanged: () => void;
    // Flag to track if the component is in edit mode or not\
    private isEditMode: boolean;
    // Tracking variable for the name property\
    private name: string | null;
    
  3. Recherchez la méthode public init, puis remplacez-la par la méthode ci-dessous.

    public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement) {
    
        // Track all the things
        this.context = context;
        this.notifyOutputChanged = notifyOutputChanged;
        this.container = container;
        this.isEditMode = false;
    
        // Create the span element to hold the project name
        const message = document.createElement("span");
        message.innerText = `Project name ${this.isEditMode ? "" :context.parameters.Name.raw}`;
    
        // Create the textbox to edit the name
        const text = document.createElement("input");
        text.type = "text";
        text.style.display = this.isEditMode ? "block" : "none";
    
        if (context.parameters.Name.raw) {
            text.value = context.parameters.Name.raw;
            // Wrap the two above elements in a div to box out the content
            const messageContainer = document.createElement("div");
            messageContainer.appendChild(message);
            messageContainer.appendChild(text);
    
            // Create the button element to switch between edit and read modes
    
            const button = document.createElement("button");
            button.textContent = this.isEditMode ? "Save" : "Edit";
            button.addEventListener("click", () => { this.buttonClick(); });
    
            // Add the message container and button to the overall control container
            this.container.appendChild(messageContainer);
            this.container.appendChild(button);
        }
    
    }
    

    Avertissement

    Vous remarquerez peut-être que l’élément EventListener de buttonClick est souligné en rouge. Rassurez-vous : nous allons créer la méthode pour cet événement ci-dessous. Si vous voyez d’autres sections en rouge, vous pouvez vérifier que tout a été copié ou saisi correctement.

  4. Ajoutez une méthode de gestionnaire de clic sur un bouton. Ajoutez la méthode suivante sous la méthode init :

    public buttonClick() {
        // Get our controls via DOM queries
        const text = this.container.querySelector("input")!;
        const message = this.container.querySelector("span")!;
        const button = this.container.querySelector("button")!;
    
        // If not in edit mode, copy the current name value to the textbox
        if (!this.isEditMode) {
            text.value = this.name ?? "";
        } 
        else if (text.value != this.name) {
            // if in edit mode, copy the textbox value to name and call the notify callback
            this.name = text.value;
            this.notifyOutputChanged();
        }
    
        // flip the mode flag
        this.isEditMode = !this.isEditMode;
    
        // Set up the new output based on changes
        message.innerText = `Project name ${this.isEditMode ? "" : this.name}`;
        text.style.display = this.isEditMode ? "inline" : "none";
        text.value = this.name ?? "";
        button.textContent = this.isEditMode ? "Save" : "Edit";
    }
    
  5. Recherchez la méthode updateView, puis remplacez-la par la méthode ci-dessous.

    public updateView(context: ComponentFramework.Context<IInputs>): void {
    
    // Checks for updates coming in from outside
    
    this.name = context.parameters.Name.raw;
    const message = this.container.querySelector("span")!;
    message.innerText = `Project name ${this.name}`;
    }
    
  6. Recherchez la méthode getOutputs, puis remplacez-la par la méthode ci-dessous.

    public getOutputs(): IOutputs {
    return {
    // If our name variable is null, return undefined instead
    Name: this.name ?? undefined
    };
    }
    
  7. Recherchez la méthode destroy, puis remplacez-la par la méthode ci-dessous.

    public destroy() {
    // Remove the event listener we created in init
    this.container.querySelector("button")!.removeEventListener("click", this.buttonClick);
    }
    
  8. Votre fichier index.ts final devrait maintenant ressembler au code ci-dessous.

    import { IInputs, IOutputs } from "./generated/ManifestTypes";
    
    export class EditablePCF implements ComponentFramework.StandardControl<IInputs, IOutputs> {
    
        /**
        * Empty constructor.
        */
    
        // The PCF context object\
        private context: ComponentFramework.Context<IInputs>;
        // The wrapper div element for the component\
        private container: HTMLDivElement;
        // The callback function to call whenever your code has made a change to a bound or output property\
        private notifyOutputChanged: () => void;
        // Flag to track if the component is in edit mode or not\
        private isEditMode: boolean;
        // Tracking variable for the name property\
        private name: string | null;
    
        constructor()
        {
    
        }
    
        /**
        * Used to initialize the control instance. Controls can kick off remote server calls and other initialization actions here.
        * Data-set values are not initialized here, use updateView.
        * @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to property names defined in the manifest, as well as utility functions.
        * @param notifyOutputChanged A callback method to alert the framework that the control has new outputs ready to be retrieved asynchronously.
        * @param state A piece of data that persists in one session for a single user. Can be set at any point in a controls life cycle by calling 'setControlState' in the Mode interface.
        * @param container If a control is marked control-type='standard', it will receive an empty div element within which it can render its content.
        */
        public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement) {
    
            // Track all the things
            this.context = context;
            this.notifyOutputChanged = notifyOutputChanged;
            this.container = container;
            this.isEditMode = false;
    
            // Create the span element to hold the project name
    
            const message = document.createElement("span");
            message.innerText = `Project name ${this.isEditMode ? "" :context.parameters.Name.raw}`;
    
            // Create the textbox to edit the name
            const text = document.createElement("input");
            text.type = "text";
            text.style.display = this.isEditMode ? "block" : "none";
    
            if (context.parameters.Name.raw) {
                text.value = context.parameters.Name.raw;
                // Wrap the two above elements in a div to box out the content
                const messageContainer = document.createElement("div");
                messageContainer.appendChild(message);
                messageContainer.appendChild(text);
    
                // Create the button element to switch between edit and read modes
    
                const button = document.createElement("button");
                button.textContent = this.isEditMode ? "Save" : "Edit";
                button.addEventListener("click", () => { this.buttonClick(); });
    
                // Add the message container and button to the overall control container
                this.container.appendChild(messageContainer);
                this.container.appendChild(button);
            }
    
        }
    
        public buttonClick() {
            // Get our controls via DOM queries
    
            const text = this.container.querySelector("input")!;
            const message = this.container.querySelector("span")!;
            const button = this.container.querySelector("button")!;
    
            // If not in edit mode, copy the current name value to the textbox
    
            if (!this.isEditMode) {
                text.value = this.name ?? "";
            } 
            else if (text.value != this.name) {
    
                // if in edit mode, copy the textbox value to name and call the notify callback
                this.name = text.value;
                this.notifyOutputChanged();
            }
    
            // flip the mode flag
            this.isEditMode = !this.isEditMode;
    
            // Set up the new output based on changes
            message.innerText = `Project name ${this.isEditMode ? "" : this.name}`;
            text.style.display = this.isEditMode ? "inline" : "none";
            text.value = this.name ?? "";
            button.textContent = this.isEditMode ? "Save" : "Edit";
        }
    
        /**
        * Called when any value in the property bag has changed. This includes field values, data-sets, global values such as container height and width, offline status, control metadata values such as label, visible, etc.
        * @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to names defined in the manifest, as well as utility functions
        */
        public updateView(context: ComponentFramework.Context<IInputs>): void {
    
            // Checks for updates coming in from outside
            this.name = context.parameters.Name.raw;
            const message = this.container.querySelector("span")!;
            message.innerText = `Project name ${this.name}`;
        }
    
        /**
        * It is called by the framework prior to a control receiving new data.
        * @returns an object based on nomenclature defined in manifest, expecting object[s] for property marked as "bound" or "output"
        */
        public getOutputs(): IOutputs {
            return {
            // If our name variable is null, return undefined instead
            Name: this.name ?? undefined
            };
        }
    
        /**
        * Called when the control is to be removed from the DOM tree. Controls should use this call for cleanup.
        * i.e. cancelling any pending remote calls, removing listeners, etc.
        */
        public destroy() {
            // Remove the event listener we created in init
            this.container.querySelector("button")!.removeEventListener("click", this.buttonClick);
        }
    }
    

Recréer et exécuter votre composant de code

Pour recréer et exécuter votre composant de code, procédez comme suit :

  1. Maintenant que la logique de votre composant est implémentée, revenez au terminal et recréez-le à l’aide de la commande ci-dessous. Vous pouvez l’exécuter directement dans VS Code ou au moyen de l’invite de commande à condition d’accéder d’abord à votre dossier editable-pcf.

    npm run build
    
  2. La création devrait réussir.

    Capture d’écran illustrant le résultat de la création.

  3. Exécutez votre composant dans l’atelier de test de Node en exécutant la commande ci-dessous. Si vous ne l’avez pas fait auparavant, un navigateur devrait se lancer affichant votre composant venant d’être créé.

    npm start
    

    Remarque

    Vous pouvez également activer le mode Surveillance pour vous assurer que toute modification des ressources suivantes est effectuée automatiquement sans avoir à redémarrer l’atelier de test à l’aide de la commande npm start watch :

    • Fichier index.ts

    • Fichier ControlManifest.Input.xml

    • Bibliothèques importées dans index.ts

    • Toutes les ressources répertoriées dans le fichier manifeste

  4. Une nouvelle fenêtre de navigateur devrait charger l’atelier de test. (La fenêtre devrait s’ouvrir automatiquement, mais vous pouvez également référencer l’adresse se trouvant dans la fenêtre de commande.)

  5. Cliquez sur Modifier.

    Capture d’écran illustrant le bouton Modifier dans l’atelier de test.

  6. Saisissez Projet 1, puis cliquez sur Enregistrer.

  7. Vous pouvez modifier la taille du conteneur.

  8. L’atelier de test devrait maintenant ressembler à l’image ci-dessous :

    Capture d’écran illustrant le contrôle dans l’atelier de test.

  9. Fermez la fenêtre de navigateur de l’atelier de test.

  10. Revenez au terminal ou à votre invite de commande (si vous n’utilisez pas le terminal VS Code) et arrêtez le Watcher en appuyant longuement sur [Ctrl] + C.

  11. Tapez Y, puis appuyez sur [ENTRÉE].