Share via


Een dashboardwidget toevoegen

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Widgets op een dashboard worden geïmplementeerd als bijdragen in het extensieframework. Eén extensie kan meerdere bijdragen hebben. Meer informatie over het maken van een extensie met meerdere widgets als bijdragen.

Dit artikel is onderverdeeld in drie delen, elk gebouw op het vorige - beginnend met een eenvoudige widget en eindigend met een uitgebreide widget.

Tip

Bekijk onze nieuwste documentatie over uitbreidingsontwikkeling met behulp van de Azure DevOps Extension SDK.

Voorbereiding en vereiste installatie voor deze zelfstudie

Voor het maken van extensies voor Azure DevOps of TFS zijn er enkele vereiste software en hulpprogramma's die u nodig hebt:

Kennis: Enige kennis van JavaScript, HTML, CSS is vereist voor widgetontwikkeling.

  • Een organisatie in Azure DevOps voor het installeren en testen van uw widget. Meer informatie vindt u hier
  • Een teksteditor. Voor veel van de zelfstudies hebben we gebruiktVisual Studio Code, die hier kunnen worden gedownload
  • De nieuwste versie van het knooppunt, die hier kan worden gedownload
  • Platformoverschrijdende CLI voor Azure DevOps (tfx-cli) om uw extensies te verpakken.
    • tfx-cli kan worden geïnstalleerd met behulp npmvan, een onderdeel van Node.js door uit te voeren npm i -g tfx-cli
  • Een basismap voor uw project. Deze map wordt in de zelfstudie genoemd home .

Bestandsstructuur extensie:

|--- README.md
|--- sdk    
    |--- node_modules           
    |--- scripts
        |--- VSS.SDK.min.js       
|--- img                        
    |--- logo.png                           
|--- scripts                        
|--- hello-world.html               // html page to be used for your widget  
|--- vss-extension.json             // extension's manifest

Wat u vindt in de zelfstudie

  1. In het eerste deel van deze handleiding ziet u hoe u een nieuwe widget maakt, waarmee een eenvoudig bericht 'Hallo wereld' wordt afgedrukt.
  2. Het tweede deel bouwt voort op het eerste onderdeel door een aanroep toe te voegen aan een Azure DevOps REST API.
  3. In het derde deel wordt uitgelegd hoe u configuratie toevoegt aan uw widget.

Notitie

Als u haast hebt en meteen de code in handen wilt krijgen, kunt u de voorbeelden hier downloaden. Nadat u het bestand hebt gedownload, gaat u naar de widgets map en volgt u stap 6 en stap 7 rechtstreeks om de voorbeeldextensie te publiceren met de drie voorbeeldwidgets met verschillende complexiteiten.

Ga aan de slag met enkele basisstijlen voor widgets die we kant-en-klare bieden voor u en enkele richtlijnen voor widgetstructuur.

Deel 1: Hallo wereld

In dit deel wordt een widget weergegeven waarmee 'Hallo wereld' wordt afgedrukt met behulp van JavaScript.

Overview dashboard with a sample widget

Stap 1: de client-SDK ophalen - VSS.SDK.min.js

Met het SDK-kernscript VSS.SDK.min.jskunnen webextensies communiceren met het Azure DevOps-frame van de host. Het script voert bewerkingen uit zoals initialiseren, het melden van de extensie wordt geladen of het ophalen van context over de huidige pagina. Haal het client-SDK-bestand VSS.SDK.min.js op en voeg het toe aan uw web-app. Plaats deze in de home/sdk/scripts map.

Gebruik de opdracht npm install om de SDK op te halen:

npm install vss-web-extension-sdk

Ga naar de GitHub-pagina client-SDK voor meer informatie over de SDK.

Stap 2: uw HTML-pagina - hello-world.html

Uw HTML-pagina is de lijm die uw indeling bij elkaar houdt en verwijzingen naar CSS en JavaScript bevat. U kunt dit bestand een naam geven, zorg ervoor dat u alle verwijzingen hello-world bijwerkt met de naam die u gebruikt.

Uw widget is gebaseerd op HTML en wordt gehost in een iframe. Voeg de onderstaande HTML toe in hello-world.html. We voegen de verplichte verwijzing naar VSS.SDK.min.js het bestand toe en voegen een h2 element toe in de , die wordt bijgewerkt met de tekenreeks Hallo wereld in de volgende stap.

    <!DOCTYPE html>
    <html>
        <head>          
            <script src="sdk/scripts/VSS.SDK.min.js"></script>              
        </head>
        <body>
            <div class="widget">
                <h2 class="title"></h2>
            </div>
        </body>
    </html>

Hoewel we een HTML-bestand gebruiken, worden de meeste HTML-hoofdelementen anders dan script en koppeling genegeerd door het framework.

Stap 3: Uw JavaScript

We gebruiken JavaScript om inhoud in de widget weer te geven. In dit artikel verpakken we al onze JavaScript-code in een &lt;script&gt; element in het HTML-bestand. U kunt ervoor kiezen om deze code in een afzonderlijk JavaScript-bestand te plaatsen en ernaar te verwijzen in het HTML-bestand. De code geeft de inhoud weer. Met deze JavaScript-code wordt ook de VSS SDK geïnitialiseerd, wordt de code voor uw widget toegewezen aan de naam van de widget en wordt het extensieframework van geslaagde of mislukte widgets op de hoogte gesteld. In ons geval is hieronder de code die 'Hallo wereld' in de widget zou afdrukken. Voeg dit script element toe aan de head HTML-code.

    <script type="text/javascript">
        VSS.init({                        
            explicitNotifyLoaded: true,
            usePlatformStyles: true
        });

        VSS.require("TFS/Dashboards/WidgetHelpers", function (WidgetHelpers) {
            WidgetHelpers.IncludeWidgetStyles();
            VSS.register("HelloWorldWidget", function () {                
                return {
                    load: function (widgetSettings) {
                        var $title = $('h2.title');
                        $title.text('Hello World');

                        return WidgetHelpers.WidgetStatusHelper.Success();
                    }
                }
            });
            VSS.notifyLoadSucceeded();
        });
    </script>

