Quickstart: Pinning a secondary tile (HTML)

Note  Not using JavaScript? See Quickstart: Pinning a secondary tile (XAML).

 

This topic walks you through the steps to create a secondary tile for an app and pin it to the Start screen.

Prerequisites

To understand this topic, you will need:

  • A working knowledge of secondary tile terms and concepts. For more information, see the Secondary tiles overview.
  • The ability to create a basic Windows Store app with JavaScript using Windows Runtime APIs. For more information, see Create your first Windows Store app using JavaScript.
  • An understanding of how to use Microsoft Visual Basic to create code for an HTML-based Windows Store app.

Important  To see the code supplied in this topic used in a full sample, see the Secondary tiles sample. The sample is provided in JavaScript, C#, C++, and Visual Basic versions.

 

Instructions

1. Add an app bar with a pin/unpin button

On Windows, you normally present a pinning opportunity to the user through a Pin to Start button in your app bar. For information on how to create an app bar, see Quickstart: Adding an app bar with commands.

Note  For Windows Phone Store apps, pinning is usually done through a context menu rather than a button on an app bar.

The following example declares an app bar with a button. This code is added to the .html page in your project to which the rest of code in this topic applies.


<div id="pinUnpinFromAppbar" data-win-control="WinJS.UI.AppBar" data-win-options="">
    <button 
        data-win-control="WinJS.UI.AppBarCommand" 
        data-win-options="{id:'commandButton',section:'global'}">
    </button>
</div>

2. Provide a unique ID for your secondary tile


var appbarTileId = "MySecondaryTile";

3. Create a function to set the button as pin or unpin

Your pin button's action toggles between pinning and unpinning the secondary tile. In this example, we create a function to set the button appropriately, using system-provided icons for a consistent appearance with other apps. This function is called as part of your app's initialization code, whenever the app bar is opened, and immediately after a successful pin/unpin operation.

The final line in this function sets the app bar's WinJS.UI.sticky property to false, which allows the app bar to be dismissed.


function setAppbarButton() {
    var commandButton = appBar.getCommandById("commandButton").winControl;

    if (Windows.UI.StartScreen.SecondaryTile.exists(appbarTileId)) {
        commandButton.label = "Unpin from Start";
        commandButton.icon = "unpin";
    } else {
        commandButton.label = "Pin to Start";
        commandButton.icon = "pin";
    }

    document.getElementById("pinUnpinFromAppbar").winControl.sticky = false;
}

4. Show the appropriate button and assign a button click handler

In this example, as part of the app's initialization, we use the setAppbarButton function from the last step to check whether the secondary tile is already pinned and set the button text accordingly.

We then assign the handler appbarButtonClicked to the pin button's click event. We'll show you how to implement the event handler in the next step.

Call the code shown in this step, together with any other initialization you need to perform, as part of your app's initialization every time that app is launched.


document.getElementById("pinUnpinFromAppbar").disabled = false;
setAppbarButton();

id("commandButton").addEventListener("click", appbarButtonClicked, false);

5. Create and pin the secondary tile in the button's event handler

This example implements a single function that can be called by the pin button's click event handler. This function collects several steps that lead to the pin request:

  • Assigns property values that are required for secondary tile creation
  • Creates the secondary tile object
  • Specifies additional properties of the secondary tile
  • Gets the screen coordinates used to display the confirmation flyout (Windows only)

Some of the properties of the secondary tile must be set before it can be pinned. If you attempt to pin a secondary tile without one or more of these properties, the attempt will fail. These are the required properties:

  • A unique ID for the tile
  • Short name (Windows 8.0 only)
  • Display name
  • An argument string that is passed to the parent application when the secondary tile is activated
  • A logo image
  • Tile options (Windows 8.0 only)

As an example argument string, this sample passes the time the secondary tile was pinned to the Start screen.

Note  On Windows Phone 8.1, the display name is never shown on a medium (150x150) secondary tile. Also, all phone tiles initially pin as medium tiles, so the newTileDesiredSize parameter is ignored on the phone.

Note  If you provide the same ID as that of an existing secondary tile, the existing secondary tile will be overwritten.

 


var currentTime = new Date();
var appbarTileId = "SecondaryTile.AppBar";
var newTileDisplayName = "Secondary tile pinned through app bar";                       
var TileActivationArguments = appbarTileId + " was pinned at " + currentTime;                        
var square150x150Logo = new Windows.Foundation.Uri("ms-appx:///Images/square150x150Tile-sdk.png");
var newTileDesiredSize = Windows.UI.StartScreen.TileSize.square150x150;

