Context-sensitive components
Describes context-sensitive components in the Optimizely user interface.
Optimizely supports context-sensitive client components. Context refers to the current page the user is working with. Because components are loosely coupled, the context service object handles the current context. To retrieve the present context:
var contextService = dependency.resolve("epi.shell.ContextService");
var currentContext = contextService.currentContext;The context service on the client interacts with the server to resolve context for the selected page, block, or entity. The actual properties on the context object depend on the type of context displayed, but a few properties are available for all contexts:
uri– The key to uniquely identify the entity in context.previewUrl– The URL to display the entity in the editing UI.data– The values of the entity in context.type– The type of data for this context. This information is derived from the URI.id– The ID of the data for this context. This information is derived from the URI.
Context on the server implements the IClientContext interface and is serialized to the client.
Example: epi.cms.contentdata context
{
"parentLink" : "4",
"customViewType" : "",
"language" : "en",
"publicUrl" : "/MaintAlloy/Alloy-Track/",
"capabilities" : {
"languageSettings" : true,
"securable" : true,
"dynamicProperties" : true,
"isFolder" : false,
"isPage" : true,
"contentResources" : true,
"language" : true,
"isBlock" : false
},
"languageContext" : {
"isTranslationNeeded" : false,
"language" : "en",
"isPreferredLanguageAvailable" : true,
"preferredLanguage" : "en",
"reason" : 1,
"warning" : null,
"hasTranslationAccess" : true
},
"hasSiteChanged" : false,
"fullHomeUrl" : "http://localhost/MaintAlloy/EPiServer/CMS/Home",
"versionedUrl" : "",
"dataType" : "epi.cms.page",
"uri" : "epi.cms.contentdata:///8_8",
"previewUrl" : "/MaintAlloy/EPiServer/CMS/Alloy-Track,,8_8/?id=8_8&epieditmode=true",
"data" : null,
"name" : "Alloy Track",
"requestedUri" : "epi.cms.contentdata:///8",
"versionAgnosticUri" : "epi.cms.contentdata:///8"
}The ContentDataContext class is serialized to produce this client context.
Access context in components with _ContextMixin
The _ContextMixin simplifies interaction with the context by providing access to the context from a component.
define([ "dojo/_base/declare", "dojo/when", "epi/shell/_ContextMixin" ],
function ( declare, when, _ContextMixin ) {
return declare([_ContextMixin], {
constructor: function() {
when(this.getCurrentContext(), function(context) {
console.log("context loaded: ", context);
});
}
}
});The _ContextMixin extends the class with the following methods:
getCurrentContext()– Returns an available context or a deferred object that resolves to the context when it is available.currentContext– The currently loaded context. This may be null.contextChanged(context, callerData)– Overridable method called when the context changes. Components check that the context is not null and may look atcontext.typeto determine whether they work with a given context.contextChangeFailed(previousContext, callerData)– Overridable method called when loading the context fails for any reason.
Change the current context
To change the current context, publish a message to the /epi/shell/context/request channel with parameters for the context as the data. A URI parameter property is required to determine which type of context to load. The following example changes the current context to an Optimizely Content Management System (CMS) ContentData object:
var pageLink = "5_135"; //Replace with code to determine the pageLink for the page you want to change to..
var contextParameters = { uri: 'epi.cms.contentdata:///' + pageLink };
topic.publish("/epi/shell/context/request", [contextParameters]);Listen to context changes with subscription
Without using _ContextMixin, subscribe to context changes using the Dojo pub or sub infrastructure. To react to a context change, subscribe to the /epi/shell/context/changed message:
startup: function () {
this.subscribe("/epi/shell/context/changed", this._contextChanged);
},
_contextChanged: function (newContext) {
if (!newContext) {
return;
}
//Do something with newContext.
}Implement a context resolver on the server
The following context resolver interfaces provide context for certain entities:
- Resolve a known reference using URI
- Query context on a specific URL
The following example shows a context resolver that performs these tasks:
/// Resolves URIs and URLs to files for the shell context service.
[ServiceConfiguration(typeof (IUrlContextResolver))]
[ServiceConfiguration(typeof (IUriContextResolver))]
public class CmsFileContextResolver: IUriContextResolver, IUrlContextResolver {
private VirtualPathProvider _vpp;
public CmsFileContextResolver(VirtualPathProvider vpp) {
SortOrder = 123;
_vpp = vpp;
}
/// The name of the model the context contextualizes.
public string Name {
get {
return "epi.cms.unifiedfile";
}
}
/// Resolves a page link in URI format.
public Task<ContextResolutionResult> TryResolveUriAsync(Uri uri, CancellationToken cancellationToken = default) {
var context = ResolvePath("~" + uri.LocalPath);
return Task.FromResult(new ContextResolutionResult(context != null, context));
}
/// Tries to resolve an url to page context.
public Task<ContextResolutionResult> TryResolveUrlAsync(Uri url, CancellationToken cancellationToken = default) {
var context = ResolvePath(url.LocalPath);
return Task.FromResult(new ContextResolutionResult(context != null, context));
}
private ClientContextBase ResolvePath(string path) {
var file = _vpp.GetFile(path) as UnifiedFile;
if (file == null) {
return null;
}
return new Models.UnifiedFileContext {
Uri = new Uri("epi.file.unifiedfile://" + VirtualPathUtilityEx.ToAppRelative(file.VirtualPath).TrimStart('~')),
Data = new {
file.VirtualPath,
// ... more unifiedfile-specific data
},
PreviewUrl = file.VirtualPath
};
}
/// Sort order among peer url resolvers.
public int SortOrder {
get;
set;
}
}Query for context by URL
Context resolvers that implement the IUrlContextResolver interface are queried when a URL loads in the preview frame. Publish a message to programmatically change the context to the context associated with a URL, as shown in the following example:
// queries the context service for the context belonging to a URL
var contextParameters = {
url: someUnknownUrl.toString()
};
topic.publish("/epi/shell/context/request", [contextParameters, {
sender: this
}]);ContextHistory and returning to a previous context
When an editor goes from one context to another, Optimizely keeps the history of every step through the ContextHistory and BackContextHistory classes on the client side (internal to Optimizely).
As a developer, clear the current context (and close the related view) and return to the previous context. This is typically done to close or cancel a view related to the current context.
For example, in the project overview, there is a Close component. Clicking Close clears all project context history and returns to the previous context.
Achieve the same result with the contextNavigation object on the client side. This static object exposes a back method that clears the history of the current context and goes to the previous context:
define("dojo/_base/declare", "epi-cms/contextNavigation", function (declare, contextNavigation) {
return declare("epi.cms.component.MyCustomeView", {
clicked: function () {
contextNavigation.back(this);
}
}
});Updated 10 days ago