VSS.init initialiseert de handshake tussen het iframe dat als host fungeert voor de widget en het hostframe. We geven door explicitNotifyLoaded: true zodat de widget de host expliciet kan informeren wanneer we klaar zijn met laden. Met dit besturingselement kunnen we de voltooiing van de belasting melden nadat we ervoor hebben gezorgd dat de afhankelijke modules worden geladen. We geven door usePlatformStyles: true zodat de Azure DevOps-kernstijlen voor HTML-elementen (zoals hoofdtekst, div enzovoort) kunnen worden gebruikt door de widget. Als de widget deze stijlen liever niet gebruikt, kunnen ze doorgeven usePlatformStyles: false.

VSS.require wordt gebruikt om de vereiste VSS-scriptbibliotheken te laden. Met een aanroep van deze methode worden automatisch algemene bibliotheken, zoals JQuery en JQueryUI, geladen. In ons geval zijn we afhankelijk van de WidgetHelpers-bibliotheek, die wordt gebruikt om de widgetstatus aan het widgetframework te communiceren. Daarom geven we de bijbehorende modulenaam TFS/Dashboards/WidgetHelpers en een callback door aan VSS.require. De callback wordt aangeroepen zodra de module is geladen. De callback bevat de rest van de JavaScript-code die nodig is voor de widget. Aan het einde van de callback roepen VSS.notifyLoadSucceeded we aan om de voltooiing van de belasting te melden.

WidgetHelpers.IncludeWidgetStyles bevat een opmaakmodel met enkele basis-css om u op weg te helpen. Zorg ervoor dat u uw inhoud inpakt in een HTML-element met klasse widget om gebruik te maken van deze stijlen.

VSS.register wordt gebruikt om een functie toe te wijzen in JavaScript, waarmee de widget uniek wordt geïdentificeerd tussen de verschillende bijdragen in uw extensie. De naam moet overeenkomen met de id naam die uw bijdrage identificeert, zoals beschreven in stap 5. Voor widgets moet de functie die wordt doorgegeven VSS.register een object retourneren dat voldoet aan het IWidget contract, bijvoorbeeld dat het geretourneerde object een load-eigenschap moet hebben waarvan de waarde een andere functie is die de kernlogica heeft om de widget weer te geven. In ons geval is het om de tekst van het h2 element bij te werken naar 'Hallo wereld'. Dit is deze functie die wordt aangeroepen wanneer het widgetframework uw widget instantieert. We gebruiken de WidgetStatusHelper widgethelpers om de WidgetStatus als succes te retourneren.

Waarschuwing

Als de naam die wordt gebruikt om de widget te registreren niet overeenkomt met de id voor de bijdrage in het manifest, werkt de widget onverwacht.

De vss-extension.json map moet altijd in de hoofdmap staan (in deze handleiding). HelloWorld Voor alle andere bestanden kunt u ze in de gewenste structuur in de map plaatsen, zorg ervoor dat u de verwijzingen op de juiste manier bijwerkt in de HTML-bestanden en in het vss-extension.json manifest.

Stap 4: het logo van uw extensie: logo.png

Uw logo wordt weergegeven in Marketplace en in de widgetcatalogus zodra een gebruiker uw extensie installeert.

U hebt een cataloguspictogram van 98 px x 98 px nodig. Kies een afbeelding, geef deze logo.pngeen naam en plaats deze in de img map.

Ter ondersteuning van TFS 2015 Update 3 hebt u een extra afbeelding nodig die 330 px x 160 px is. Deze voorbeeldafbeelding wordt weergegeven in deze catalogus. Kies een afbeelding, geef deze preview.pngeen naam en plaats deze in de img map zoals voorheen.

U kunt deze installatiekopieën de gewenste naam opgeven zolang het extensiemanifest in de volgende stap wordt bijgewerkt met de namen die u gebruikt.

Stap 5: het manifest van uw extensie: vss-extension.json

Maak een json-bestand (vss-extension.jsonbijvoorbeeld) in de home map met de volgende inhoud:

    {
        "manifestVersion": 1,
        "id": "vsts-extensions-myExtensions",
        "version": "1.0.0",
        "name": "My First Set of Widgets",
        "description": "Samples containing different widgets extending dashboards",
        "publisher": "fabrikam",
        "categories": ["Azure Boards"],
        "targets": [
            {
                "id": "Microsoft.VisualStudio.Services"
            }
        ],
        "icons": {
            "default": "img/logo.png"
        },
        "contributions": [
            {
                "id": "HelloWorldWidget",
                "type": "ms.vss-dashboards-web.widget",
                "targets": [
                    "ms.vss-dashboards-web.widget-catalog"
                ],
                "properties": {
                    "name": "Hello World Widget",
                    "description": "My first widget",
                    "catalogIconUrl": "img/CatalogIcon.png",
                    "previewImageUrl": "img/preview.png",                            
                    "uri": "hello-world.html",
                    "supportedSizes": [
                         {
                                "rowSpan": 1,
                                "columnSpan": 2
                            }
                        ],
                    "supportedScopes": ["project_team"]
                }
            }
        ],
        "files": [
            {
                "path": "hello-world.html", "addressable": true
            },
            {
                "path": "sdk/scripts", "addressable": true
            },
            {
                "path": "img", "addressable": true
            }
        ]
    }

Zie de referentie voor het extensiemanifest voor meer informatie over vereiste kenmerken

Notitie

De uitgever moet hier worden gewijzigd in de naam van uw uitgever. Als u nu een uitgever wilt maken, gaat u naar Package/Publish/Install.

Pictogrammen

De pictogrammen stanza geeft het pad naar het pictogram van uw extensie in uw manifest.

Bijdragen

Elke bijdragevermelding definieert eigenschappen.

  • De id om uw bijdrage te identificeren. Deze id moet uniek zijn binnen een extensie. Deze id moet overeenkomen met de naam die u in stap 3 hebt gebruikt om uw widget te registreren.
  • Het type bijdrage. Voor alle widgets moet het type zijn ms.vss-dashboards-web.widget.
  • De matrix met doelen waaraan de bijdrage bijdraagt. Voor alle widgets moet het doel zijn [ms.vss-dashboards-web.widget-catalog].
  • De eigenschappen zijn objecten met eigenschappen voor het bijdragetype. Voor widgets zijn de volgende eigenschappen verplicht.