Next, we create the secondary tile object. This version of the constructor creates a medium tile. Note that if your secondary tile receives notifications, it is a best practice to declare all tile sizes. This is done by providing logo images through the SecondaryTileVisualElements clasa.


var tile = new Windows.UI.StartScreen.SecondaryTile(appbarTileId,
                                                    newTileDisplayName,
                                                    TileActivationArguments,
                                                    square150x150Logo,
                                                    newTileDesiredSize);

Now that you have a secondary tile object, you can specify secondary tile properties that are not set through the constructor. This example specifies the foreground text color and small logo and specifies that the display name is shown on the tile.

Note  On Windows Phone 8.1, neither the small logo nor the display name are shown on a medium (150x150) secondary tile and the foreground text color cannot be specified, so those properties as set in this example are ignored on the phone.


tile.visualElements.showNameOnSquare150x150Logo = true;                        
tile.visualElements.foregroundText = Windows.UI.StartScreen.ForegroundText.light;
tile.visualElements.square30x30Logo = new Windows.Foundation.Uri("ms-appx:///Images/square30x30Tile-sdk.png");

On Windows, the user must confirm before a secondary tile is pinned. In the confirmation dialog, the user can override the tile's display name and select from various tile sizes to pin. The confirmation flyout should be shown near the button that invoked the pin request. This example retrieves the bounding rectangle of the pin button and specifies that the confirmation dialog should display above the button.

Note  On Windows Phone 8.1, the user is not presented with a confirmation dialog; the tile is simply pinned to the Start screen as a medium tile and without a display name. The code shown here would be ignored.


var element = document.getElementById("commandButton");
var selectionRect = element.getBoundingClientRect();
var buttonCoordinates = { x: selectionRect.left, y: selectionRect.top, width: selectionRect.width, height: selectionRect.height };
var placement = Windows.UI.Popups.Placement.above;

Next, the function requests that the secondary tile be pinned.

  • On Windows Phone 8.1, this call pins the tile, suspends the app, and takes the user to the Start screen.
  • On Windows, this call displays the confirmation flyout that asks the user for permission to pin the tile. Using the bounding rectangle of the pin button, this example displays the confirmation flyout above those coordinates. On user approval, Windows creates the secondary tile and places it on the Start screen. The user remains in the app.

return new WinJS.Promise(function (complete, error, progress) {
    tile.requestCreateForSelectionAsync(buttonCoordinates, placement).done(function (isCreated) {
        if (isCreated) {
            complete(true);
        } else {
            complete(false);
        }
    });
});

Note  On Windows Phone 8.1, a call to RequestCreateAsync or RequestCreateForSelectionAsync exits the app and takes the user to the Start screen. Because of this, any code that follows the RequestCreateAsync or RequestCreateForSelectionAsync call will not be executed. Therefore, in Windows Phone 8.1 projects, you should listen for the Suspending event so that you can perform anything, such as saving the app state, that needs to be done before the app exits.

The full appbarButtonClicked and pinByElementAsync functions from the Secondary tiles sample are shown here.


function appbarButtonClicked() {
    document.getElementById("pinUnpinFromAppbar").winControl.sticky = true;

    if (WinJS.UI.AppBarIcon.unpin === document.getElementById("commandButton").winControl.icon) {
        unpinByElementAsync(document.getElementById("commandButton"), appbarTileId).done(function (isDeleted) {
            if (isDeleted) {
                WinJS.log && WinJS.log("Secondary tile was successfully unpinned.", "sample", "status");
                setAppbarButton();
            } else {
                WinJS.log && WinJS.log("Secondary tile was not unpinned.", "sample", "error");
                setAppbarButton();
            }
        });
    } else {
        pinByElementAsync(document.getElementById("commandButton"), appbarTileId, "Appbar pinned secondary tile").done(function (isCreated) {
            if (isCreated) {
                WinJS.log && WinJS.log("Secondary tile was successfully pinned.", "sample", "status");
                setAppbarButton();
            } else {
                WinJS.log && WinJS.log("Secondary tile was not pinned.", "sample", "error");
                setAppbarButton();
            }
        });
    }
}                        
                        
