A library used to retrieve HTML partials to use when composing HTML Play frontend applications.
It supports caching the partials and substituting placeholders.
Include the following dependency in your SBT build
resolvers += MavenRepository("HMRC-open-artefacts-maven2", "https://open.artefacts.tax.service.gov.uk/maven2")
libraryDependencies += "uk.gov.hmrc" %% "play-partials-play-xx" % "x.x.x"
Where play-xx
is your version of Play (e.g. play-29
).
This is the simplest way to use the library. It contains error handling and placeholder substitutions.
There are two implementations provided: CachedStaticHtmlPartialRetriever and FormPartialRetriever.
First implement PartialRetriever
and override loadPartial
:
object MyRetriever extends PartialRetriever {
override def loadPartial(url: String): Future[HtmlPartial] =
httpClientV2.get(url"/some/url").execute[HtmlPartial].recover(HtmlPartial.connectionExceptionsAsHtmlPartialFailure)
}
Then you can request the Html
with getPartialContentAsync
. You can provide parameter subsitutions which replaces any placeholder with the form {{parameterKey}}
.
// Returns a Future[Html] - you can pass the Html on to the view
MyRetriever.getPartialContentAsync("http://my.partial")
// Returns a Future[Html] - you can pass the Html on to the view
// You can provide template parameters and HTML to be returned in the case of error
MyRetriever.getPartialContentAsync(
url = "http://my.partial",
templateParameters = Map("NONCE_ATTR" -> CSPNonce.attr),
errorMessage = Html("Could not load partial")
)
If you want to do your own error handling, you can call getPartial
which returns the HtmlPartial
If you need to use a static cached partial, use CachedStaticHtmlPartialRetriever
. It will retrieve the partial from the given URL and cache it (the cache key is the partial URL) for the defined period of time. You can also pass through a map of parameters used to replace placeholders in the retrieved partial.
You can configure the following cache parameters in your application.conf
:
play-partial.cache.refreshAfter
play-partial.cache.expireAfter
play-partial.cache.maxEntries
An instance is already provided for injection. It is used in the same way as PartialRetriever
above. e.g.
class MyController @Inject()(cachedStaticHtmlPartialRetriever: CachedStaticHtmlPartialRetriever) {
// Returns a Future[Html] - you can pass the Html on to the view
cachedStaticHtmlPartialProvider.getPartialContentAsync("http://my.partial")
// Returns a Future[Html] - you can pass the Html on to the view
// You can provide template parameters and HTML to be returned in the case of error
cachedStaticHtmlPartialProvider.getPartialContentAsync(
url = "http://my.partial",
templateParameters = Map("NONCE_ATTR", CSPNonce.attr),
errorMessage = Html("Could not load partial")
)
}
A special case of the static partials are HTML forms. By using FormPartialRetriever
a csrfToken will be added in the request and any {{csrfToken}}
placeholder will be replaced with the Play CSRF token value in the response.
Note, these are not cached.
class MyView @Inject()(formPartialRetriever: FormPartialRetriever) {
formPartialRetriever.getPartialContentAsync("http://my.partial")
}
Use this type to read an HTTP response containing a partial, and safely handle the possible outcomes:
- For success (2xx) status codes, an
HtmlPartial.Success
is returned, which contains the HTML body and optionally a hint on the title that should be used on the page. - For non-success (400 -> 599) status codes, an
HtmlPartial.Failure
is returned - A handler is also supplied which translates connection-related exceptions into an
HtmlPartial.Failure
object Connector {
def somePartial(): Future[HtmlPartial] =
httpClientV2.get(url"/some/url").execute[HtmlPartial].recover(HtmlPartial.connectionExceptionsAsHtmlPartialFailure)
}
// Elsewhere in your service:
Connector.somePartial().map(p =>
Ok(views.html.my_view(partial = p.successfulContentOrElse(Html("Sorry, there's been a problem retrieving ..."))))
)
// or, if you just want to blank out a missing partial:
Connector.somePartial().map(p =>
Ok(views.html.my_view(partial = p.successfulContentOrEmpty))
)
// or, if you want to have finer-grained control:
Connector.somePartial().map {
case HtmlPartial.Success(Some(title), content) =>
Ok(views.html.my_view(message = content, title = title))
case HtmlPartial.Success(None, content) =>
Ok(views.html.my_view(message = content, title = "A fallback title"))
case HtmlPartial.Failure =>
Ok(views.html.my_view(message = Html("Sorry, there's been a technical problem retrieving your info"), title = "A fallback title"))
}
In order to include cookies in the partial request, the HeaderCarrier must be created from the request with HeaderCarrierForPartialsConverter.fromRequestWithEncryptedCookie
rather than with HeaderCarrierConverter
from http-verbs.
class MyView @Inject()(headerCarrierForPartialsConverter: HeaderCarrierForPartialsConverter) {
def getPartial(request: RequestHeader) = {
implicit val hc = headerCarrierForPartialsConverter.fromRequestWithEncryptedCookie(request)
httpClientV2.get(url"http://my.partial").execute[HtmlPartial]
}
}
- Cross compiled for Scala 3 and 2.13. Scala 2.12 has been dropped.
- Uses HttpClientV2
- Built for Play 2.8 and 2.9.
- There are specific artefacts for each version of play. The version does not include the play version any more.
com.github.ben-manes.caffeine:caffeine
dependency has been updated to3.x
which means it only supports Java 11 or above.
Fixes template replacements for templateParameters
parameter passed to getPartial
and getPartialContentAsync
.
Drops support for Play 2.6 and 2.7.
Built for Scala 2.12 and 2.13.
Built for Play 2.6, 2.7 and 2.8.
- Injectable instances for
CachedStaticHtmlPartialRetriever
,FormPartialRetriever
andHeaderCarrierForPartialsConverter
are provided. They should be used in preference to implementing the traits. HeaderCarrierForPartialsConverter
requires aApplicationCrypto
(amongst other dependencies) instead of an ambiguousdef crypto: (String) => String
function. Using the injectable instance ofHeaderCarrierForPartialsConverter
should suffice for most use-cases, and ensures that encryption is properly applied.PartialRetriever.loadPartial
andPartialRetriever.getPartial
now return an asynchronousFuture[HtmlPartial]
PartialRetriever.getPartialContent
is deprecated, in preference toPartialRetriever.getPartialContentAsync
, which returnsFuture[Html]
Deprecated removals:
- The deprecated type
CachedStaticHtmlPartial
was removed - useCachedStaticHtmlPartialRetriever
instead. - The deprecated type
FormPartial
was removed - useFormPartialRetriever
instead. - The deprecated method
PartialRetriever.get
was removed, usePartialRetriever.getPartial
orPartialRetriever.getPartialContent
instead.
This code is open source software licensed under the Apache 2.0 License.