Eigenschappen Beschrijving
name De naam van de widget die moet worden weergegeven in de widgetcatalogus.
beschrijving Beschrijving van de widget die moet worden weergegeven in de widgetcatalogus.
catalogIconUrl Relatief pad van het cataloguspictogram dat u in stap 4 hebt toegevoegd om weer te geven in de widgetcatalogus. De afbeelding moet 98 px x 98 px zijn. Als u een andere mapstructuur of een andere bestandsnaam hebt gebruikt, geeft u hier het juiste relatieve pad op.
previewImageUrl Relatief pad van de voorbeeldafbeelding die u in stap 4 hebt toegevoegd om alleen weer te geven in de widgetcatalogus voor TFS 2015 Update 3. De afbeelding moet 330 px x 160 px zijn. Als u een andere mapstructuur of een andere bestandsnaam hebt gebruikt, geeft u hier het juiste relatieve pad op.
uri Relatief pad van het HTML-bestand dat u in stap 1 hebt toegevoegd. Als u een andere mapstructuur of een andere bestandsnaam hebt gebruikt, geeft u hier het juiste relatieve pad op.
supportedSizes Matrix met grootten die door uw widget worden ondersteund. Wanneer een widget meerdere grootten ondersteunt, is de eerste grootte in de matrix de standaardgrootte van de widget. De widget size waarde wordt opgegeven voor de rijen en kolommen die worden bezet door de widget in het dashboardraster. Eén rij/kolom komt overeen met 160 px. Elke dimensie boven 1x1 krijgt een extra 10 px die de rugmarge tussen widgets vertegenwoordigt. Een 3x2-widget is 160*3+10*2 bijvoorbeeld breed en 160*2+10*1 hoog. De maximale ondersteunde grootte is 4x4.
supportedScopes Op dit moment ondersteunen we alleen teamdashboards. De waarde moet zijn project_team. Wanneer we in de toekomst andere dashboardbereiken ondersteunen, zijn er hier meer opties om uit te kiezen.

Files

In de bestanden worden de bestanden vermeld die u wilt opnemen in uw pakket: uw HTML-pagina, uw scripts, het SDK-script en uw logo. Ingesteld addressable op true tenzij u andere bestanden opneemt die niet url-adresseerbaar hoeven te zijn.

Notitie

Raadpleeg de referentie voor het extensiemanifest voor meer informatie over het extensiemanifestbestand, zoals de eigenschappen en wat ze doen.

Stap 6: Verpakken, publiceren en delen

Zodra u uw extensie hebt geschreven, is de volgende stap bij het inpakken van de extensie in Marketplace om al uw bestanden samen te verpakken. Alle extensies zijn verpakt als VSIX 2.0-compatibele .vsix-bestanden. Microsoft biedt een platformoverschrijdende opdrachtregelinterface (CLI) om uw extensie te verpakken.

Het verpakkingshulpmiddel ophalen

U kunt de platformoverschrijdende CLI voor Azure DevOps (tfx-cli) installeren of bijwerken met behulp npmvan een onderdeel van Node.js vanaf de opdrachtregel.

npm i -g tfx-cli

Uw extensie verpakken

Het verpakken van uw extensie in een .vsix-bestand is moeiteloos zodra u de tfx-cli hebt. Ga naar de basismap van uw extensie en voer de volgende opdracht uit.

tfx extension create --manifest-globs vss-extension.json

Notitie

De versie van een extensie/integratie moet bij elke update worden verhoogd.
Wanneer u een bestaande extensie bijwerkt, werkt u de versie in het manifest bij of geeft u de --rev-version opdrachtregelswitch door. Hiermee wordt het patchversienummer van uw extensie verhoogd en wordt de nieuwe versie opgeslagen in uw manifest.

Nadat u de verpakte extensie in een .vsix-bestand hebt, kunt u de extensie publiceren naar Marketplace.

Uitgever voor de extensie maken

Alle extensies, inclusief extensies van Microsoft, worden geïdentificeerd als geleverd door een uitgever. Als u nog geen lid bent van een bestaande uitgever, maakt u er een.

  1. Meld u aan bij de Visual Studio Marketplace-publicatieportal
  2. Als u nog geen lid bent van een bestaande uitgever, wordt u gevraagd een uitgever te maken. Als u niet wordt gevraagd om een uitgever te maken, schuift u omlaag naar de onderkant van de pagina en selecteert u Extensies publiceren onder Verwante sites.
    • Geef een id op voor uw uitgever, bijvoorbeeld: mycompany-myteam
      • De id wordt gebruikt als de waarde voor het kenmerk in het publisher manifestbestand van uw extensies.
    • Geef een weergavenaam op voor uw uitgever, bijvoorbeeld: My Team
  3. Controleer de Marketplace Publisher-overeenkomst en selecteer Maken

De uitgever is nu gedefinieerd. In een toekomstige release kunt u machtigingen verlenen om de extensies van uw uitgever weer te geven en te beheren. Het is eenvoudig en veiliger voor teams en organisaties om extensies te publiceren onder een gemeenschappelijke uitgever, maar zonder dat u een set referenties hoeft te delen voor een set gebruikers.

Werk het vss-extension.json manifestbestand in de voorbeelden bij om de dummy-uitgever-id te vervangen door uw uitgevers-id fabrikam .

De extensie publiceren en delen

Nadat u een uitgever hebt gemaakt, kunt u nu uw extensie uploaden naar Marketplace.

  1. Zoek de knop Nieuwe extensie uploaden, navigeer naar het verpakte VSIX-bestand en selecteer uploaden.

U kunt uw extensie ook uploaden via de opdrachtregel met behulp van de tfx extension publish opdracht in plaats van tfx extension create uw extensie in één stap te verpakken en te publiceren. U kunt eventueel --share-with uw extensie delen met een of meer accounts na publicatie. U hebt ook een persoonlijk toegangstoken nodig.

tfx extension publish --manifest-globs your-manifest.json --share-with yourOrganization

Stap 7: Widget toevoegen uit de catalogus

  1. Ga naar uw project in Azure DevOps, http://dev.azure.com/{yourOrganization}/{yourProject}

  2. Selecteer Overzicht en selecteer vervolgens Dashboards.

  3. Kies Een widget toevoegen.

  4. Markeer uw widget en selecteer vervolgens Toevoegen.

    De widget wordt weergegeven op uw dashboard.

Deel 2: Hallo wereld met Azure DevOps REST API

Widgets kunnen een van de REST API's in Azure DevOps aanroepen om te communiceren met Azure DevOps-resources. In dit voorbeeld gebruiken we de REST API voor WorkItemTracking om informatie over een bestaande query op te halen en enkele querygegevens weer te geven in de widget direct onder de tekst 'Hallo wereld'.

Overview dashboard with a sample widget using the REST API for WorkItemTracking.

Stap 1: HTML