function pinByElementAsync(element, newTileID, newTileDisplayName) {

    var square150x150Logo = new Windows.Foundation.Uri("ms-appx:///Images/square150x150Tile-sdk.png");
    var square30x30Logo = new Windows.Foundation.Uri("ms-appx:///Images/square30x30Tile-sdk.png");

    var currentTime = new Date();
    var TileActivationArguments = newTileID + " was pinned at=" + currentTime;

    var tile = new Windows.UI.StartScreen.SecondaryTile(newTileID,
                                                        newTileDisplayName,
                                                        TileActivationArguments,
                                                        square150x150Logo,
                                                        Windows.UI.StartScreen.TileSize.square150x150);
                                                        
    tile.visualElements.foregroundText = Windows.UI.StartScreen.ForegroundText.light;
    tile.visualElements.square30x30Logo = square30x30Logo;
    tile.visualElements.showNameOnSquare150x150Logo = true;

    var selectionRect = element.getBoundingClientRect();

    return new WinJS.Promise(function (complete, error, progress) {
        tile.requestCreateForSelectionAsync({ x: selectionRect.left, y: selectionRect.top, width: selectionRect.width, height: selectionRect.height }, Windows.UI.Popups.Placement.above).done(function (isCreated) {
            if (isCreated) {
                complete(true);
            } else {
                complete(false);
            }
        });
    });
}

6. Create an unpin function

When the secondary tile is already pinned, the pin button becomes an unpin button and the button's click event handler unpins the tile. This example provides the function that the handler calls to unpin the tile. As parameters, the function accepts the pin button object, again for the purpose of placing the confirmation flyout, and the secondary tile's unique ID. As in the pin function, the unpin call returns a Promise object.

Note  Any secondary tile can also be unpinned through the Start screen app bar. You have the option of relying on that method for unpinning, in which case you don't need to implement unpin functionality or provide an unpin button.

 

Note  On Windows Phone 8.1, the user is not asked for confirmation to unpin a secondary tile. Unpinning a secondary tile on the phone is identical to unpinning any other tile. The code shown here would be ignored.


function unpinByElementAsync(element, unwantedTileID) {

    var selectionRect = element.getBoundingClientRect();
    var buttonCoordinates = { x: selectionRect.left, y: selectionRect.top, width: selectionRect.width, height: selectionRect.height };
    var placement = Windows.UI.Popups.Placement.above;

    var tileToDelete = new Windows.UI.StartScreen.SecondaryTile(unwantedTileID);
    
    return new WinJS.Promise(function (complete, error, progress) {
        tileToGetDeleted.requestDeleteForSelectionAsync(buttonCoordinates, placement).done(function (isDeleted) {
            if (isDeleted) {
                complete(true);
            } else {
                complete(false);
            }
        });
    });
}

7. Implement the event handler for your button

When the user selects your button on the app bar, a flyout asks the user for confirmation. To make sure that the app bar isn't dismissed while the flyout is showing, you must set the app bar's WinJS.UI.sticky property. Also, make sure that the parent of your flyout is correctly assigned. This example calls the setAppbarButton, pinByElementAsync, and unpinByElementAsync functions we defined in the previous steps.

Note that the handler calls setAppbarButton for both success and failure cases in both pinning and unpinning operations. If the operation was successful, the button will swap between pin and unpin. If the operation failed, the button will remain as it is. In both cases, the function must be called to revert the WinJS.UI.sticky property to false so that the app bar can be dismissed.


function appbarButtonClicked() {
    document.getElementById("pinUnpinFromAppbar").winControl.sticky = true;

    if (WinJS.UI.AppBarIcon.unpin === document.getElementById("commandButton").winControl.icon) {
        unpinByElementAsync(document.getElementById("commandButton"), appbarTileId).done(function (isDeleted) {
            if (isDeleted) {
                WinJS.log && WinJS.log("Secondary tile was successfully unpinned.", "sample", "status");
                setAppbarButton();
            } else {
                WinJS.log && WinJS.log("Secondary tile was not unpinned.", "sample", "error");
                setAppbarButton();
            }
        });
    } else {
        pinByElementAsync(document.getElementById("commandButton"), appbarTileId, "App bar pinned secondary tile", "A secondary tile that was pinned by the user from the app bar").done(function (isCreated) {
            if (isCreated) {
                WinJS.log && WinJS.log("Secondary tile was successfully pinned.", "sample", "status");
                setAppbarButton();
            } else {
                WinJS.log && WinJS.log("Secondary tile was not pinned.", "sample", "error");
                setAppbarButton();
            }
        });
    }
}

Summary and next steps

In this Quickstart, you defined a button on an app bar with which a user could pin or unpin a secondary tile. You created the secondary tile, defined many of its properties, and presented the confirmation dialog to the user that results in the final addition of the secondary tile to the Start screen.

After a secondary tile is pinned, the parent app tile then creates a channel Uniform Resource Identifier (URI) so that it can communicate with the secondary tile. For more information, see Quickstart: Sending a notification to a secondary tile.

Secondary tiles sample

Secondary tiles overview

Quickstart: Sending a notification to a secondary tile

Guidelines and checklist for secondary tiles

SecondaryTile class