tvOS Tutorial: Using TVML Templates
In this tvOS tutorial, you’ll learn how to use TVML templates and templating engines to make great-looking user interfaces. By Chris Belanger.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
tvOS Tutorial: Using TVML Templates
35 mins
- Getting Started
- Loading Scripts
- TVML Templates
- The Product Template
- Data Injection
- Reading JSON From the App Bundle
- Injecting Data Into the Document String
- Resolving Image URLs
- Using the Mustache.js Templates
- Template Sections
- Filling out the TVML Template
- Adding Shelves
- Handling Text Overflow
- Event Handling
- Viewer Ratings
- Collecting Ratings
- Where to Go From Here?
Handling Text Overflow
The descriptive alert template provides space for an extended area of text and buttons. It sounds ideal for this purpose. You’ll use this template and a spot of JavaScript to wire it up.
In the Xcode project, right-click on the layouts group and select New File…. Choose tvOS\Other\Empty and name the file expandedDetailText.tvml.
Open the new file and add the following:
<?xml version="1.0" encoding="UTF-8" ?>
<document>
<descriptiveAlertTemplate>
<title>{{title}}</title>
<description>{{text}}</description>
<button action="dismiss">
<text>Dismiss</text>
</button>
</descriptiveAlertTemplate>
</document>
This should be quite straightforward to understand. There’s the usual XML prologue, the
tag and some elements you’ve used before. Notice that the button tag has an action
attribute; this is a user-defined attribute that’s not part of the TVML specification.
You can define any attributes that you want (provided they don’t clash with existing attributes) and then read them from your JavaScript app. You’ll write some code to handle this dismiss
action in just a bit.
Open video.tvml and find the
tag. Update the element to match the following:
<description allowsZooming="true"
moreLabel="more"
action="showOverflow"
title="{{title}}">{{description}}</description>
You’ve added two new attributes: action
and title
. You’ll use both of these in the event handler to create the expanded detail text document.
Event Handling
Now that the document templates are ready to go you can turn your attention to the JavaScript that wires everything up.
Open main.js and add the following function:
function _handleEvent(event) {
// 1:
var sender = event.target;
var action = sender.getAttribute("action");
// 2:
switch(action) {
case "showOverflow":
// 3:
var data = {
text: sender.textContent,
title: sender.getAttribute("title")
};
// 4:
var expandedText = resourceLoader
.getDocument("expandedDetailText.tvml", data);
expandedText.addEventListener("select", _handleEvent);
navigationDocument.presentModal(expandedText);
break;
case "dismiss":
// 5:
navigationDocument.dismissModal();
break;
}
}
Taking this piece-by-piece:
-
The
target
property of theevent
argument represents the DOM object that fired the event.getAttribute()
of a DOM object will return the value for the specified attribute. Here you’re using it to find the value of theaction
attribute you added above. -
Switch on the
action
attribute to invoke the appropriate code. -
If the action is
showOverflow
, then you have a description field with too much content. Construct an object with the data required by the expanded detail text document. Once again you’re usinggetAttribute()
along withtextContent
, which returns the content of the tag itself. -
Load the expandedDetailText.tvml document in the usual way, add an event listener and use
presentModal()
onNavigationDocument
to display the new document on top of the current document.
-
If the action is set to
dismiss
, usedismissModal()
onNavigationDocument
to perform the dismissal.
Now that you’ve created this event handler, you need to wire it up to the initial document. Add the following line to App.onLaunch
, just after you call loadInitialDocument()
:
initialDoc.addEventListener("select", _handleEvent);
This registers _handleEvent
as a listener for the select event, and uses event bubbling to handle all events triggered within the document.
Build and run the app, navigate down to the over-full description and hit the select button. You’ll see your new expanded detail text page:
You can use the dismiss button to return to the video screen.
Viewer Ratings
In the final part of this tutorial, you’ll add a new ratings section to the video page and let the user select a rating using a new template.
Open video.tvml and add the following new shelf underneath the Production shelf:
<shelf>
<header>
<title>What other people thought</title>
</header>
<section>
{{#ratings-reviews}}
<ratingCard action="addRating">
{{#rw-ratings}}
<title>{{out-of-five}} / 5</title>
<ratingBadge value="{{badge-value}}"></ratingBadge>
<description>Mean of {{count}} ratings.</description>
{{/rw-ratings}}
</ratingCard>
{{#reviews}}
<reviewCard>
<title>{{title}}</title>
<description>{{description}}</description>
<text>{{name}} {{date}}</text>
</reviewCard>
{{/reviews}}
{{/ratings-reviews}}
</section>
</shelf>
By now, you’ll recognize most of the TVML elements, but there are still a few new ones:
-
<ratingCard>
: Displays a small card suitable for showing the ratings of a product. -
<ratingBadge>
: A specialized badge for showing a star-rating. Thevalue
attribute should be a value between 0 and 1, which will be converted to a proportion of five stars. -
<reviewCard>
: A card for displaying user or critic reviews.
Notice that the
element has the custom action
attribute again. You’ll use this later to display the rating page.
Build and run to see what the new shelf looks like:
When the user selects the rating card, you want to let them choose a rating for the current video. This is exactly what the ratings TVML template is for.
Collecting Ratings
In Xcode, right-click on the layouts group and select New File…. Choose tvOS\Other\Empty and name the file videoRating.tvml.
Open the new file and add the following:
<?xml version="1.0" encoding="UTF-8" ?>
<document>
<ratingTemplate>
<title>{{title}}</title>
<ratingBadge />
</ratingTemplate>
</document>
This new file uses the
which simply displays and collects ratings. It contains a <title>
and a <ratingBadge>
, both of which you’ve already seen.
The template is ready; you just need to display it. Open main.js and add the following case
to the switch
statement in _handleEvent()
:
case "addRating":
var ratingDoc = resourceLoader.getDocument("videoRating.tvml",
{title: "Rate Video"});
navigationDocument.presentModal(ratingDoc);
break;
These few lines load the new document you created and provide the title to the templating engine. It then displays the document modally.
Build and run, navigate to the rating card and hit select to see the new ratings page:
Now that is one swell-looking – and extensible – interface.
Where to Go From Here?
You can download the final project from this tutorial here.
In this tutorial you’ve created a great-looking TVML app and used three of the built-in templates along with a vast array of TVML-specific elements. You also integrated a JavaScript templating engine to separate the UI from the data. Adopting great development techniques right from the start is a win in anyone’s book.
You can check out Apple’s documentation (apple.co/1PJuOAV) for specifics about the templates and elements covered in this tutorial.
If you enjoyed what you learned in this tutorial, why not check out the complete tvOS Apprentice book, available in our store?
Here’s a taste of what’s in the book:
Section I: Architecture
This section is designed to give you a birds-eye view of how tvOS works and help you decide what to read next.
Section II: TVML Apps
This section covers the basics for creating an app via the TVML approach. From the basics of Hello World through a real world example, by the end of this section you’ll know everything you need to create client / server apps for Apple TV.
Section III: Traditional Apps
This section covers the basics for creating apps via the traditional approach. You’ll learn the new libraries created for Apple TV, and how the ported libraries from iOS can be used.
Section IV: Advanced Frameworks
This section covers some of the more advanced frameworks you’ll need for many TV app use cases. Whether you took the TVML approach or the Traditional approach, these frameworks will be important to understand to make your app stand out.
Section V: Design
This section covers design concepts important for tvOS. For your app to stand apart from the rest, you’ll need to understand these design concepts well.
Bonus Chapter
And that’s not all — on top of the above, we have a bonus chapter for you that gives you a crash course in JavaScript!
By the end of this book, you’ll have some great hands-on experience with building exciting, good-looking apps for the Apple TV!
And to help sweeten the deal, the digital edition of the book is on sale for $49.99! But don’t wait — this sale price is only available for a limited time.
Speaking of sweet deals, be sure to check out the great prizes we’re giving away this year with the iOS 11 Launch Party, including over $9,000 in giveaways!
To enter, simply retweet this post using the #ios11launchparty hashtag by using the button below:
We hope you enjoy this update, and stay tuned for more book releases and updates!