Kopieer het bestand hello-world.html uit het vorige voorbeeld en wijzig de naam van de kopie in hello-world2.html. Uw map ziet er nu als volgt uit:

|--- README.md
|--- sdk    
    |--- node_modules           
    |--- scripts
        |--- VSS.SDK.min.js       
|--- img                        
    |--- logo.png                           
|--- scripts                        
|--- hello-world.html               // html page to be used for your widget  
|--- hello-world2.html              // renamed copy of hello-world.html
|--- vss-extension.json             // extension's manifest

Voeg een nieuw div-element toe direct onder de h2 om de querygegevens op te nemen. Werk de naam van de widget van 'HelloWorldWidget' bij naar 'HelloWorldWidget2' in de regel waar u VSS.register aanroept. Hierdoor kan het framework de widget in de extensie uniek identificeren.
<!DOCTYPE html>
<html>
    <head>                          
        <script src="sdk/scripts/VSS.SDK.min.js"></script>              
        <script type="text/javascript">
            VSS.init({
                explicitNotifyLoaded: true,
                usePlatformStyles: true
            });

            VSS.require("TFS/Dashboards/WidgetHelpers", function (WidgetHelpers) {
                WidgetHelpers.IncludeWidgetStyles();
                VSS.register("HelloWorldWidget2", function () {                
                    return {
                        load: function (widgetSettings) {
                            var $title = $('h2.title');
                            $title.text('Hello World');

                            return WidgetHelpers.WidgetStatusHelper.Success();
                        }
                    }
                });
                VSS.notifyLoadSucceeded();
            });       
        </script>
    </head>
    <body>
        <div class="widget">
            <h2 class="title"></h2>
            <div id="query-info-container"></div>
        </div>
    </body>
</html>

Stap 2: Toegang tot Azure DevOps-resources

Als u toegang tot Azure DevOps-resources wilt inschakelen, moeten bereiken worden opgegeven in het extensiemanifest. We voegen het vso.work bereik toe aan ons manifest.
Dit bereik geeft aan dat de widget alleen-lezentoegang nodig heeft tot query's en werkitems. Bekijk hier alle beschikbare bereiken. Voeg het onderstaande toe aan het einde van het extensiemanifest.

{
    ...,
    "scopes":[
        "vso.work"
    ]
}

Waarschuwing

Het toevoegen of wijzigen van bereiken nadat een extensie is gepubliceerd, wordt momenteel niet ondersteund. Als u uw extensie al hebt geüpload, verwijdert u deze uit Marketplace. Ga naar Visual Studio Marketplace Publishing Portal, klik met de rechtermuisknop op uw extensie en selecteer Verwijderen.

Stap 3: De REST API-aanroep maken

Er zijn veel bibliotheken aan de clientzijde die toegankelijk zijn via de SDK om REST API-aanroepen te maken in Azure DevOps. Deze bibliotheken worden REST-clients genoemd en zijn JavaScript-wrappers rond Ajax-aanroepen voor alle beschikbare eindpunten aan de serverzijde. U kunt methoden van deze clients gebruiken in plaats van ajax-aanroepen zelf te schrijven. Met deze methoden worden de API-antwoorden toegewezen aan objecten die door uw code kunnen worden gebruikt.

In deze stap wordt de VSS.require aanroep bijgewerkt die moet worden geladen TFS/WorkItemTracking/RestClient. Dit biedt de WorkItemTracking REST-client. We kunnen deze REST-client gebruiken om informatie op te halen over een query die wordt aangeroepen Feedback onder de map Shared Queries.

Binnen de functie die we doorgeven VSS.register, maken we een variabele voor het opslaan van de huidige project-id. We hebben deze variabele nodig om de query op te halen. We maken ook een nieuwe methode getQueryInfo voor het gebruik van de REST-client. Deze methode die vervolgens wordt aangeroepen vanuit de load-methode.

De methode getClient geeft een exemplaar van de REST-client die we nodig hebben. De methode getQuery retourneert de query die in een belofte is verpakt. De bijgewerkte VSS.require versie ziet er als volgt uit:

VSS.require(["TFS/Dashboards/WidgetHelpers", "TFS/WorkItemTracking/RestClient"], 
    function (WidgetHelpers, TFS_Wit_WebApi) {
        WidgetHelpers.IncludeWidgetStyles();
        VSS.register("HelloWorldWidget2", function () { 
            var projectId = VSS.getWebContext().project.id;

            var getQueryInfo = function (widgetSettings) {
                // Get a WIT client to make REST calls to Azure DevOps Services
                return TFS_Wit_WebApi.getClient().getQuery(projectId, "Shared Queries/Feedback")
                    .then(function (query) {
                        // Do something with the query

                        return WidgetHelpers.WidgetStatusHelper.Success();
                    }, function (error) {                            
                        return WidgetHelpers.WidgetStatusHelper.Failure(error.message);
                    });
            }

            return {
                load: function (widgetSettings) {
                    // Set your title
                    var $title = $('h2.title');
                    $title.text('Hello World');

                    return getQueryInfo(widgetSettings);
                }
            }
        });
        VSS.notifyLoadSucceeded();
    });

Let op het gebruik van de methode Failure van WidgetStatusHelper. Hiermee kunt u aan het widgetframework aangeven dat er een fout is opgetreden en profiteren van de standaardfoutervaring die aan alle widgets is verstrekt.

Als u de query niet onder de FeedbackShared Queries map hebt, vervangt Shared Queries\Feedback u de code door het pad van een query die in uw project aanwezig is.

Stap 4: Het antwoord weergeven

De laatste stap is het weergeven van de querygegevens in de widget. De getQuery functie retourneert een object van het type Contracts.QueryHierarchyItem binnen een belofte. In dit voorbeeld geven we de query-id, de naam van de query en de naam van de maker van de query weer onder de tekst 'Hallo wereld'. Vervang de // Do something with the query opmerking door het onderstaande:

    // Create a list with query details                                
    var $list = $('<ul>');                                
    $list.append($('- ').text("Query Id: " + query.id));
    $list.append($('- ').text("Query Name: " + query.name));
    $list.append($('- ').text("Created By: " + ( query.createdBy? query.createdBy.displayName: "<unknown>" ) ) );                                                            

    // Append the list to the query-info-container
    var $container = $('#query-info-container');
    $container.empty();
    $container.append($list);

Uw laatste hello-world2.html is als volgt:

