Skip to main content

Content field extensions: the slider

On this page we'll show you how to develop a content field extension using the example of a slider. We'll walk through the slider example in detail and introduce the core features of the Dynamic Content SDK.

You can right click to download the complete slider example as an HTML file.

The extensions SDK is available on GitHub.

The slider extension
Link copied!

The slider is a very simple content field extension that allows the user to choose a number in a specified range. Although the functionality is very simple, the sample does make use of many of the key features of the Dynamic Content extensions SDK.

A content item containing with a field implemented by the slider extension

Using the slider extension in a schema
Link copied!

Add the ui:extension keyword to a property to specify that the property is rendered by an extension. Specify the name that was used to register the extension, together with an optional list of parameters.

An example of a property that uses the slider extension is shown below. The extension is designed to be used with a property of type number. The params specified in the property are optional, so you can choose not to include them and default values will be used instead.

The schema shown below assumes the slider has been registered with a name of "simple-slider". See the registering the slider section for more details of how to register the extension and set up snippets to make it easier to add a property in the schema editor.

"type": "object",
"properties": {
"transitiontime": {
"title": "Transition time",
"description": "Choose the transition time in seconds",
"type": "number",
"ui:extension": {
"name": "simple-slider",
"params": {
"min": 0,
"max": 20,
"value": 6
}
},
"minimum": 0,
"maximum": 20
}

}

You could replace "name" with "url" and specify https://amp-product.s3-eu-west-1.amazonaws.com/doc-examples/slider/index.html for the extension URL, but registering the extension is the more flexible approach.

Inititializing the SDK
Link copied!

Note that this example uses the CDN hosted file of version 2.0.0 of the SDK: https://unpkg.com/dc-extensions-sdk@2.0.0/dist/dc-extensions-sdk.umd.js" to include the extensions SDK. For other ways of using the SDK in your app see SDK Read Me.

To initialize the SDK we use the init function. This loads the web app into an iframe and establishes the connection with Dynamic Content. The function returns a promise that resolves to an instance of ContentFieldExtension, which you can then use to call other functions. If the connection cannot be established, if the web app URL is not available, for example, then an error is returned. If the slider extension cannot be loaded, then Dynamic Content will render it as a standard number property instead.

dcExtensionsSdk.init()

SDK functions must be called asynchronously and one way to do this is to wrap the calls in a JavaScript await. To use await you must call it from within a JavaScript function defined as asynchronous, as shown in the code below.

(async function  () {
try {
new Extension(await dcExtensionsSdk.init())
} catch (e) {
document.body.innerHTML = 'Failed to connect'
}
})()

The slider example defines a class called Extension that is constructed with the ContentFieldExtension instance returned by the SDK's init function. The class contains all the methods for setting up the slider, reading the params defined in the schema and updating the value of the property that uses the slider when the user changes its value.

Reading the params
Link copied!

The slider can accept 3 values defined in "params" section of a property that uses the extension: min, max and value. However, the schema is still valid if these params are not included, so we need to ensure that default values are set up if the params are not defined.