<!DOCTYPE html>
<html>
<head>    
    <script src="sdk/scripts/VSS.SDK.min.js"></script>
    <script type="text/javascript">
        VSS.init({
            explicitNotifyLoaded: true,
            usePlatformStyles: true
        });

        VSS.require(["TFS/Dashboards/WidgetHelpers", "TFS/WorkItemTracking/RestClient"], 
            function (WidgetHelpers, TFS_Wit_WebApi) {
                WidgetHelpers.IncludeWidgetStyles();
                VSS.register("HelloWorldWidget2", function () {                
                    var projectId = VSS.getWebContext().project.id;

                    var getQueryInfo = function (widgetSettings) {
                        // Get a WIT client to make REST calls to Azure DevOps Services
                        return TFS_Wit_WebApi.getClient().getQuery(projectId, "Shared Queries/Feedback")
                            .then(function (query) {
                                // Create a list with query details                                
                                var $list = $('<ul>');
                                $list.append($('- ').text("Query ID: " + query.id));
                                $list.append($('- ').text("Query Name: " + query.name));
                                $list.append($('- ').text("Created By: " + (query.createdBy ? query.createdBy.displayName: "<unknown>") ));

                                // Append the list to the query-info-container
                                var $container = $('#query-info-container');
                                $container.empty();
                                $container.append($list);

                                // Use the widget helper and return success as Widget Status
                                return WidgetHelpers.WidgetStatusHelper.Success();
                            }, function (error) {
                                // Use the widget helper and return failure as Widget Status
                                return WidgetHelpers.WidgetStatusHelper.Failure(error.message);
                            });
                    }

                    return {
                        load: function (widgetSettings) {
                            // Set your title
                            var $title = $('h2.title');
                            $title.text('Hello World');

                            return getQueryInfo(widgetSettings);
                        }
                    }
                });
            VSS.notifyLoadSucceeded();
        });       
    </script>

</head>
<body>
    <div class="widget">
        <h2 class="title"></h2>
        <div id="query-info-container"></div>
    </div>
</body>
</html>

Stap 5: Updates van extensiemanifest

In deze stap werken we het extensiemanifest bij om een vermelding voor onze tweede widget op te nemen. Voeg een nieuwe bijdrage toe aan de matrix in de contributions eigenschap en voeg het nieuwe bestand hello-world2.html toe aan de matrix in de bestandseigenschap. U hebt een andere voorbeeldafbeelding nodig voor de tweede widget. Geef deze een naam en plaats deze preview2.png in de img map.

 {
     ...,
     "contributions":[
         ...,
        {
             "id": "HelloWorldWidget2",
             "type": "ms.vss-dashboards-web.widget",
             "targets": [
                 "ms.vss-dashboards-web.widget-catalog"
             ],
             "properties": {
                 "name": "Hello World Widget 2 (with API)",
                 "description": "My second widget",
                 "previewImageUrl": "img/preview2.png",                            
                 "uri": "hello-world2.html",
                 "supportedSizes": [
                      {
                             "rowSpan": 1,
                             "columnSpan": 2
                         }
                     ],
                 "supportedScopes": ["project_team"]
             }
         }

     ],
     "files": [
         {
             "path": "hello-world.html", "addressable": true
         },
         {
             "path": "hello-world2.html", "addressable": true
         },      
         {
             "path": "sdk/scripts", "addressable": true
         },
         {
             "path": "img", "addressable": true
         }
     ],
     "scopes":[
         "vso.work"
     ]
 }

Stap 6: Verpakken, publiceren en delen

Uw extensie verpakken, publiceren en delen. Als u de extensie al hebt gepubliceerd, kunt u de extensie opnieuw verpakken en rechtstreeks bijwerken naar Marketplace.

Stap 7: Widget toevoegen uit de catalogus

Ga nu naar uw teamdashboard op https:\//dev.azure.com/{yourOrganization}/{yourProject}. Als deze pagina al is geopend, vernieuwt u deze. Beweeg de muisaanwijzer op de knop Bewerken in de rechterbenedenhoek en selecteer de knop Toevoegen. De widgetcatalogus wordt geopend waar u de widget vindt die u hebt geïnstalleerd. Kies uw widget en selecteer de knop Toevoegen om deze toe te voegen aan uw dashboard.

Deel 3: Hallo wereld met configuratie

In deel 2 van deze handleiding hebt u gezien hoe u een widget maakt waarin querygegevens voor een in code vastgelegde query worden weergegeven. In dit deel voegen we de mogelijkheid toe om de query te configureren die moet worden gebruikt in plaats van de in code vastgelegde query. In de configuratiemodus krijgt de gebruiker een livevoorbeeld van de widget te zien op basis van hun wijzigingen. Deze wijzigingen worden opgeslagen in de widget op het dashboard wanneer de gebruiker Opslaan selecteert.

Overview dashboard live preview of the widget based on changes.

Stap 1: HTML

Implementaties van widgets en widgetconfiguraties zijn veel hetzelfde. Beide worden geïmplementeerd in het extensieframework als bijdragen. Beide gebruiken hetzelfde SDK-bestand, VSS.SDK.min.js. Beide zijn gebaseerd op HTML, JavaScript en CSS.

Kopieer het bestand html-world2.html uit het vorige voorbeeld en wijzig de naam van de kopie in hello-world3.html. Voeg nog een HTML-bestand toe met de naam configuration.html. Uw map ziet er nu uit zoals in het volgende voorbeeld:

|--- README.md
|--- sdk    
    |--- node_modules           
    |--- scripts
        |--- VSS.SDK.min.js       
|--- img                        
    |--- logo.png                           
|--- scripts          
|--- configuration.html                          
|--- hello-world.html               // html page to be used for your widget  
|--- hello-world2.html              // renamed copy of hello-world.html
|--- hello-world3.html              // renamed copy of hello-world2.html
|--- vss-extension.json             // extension's manifest

Voeg de onderstaande HTML toe in configuration.html. We voegen in principe de verplichte verwijzing toe aan de VSS. SDK.min.js-bestand en een select-element voor de vervolgkeuzelijst om een query te selecteren in een vooraf ingestelde lijst.
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>                          
            <script src="sdk/scripts/VSS.SDK.min.js"></script>              
        </head>
        <body>
            <div class="container">
                <fieldset>
                    <label class="label">Query: </label>
                    <select id="query-path-dropdown" style="margin-top:10px">
                        <option value="" selected disabled hidden>Please select a query</option>
                        <option value="Shared Queries/Feedback">Shared Queries/Feedback</option>
                        <option value="Shared Queries/My Bugs">Shared Queries/My Bugs</option>
                        <option value="Shared Queries/My Tasks">Shared Queries/My Tasks</option>                        
                    </select>
                </fieldset>             
            </div>
        </body>
    </html>

Stap 2: JavaScript - Configuratie

Gebruik JavaScript om inhoud weer te geven in de widgetconfiguratie, net zoals we hebben gedaan voor de widget in stap 3 van deel 1 in deze handleiding. Deze JavaScript-code geeft inhoud weer, initialiseert de VSS SDK, wijst de code voor uw widgetconfiguratie toe aan de configuratienaam en geeft de configuratie-instellingen door aan het framework. In ons geval is hieronder de code waarmee de widgetconfiguratie wordt geladen. Open het bestand configuration.html en het onderstaande <script> element naar de <head>.

    <script type="text/javascript">
        VSS.init({                        
            explicitNotifyLoaded: true,
            usePlatformStyles: true
        });

        VSS.require("TFS/Dashboards/WidgetHelpers", function (WidgetHelpers) {
            VSS.register("HelloWorldWidget.Configuration", function () {   
                var $queryDropdown = $("#query-path-dropdown"); 

                return {
                    load: function (widgetSettings, widgetConfigurationContext) {
                        var settings = JSON.parse(widgetSettings.customSettings.data);
                        if (settings && settings.queryPath) {
                             $queryDropdown.val(settings.queryPath);
                         }

                        return WidgetHelpers.WidgetStatusHelper.Success();
                    },
                    onSave: function() {
                        var customSettings = {
                            data: JSON.stringify({
                                    queryPath: $queryDropdown.val()
                                })
                        };
                        return WidgetHelpers.WidgetConfigurationSave.Valid(customSettings); 
                    }
                }
            });
            VSS.notifyLoadSucceeded();
        });
    </script>

VSS.init, VSS.requireen VSS.register spelen dezelfde rol als voor de widget zoals beschreven in deel 1. Het enige verschil is dat voor widgetconfiguraties de functie die wordt doorgegeven VSS.register , een object moet retourneren dat voldoet aan het IWidgetConfiguration contract.

De load eigenschap van het IWidgetConfiguration contract moet een functie hebben als waarde. Deze functie bevat de set stappen om de widgetconfiguratie weer te geven. In ons geval is het om de geselecteerde waarde van het vervolgkeuzeelement bij te werken met bestaande instellingen, indien van toepassing. Deze functie wordt aangeroepen wanneer het framework uw instantie instantieert widget configuration

De onSave eigenschap van het IWidgetConfiguration contract moet een functie hebben als waarde. Deze functie wordt aangeroepen door het framework wanneer de gebruiker Opslaan selecteert in het configuratiedeelvenster. Als de gebruikersinvoer gereed is om op te slaan, serialiseert u deze in een tekenreeks, maakt u het custom settings object en gebruikt WidgetConfigurationSave.Valid() u deze om de gebruikersinvoer op te slaan.

In deze handleiding gebruiken we JSON om de gebruikersinvoer in een tekenreeks te serialiseren. U kunt een andere manier kiezen om de gebruikersinvoer naar tekenreeks te serialiseren. Het is toegankelijk voor de widget via de aangepaste eigenschap Instellingen van het WidgetSettings object. De widget moet dit deserialiseren, wat wordt behandeld in stap 4.

Stap 3: JavaScript - Livevoorbeeld inschakelen

Als u livevoorbeeldupdate wilt inschakelen wanneer de gebruiker een query selecteert in de vervolgkeuzelijst, voegen we een wijzigingsgebeurtenishandler toe aan de knop. Deze handler meldt het framework dat de configuratie is gewijzigd. Het geeft ook de customSettings gegevens door die moeten worden gebruikt voor het bijwerken van de preview. Om het framework op de hoogte te stellen, moet de notify methode op de widgetConfigurationContext aangeroepen methode worden aangeroepen. Er zijn twee parameters nodig: de naam van de gebeurtenis, die in dit geval is WidgetHelpers.WidgetEvent.ConfigurationChange, en een EventArgs object voor de gebeurtenis, gemaakt op basis customSettings van WidgetEvent.Args de helpermethode.

Voeg het onderstaande toe aan de functie die is toegewezen aan de load eigenschap.

 $queryDropdown.on("change", function () {
     var customSettings = {
        data: JSON.stringify({
                queryPath: $queryDropdown.val()
            })
     };
     var eventName = WidgetHelpers.WidgetEvent.ConfigurationChange;
     var eventArgs = WidgetHelpers.WidgetEvent.Args(customSettings);
     widgetConfigurationContext.notify(eventName, eventArgs);
 });

U moet het framework van configuratiewijziging ten minste één keer melden, zodat de knop Opslaan kan worden ingeschakeld.

Aan het einde ziet uw configuration.html naam er als volgt uit:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>                          
            <script src="sdk/scripts/VSS.SDK.min.js"></script>      
            <script type="text/javascript">
                VSS.init({                        
                    explicitNotifyLoaded: true,
                    usePlatformStyles: true
                });

                VSS.require("TFS/Dashboards/WidgetHelpers", function (WidgetHelpers) {
                    VSS.register("HelloWorldWidget.Configuration", function () {   
                        var $queryDropdown = $("#query-path-dropdown");

                        return {
                            load: function (widgetSettings, widgetConfigurationContext) {
                                var settings = JSON.parse(widgetSettings.customSettings.data);
                                if (settings && settings.queryPath) {
                                     $queryDropdown.val(settings.queryPath);
                                 }

                                 $queryDropdown.on("change", function () {
                                     var customSettings = {data: JSON.stringify({queryPath: $queryDropdown.val()})};
                                     var eventName = WidgetHelpers.WidgetEvent.ConfigurationChange;
                                     var eventArgs = WidgetHelpers.WidgetEvent.Args(customSettings);
                                     widgetConfigurationContext.notify(eventName, eventArgs);
                                 });

                                return WidgetHelpers.WidgetStatusHelper.Success();
                            },
                            onSave: function() {
                                var customSettings = {data: JSON.stringify({queryPath: $queryDropdown.val()})};
                                return WidgetHelpers.WidgetConfigurationSave.Valid(customSettings); 
                            }
                        }
                    });
                    VSS.notifyLoadSucceeded();
                });
            </script>       
        </head>
        <body>
            <div class="container">
                <fieldset>
                    <label class="label">Query: </label>
                    <select id="query-path-dropdown" style="margin-top:10px">
                        <option value="" selected disabled hidden>Please select a query</option>
                        <option value="Shared Queries/Feedback">Shared Queries/Feedback</option>
                        <option value="Shared Queries/My Bugs">Shared Queries/My Bugs</option>
                        <option value="Shared Queries/My Tasks">Shared Queries/My Tasks</option>                        
                    </select>
                </fieldset>     
            </div>
        </body>
    </html>