Parameters sent to the extension and defined in the schema are available in contentFieldExtension.params.instance, while installation parameters are found in contentFieldExtension.params.installation.

 initializeInput() {
const { min = 0, max = 10, value = 0 } = this.contentFieldExtension.params.instance;

Object.assign(this.slider, {
min,
max,
value
});

Any additional params defined in the schema will be ignored.

Reading stored values
Link copied!

If the user has saved a content item with a property that uses your extension, then you will need to restore the data that was saved. In the case of a slider we just need to retrieve the previously stored number.

To retrieve the previously stored value call the contentFieldExtension.field.getValue() method. Because we may be working with a content item that has not been saved, then we need to check the value against "undefined". If a value is returned, we store it in the currentValue instance variable of our Extension object. If a value has been set, then this will be used instead of the value passed in params.

 async setCurrentValue() {
try {
const savedValue = await this.contentFieldExtension.field.getValue();

if (typeof savedValue !== "undefined") {
this.currentValue = parseInt(savedValue, 10);
}
} catch (err) {
console.log(err);
}
}

The getValue() method is called asynchronously and if it fails we just log the error to the console and don't change the current value.

Setting the frame size
Link copied!

After setting up the value of the slider we then set the size of the frame containing our extension. We can set the frame size in pixels, but the SDK contains an auto resize function that will resize the frame when its content changes.

this.contentFieldExtension.frame.startAutoResizer();

Our slider is fixed size so the frame size won't change, but if we allowed the user to add an array of values, then the auto resizer would ensure that the frame would automatically resize when new items are added.

Updating the property value
Link copied!

When the user updates the value of the slider, we need to update the value of the property that uses it. To do this we call this.contentFieldExtension.field.setValue() passing the slider's current value.

async updateFieldValue(value) {
try {
await this.contentFieldExtension.field.setValue(parseInt(value, 10));
} catch (err) {
// the field value is not set to the new value, write a warning on the console
console.log(err.message);
}
}

Notice that we convert the value to a number before saving it back to the property. If we tried to set a value other than a valid number, the content would not be valid and the value could not be saved.

Registering the extension
Link copied!

Registering an extension makes it easy to add a property that uses it to in the schema editor. The example schema shown earlier on this page assumes that the slider extension is registered on your hub with a name of "simple-slider" and using the URL https://amp-product.s3-eu-west-1.amazonaws.com/doc-examples/slider/index.html.

To register the extension, choose "Extensions" from the Development menu and click "Register extension".

To register an extension you must add a label, name, its URL. You can also add a description.

In this section, you can navigate to the separate Installation parameters tab. You can also add one or more snippets:

{
"title": "transitiontime",
"description": "Choose the transition time in seconds",
"type": "number",
"ui:extension": {
"name": "simple-slider",
"params": {
"min": 0,
"max": 10,
"value": 5
}
},
"minimum": 0,
"maximum": 10
}

Snippets can be chosen from the "Add extension" menu in the schema editor and that's the quickest way to add a property that uses the extension.

See registering extensions for more details.

Complete example
Link copied!

To view the complete HTML file for the slider, expand the section below.

The example does not contain any styling, so you can customize it by adding your own CSS.

<!DOCTYPE html>
<html>
<body>
// include the Dynamic Content Extensions SDK

<script src="https://unpkg.com/dc-extensions-sdk@2.0.0/dist/dc-extensions-sdk.umd.js"></script>

<p>Drag the slider to set the value.</p>
<div class="slidecontainer">
<input
type="range"
min="1"
max="10"
value="0"
class="slider slider_input"
/>
<p>Value: <span class="input_value"></span></p>
</div>

<script>
class Extension {
constructor(contentFieldExtension) {
this.contentFieldExtension = contentFieldExtension;

this.currentValue = 0;

this.slider = document.querySelector('.slider_input');
this.inputValue = document.querySelector('.input_value');

this.setCurrentValue().finally(() => {
this.initializeInput();
this.contentFieldExtension.startAutoResizer();
});
}

async updateFieldValue(value) {
try {
await this.contentFieldExtension.field.setValue(
parseInt(value, 10)
);
} catch (err) {
// the field value is not set to the new value, write a warning on the console
console.log(err.message);
}
}

async setCurrentValue() {
try {
const savedValue =
await this.contentFieldExtension.field.getValue();

if (typeof savedValue !== 'undefined') {
this.currentValue = parseInt(savedValue, 10);
}
} catch (err) {
console.log(err);
}
}

initializeInput() {
const {
min = 0,
max = 10,
value = 0,
} = this.contentFieldExtension.params.instance;

Object.assign(this.slider, {
min,
max,
value,
});

// set the slider value to the saved value if the content item has been previously saved
if (this.currentValue != 0) this.slider.value = this.currentValue;

// get the label to show the current slider value
this.inputValue.innerHTML = this.slider.value;
this.slider.onchange = event => this.onInputChange(event);
}

onInputChange({ target: { value } }) {
this.inputValue.innerHTML = value;
this.updateFieldValue(value);
}
}

(async function () {
try {
new Extension(await init());
} catch (e) {
document.body.innerHTML = 'Failed to connect';
}
})();
</script>
</body>
</html>

To find out more about features provided by the SDK and not included in the slider example, build the extensions SDK locally and view the reference in the "docs" folder. You can also find the SDK documentation online.

From the ContentFieldExtensioninstance you can access features to display image, video and content browsers and access information such as the available locales and the visualization URL.

Dynamic Content Extensions SDK

Extensions Style Guide

SDK Documentation