Stap 4: JavaScript - Opnieuw laden implementeren in de widget

We hebben de widgetconfiguratie ingesteld om het querypad op te slaan dat door de gebruiker is geselecteerd. We moeten nu de code in de widget bijwerken om deze opgeslagen configuratie te gebruiken in plaats van de in code vastgelegde Shared Queries/Feedback code uit het vorige voorbeeld.

Open het bestand hello-world3.html en werk de naam van de widget bij van HelloWorldWidget2 naar HelloWorldWidget3 in de regel waar u aanroept VSS.register. Hierdoor kan het framework de widget in de extensie uniek identificeren.

De functie die via momenteel is toegewezen HelloWorldWidget3 , VSS.register retourneert een object dat voldoet aan het IWidget contract. Omdat onze widget nu configuratie nodig heeft, moet deze functie worden bijgewerkt om een object te retourneren dat voldoet aan het IConfigurableWidget contract. Werk hiervoor de retourinstructie bij om een eigenschap met de naam opnieuw laden op te nemen, zoals hieronder wordt beschreven. De waarde voor deze eigenschap is een functie die de getQueryInfo methode nog één keer aanroept. Deze herloadmethode wordt door het framework aangeroepen telkens wanneer de invoer van de gebruiker verandert om de livevoorbeeld weer te geven. Dit wordt ook aangeroepen wanneer de configuratie wordt opgeslagen.

return {
    load: function (widgetSettings) {
        // Set your title
        var $title = $('h2.title');
        $title.text('Hello World');

        return getQueryInfo(widgetSettings);
    },
    reload: function (widgetSettings) {
        return getQueryInfo(widgetSettings);
    }
}

Het in code vastgelegde querypad in 'getQueryInfo' moet worden vervangen door het geconfigureerde querypad, dat kan worden geëxtraheerd uit de parameter widget Instellingen die wordt doorgegeven aan de methode. Voeg het onderstaande toe aan het begin van de methode 'getQueryInfo' en vervang het in code vastgelegde querypad door 'settings.queryPath'.
var settings = JSON.parse(widgetSettings.customSettings.data);
if (!settings || !settings.queryPath) {
    var $container = $('#query-info-container');
    $container.empty();
    $container.text("Sorry nothing to show, please configure a query path.");

    return WidgetHelpers.WidgetStatusHelper.Success();
}

Op dit moment is uw widget klaar om te worden weergegeven met de geconfigureerde instellingen.

Zowel de load eigenschappen als de reload eigenschappen hebben een vergelijkbare functie. Dit is het geval voor de meest eenvoudige widgets. Voor complexe widgets zijn er bepaalde bewerkingen die u slechts één keer wilt uitvoeren, ongeacht hoe vaak de configuratie verandert. Of er zijn enkele zware bewerkingen die niet meer dan één keer hoeven te worden uitgevoerd. Dergelijke bewerkingen maken deel uit van de functie die overeenkomt met de load eigenschap en niet de reload eigenschap.

Stap 5: Updates van extensiemanifest

Open het vss-extension.json bestand om twee nieuwe vermeldingen op te nemen in de matrix in de contributions eigenschap. Een voor de HelloWorldWidget3 widget en de andere voor de configuratie. U hebt nog een voorbeeldafbeelding nodig voor de derde widget. Geef deze een naam en plaats deze preview3.png in de img map. Werk de matrix in de files eigenschap bij om de twee nieuwe HTML-bestanden op te nemen die we in dit voorbeeld hebben toegevoegd.

{
    ...
    "contributions": [
        ... , 
        {
             "id": "HelloWorldWidget3",
             "type": "ms.vss-dashboards-web.widget",
             "targets": [
                 "ms.vss-dashboards-web.widget-catalog",
                 "fabrikam.vsts-extensions-myExtensions.HelloWorldWidget.Configuration"
             ],
             "properties": {
                 "name": "Hello World Widget 3 (with config)",
                 "description": "My third widget",
                 "previewImageUrl": "img/preview3.png",                       
                 "uri": "hello-world3.html",
                 "supportedSizes": [
                      {
                             "rowSpan": 1,
                             "columnSpan": 2
                         }
                     ],
                 "supportedScopes": ["project_team"]
             }
         },
         {
             "id": "HelloWorldWidget.Configuration",
             "type": "ms.vss-dashboards-web.widget-configuration",
             "targets": [ "ms.vss-dashboards-web.widget-configuration" ],
             "properties": {
                 "name": "HelloWorldWidget Configuration",
                 "description": "Configures HelloWorldWidget",
                 "uri": "configuration.html"
             }
         }
    ],
    "files": [
            {
                "path": "hello-world.html", "addressable": true
            },
             {
                "path": "hello-world2.html", "addressable": true
            },
            {
                "path": "hello-world3.html", "addressable": true
            },
            {
                "path": "configuration.html", "addressable": true
            },
            {
                "path": "sdk/scripts", "addressable": true
            },
            {
                "path": "img", "addressable": true
            }
        ],
        ...     
}

Let op de bijdrage voor widgetconfiguratie volgt een iets ander model dan de widget zelf. Een bijdrage-vermelding voor widgetconfiguratie heeft:
  • De id om uw bijdrage te identificeren. Dit moet uniek zijn binnen een extensie.
  • Het type bijdrage. Voor alle widgetconfiguraties moet dit zijn ms.vss-dashboards-web.widget-configuration
  • De matrix met doelen waaraan de bijdrage bijdraagt. Voor alle widgetconfiguraties heeft dit één vermelding: ms.vss-dashboards-web.widget-configuration.
  • De eigenschappen die een set eigenschappen bevatten met de naam, beschrijving en de URI van het HTML-bestand dat wordt gebruikt voor configuratie.

Ter ondersteuning van de configuratie moet ook de widgetbijdrage worden gewijzigd. De matrix met doelen voor de widget moet worden bijgewerkt om de id voor de configuratie in het formulier <>publisheropid for the extension>< te nemen.<id for the configuration contribution> Dit is fabrikam.vsts-extensions-myExtensions.HelloWorldWidget.Configurationin dit geval .

Waarschuwing

Als de bijdragevermelding voor uw configureerbare widget niet is gericht op de configuratie met behulp van de juiste uitgever en extensienaam zoals eerder beschreven, wordt de knop Configureren niet weergegeven voor de widget.

Aan het einde van dit deel moet het manifestbestand drie widgets en één configuratie bevatten. U kunt hier het volledige manifest ophalen uit het voorbeeld.

Stap 6: Verpakken, publiceren en delen

Als u uw extensie nog niet hebt gepubliceerd, leest u deze sectie om uw extensie te verpakken, te publiceren en te delen. Als u de extensie al eerder hebt gepubliceerd, kunt u de extensie opnieuw verpakken en rechtstreeks bijwerken naar Marketplace.

Stap 7: Widget toevoegen uit de catalogus

Ga nu naar uw teamdashboard op https://dev.azure.com/{yourOrganization}/{yourProject}. Als deze pagina al is geopend, vernieuwt u deze. Beweeg de muisaanwijzer op de knop Bewerken in de rechterbenedenhoek en selecteer de knop Toevoegen. Hiermee opent u de widgetcatalogus waar u de widget vindt die u hebt geïnstalleerd. Kies uw widget en selecteer de knop Toevoegen om deze toe te voegen aan uw dashboard.

Er wordt een bericht weergegeven waarin u wordt gevraagd om de widget te configureren.

Overview dashboard with a sample widget from the catalog.

Er zijn twee manieren om widgets te configureren. U kunt de muisaanwijzer op de widget plaatsen, het beletselteken selecteren dat in de rechterbovenhoek wordt weergegeven en vervolgens Configureren selecteren. Het andere is om de knop Bewerken in de rechterbenedenhoek van het dashboard te selecteren en vervolgens de knop Configureren te selecteren die in de rechterbovenhoek van de widget wordt weergegeven. Hiermee opent u de configuratie-ervaring aan de rechterkant en een voorbeeld van uw widget in het midden. Kies een query in de vervolgkeuzelijst. In het livevoorbeeld worden de bijgewerkte resultaten weergegeven. Selecteer Opslaan en de widget geeft de bijgewerkte resultaten weer.

Stap 8: Meer configureren (optioneel)

U kunt zoveel HTML-formulierelementen toevoegen als u nodig hebt in de configuration.html voor aanvullende configuratie. Er zijn twee configureerbare functies die standaard beschikbaar zijn: widgetnaam en widgetgrootte.

Standaard wordt de naam die u opgeeft voor uw widget in het extensiemanifest opgeslagen als de widgetnaam voor elk exemplaar van uw widget dat ooit aan een dashboard wordt toegevoegd. U kunt toestaan dat gebruikers dit configureren, zodat ze elke naam kunnen toevoegen die ze willen toevoegen aan hun exemplaar van uw widget. Als u een dergelijke configuratie wilt toestaan, voegt isNameConfigurable:true u de sectie Eigenschappen voor uw widget toe in het extensiemanifest.

Als u meer dan één vermelding opgeeft voor uw widget in de supportedSizes matrix in het extensiemanifest, kunnen gebruikers ook de grootte van de widget configureren.

Het extensiemanifest voor het derde voorbeeld in deze handleiding zou er als volgt uitzien als we de configuratie van de widgetnaam en grootte inschakelen:

{
    ...
    "contributions": [
        ... , 
        {
             "id": "HelloWorldWidget3",
             "type": "ms.vss-dashboards-web.widget",
             "targets": [
                 "ms.vss-dashboards-web.widget-catalog",  "fabrikam.vsts-extensions-myExtensions.HelloWorldWidget.Configuration"
             ],
             "properties": {
                 "name": "Hello World Widget 3 (with config)",
                 "description": "My third widget",
                 "previewImageUrl": "img/preview3.png",                       
                 "uri": "hello-world3.html",
                 "isNameConfigurable": true,
                 "supportedSizes": [
                    {
                        "rowSpan": 1,
                        "columnSpan": 2
                    },
                    {
                        "rowSpan": 2,
                        "columnSpan": 2
                    }
                 ],
                 "supportedScopes": ["project_team"]
             }
         },
         ...
}

Met de vorige wijziging kunt u de extensie opnieuw verpakken en bijwerken . Vernieuw het dashboard met deze widget (Hallo wereld Widget 3 (met configuratie)). Open de configuratiemodus voor uw widget. U kunt nu de optie zien om de naam en grootte van de widget te wijzigen.

Widget where name and size can be configured

Kies een andere grootte in de vervolgkeuzelijst. U ziet dat het formaat van de livevoorbeeld wordt gewijzigd. Sla de wijziging op en de widget op het dashboard wordt ook aangepast.

Waarschuwing

Als u een al ondersteunde grootte verwijdert, kan de widget niet goed worden geladen. We werken aan een oplossing voor een toekomstige release.

Als u de naam van de widget wijzigt, resulteert dit niet in een zichtbare wijziging in de widget. Dit komt doordat onze voorbeeldwidgets de widgetnaam nergens weergeven. Laten we de voorbeeldcode wijzigen om de widgetnaam weer te geven in plaats van de in code vastgelegde tekst 'Hallo wereld'.

Hiervoor vervangt u de in code vastgelegde tekst 'Hallo wereld' widgetSettings.name door in de regel waar we de tekst van het h2 element instellen. Dit zorgt ervoor dat de widgetnaam wordt weergegeven telkens wanneer de widget wordt geladen bij het vernieuwen van de pagina. Omdat we willen dat de livevoorbeeld telkens wordt bijgewerkt wanneer de configuratie wordt gewijzigd, moeten we dezelfde code toevoegen in het reload deel van onze code. De definitieve retourinstructie is hello-world3.html als volgt:

return {
    load: function (widgetSettings) {
        // Set your title
        var $title = $('h2.title');
        $title.text(widgetSettings.name);

        return getQueryInfo(widgetSettings);
    },
    reload: function (widgetSettings) {
        // Set your title
        var $title = $('h2.title');
        $title.text(widgetSettings.name);

        return getQueryInfo(widgetSettings);
    }
}

Verpak de extensie opnieuw en werk deze opnieuw bij . Vernieuw het dashboard met deze widget. Wijzigingen in de widgetnaam, in de configuratiemodus, werken de widgettitel nu bij.