Skip to main content

Sharing data between slides

Related links:

In order to share data between slides, we will be using the deck's context. This is a source of data that holds information specific to the appointment, this data can be queried and used by your slides, as well as updated by them throughout a presentation - making it the perfect medium for sharing data between the slides of your deck.

Now let's get stuck in and learn how to use the context!

Generating your context

First up, we'll need to generate the context, to do this, we'll be using fieldsets. Read on to learn how to import the fieldsets hook and get started.

Add fieldsets interface to hooks

Let's set it up so that the CDK and LivePreso recognise that you want to deal with fieldsets. First you will want to create a hooks file, use the hooks object in the project.yaml to define where in your deck your hooks.js file is located.

project.yaml

hooks: js/hooks.js

Second, we'll need a fieldsets file. In general, you place this in js/hooks/fieldsets.js. To this file you will add the bare minimum for fieldsets to be loaded.

fieldsets.js

export default function (options) {
const { Fieldset } = options;

return new Fieldset({});
}

hooks.js

Going back to our hooks.js file, you need to export the hook:

import Fieldsets from "./hooks/fieldsets.js";

export default {
fieldsets: Fieldsets,
};

That's it! The CDK and LivePreso now read fieldsets.

Generating the context

The context is almost entirely generated by fieldsets, and is only added to as your deck needs it. Modifying context can be done globally on three separate events: onLoad, and onSave, at least while there are no fields available.

export default function (options) {
const { Fieldset } = options;

return new Fieldset({
onLoad() {
return {
context: {
onLoadField: true,
},
};
},

onSave() {
return {
context: {
onSaveField: true,
},
};
},
});
}

If you test this in the CDK or LivePreso app, you will notice on load the onLoadField key has been added to the context. When you press Run (analogous to pressing save in the preso create screen), it will add the onSaveField key to the context as well. Note how the context in each function is merged together, rather than overwriting each other.

The result of our context after save is:

{
"fields": {},
"onLoadField": true,
"onSaveField": true
}

Populating the context on preso creation

Now that you know how to add context, it's probably a good idea to start adding useful information to your presentations. Each function exposed by fieldsets exposes an object containing useful information about the state of fieldsets and the preso at different stages of its creation. From field state, to customers and contacts selected, this can be used to create useful context.

Let's make use of data associated with the appointment - specifically adding the names of the contacts to our context, as this is something that might be done often.

export default function (options) {
const { Fieldset } = options;

return new Fieldset({
onSave({ data }) {
return {
context: {
attendees: data.contacts.map((contact) => contact.fullName),
},
};
},
});
}

Generally it's best to only add the data you need into your context, keeping it simpler to navigate and access what you need.

Now if you were wanting to access to the list of your attendees in your presentation, you could use:

Bridge.Context.get("attendees");

See the fieldsets options reference for more information on the data available.

Accessing context data from your deck

Once you've finished generating your context, you'll be wanting to access that data from a slide.

Your first option is to use Bridge.Context.get. This function includes the ability to supply an optional default value, which is returned if nothing is found for your supplied key.

// fetch the toggle state, or default to 'on' if it is not set.
var state = Bridge.Context.get("toggle-button-state", "on");
warning

If you choose not to supply a default, be extra careful to add validation and tests to the data you receive. You may otherwise find yourself with broken content in the wild.

Robust selection

Similar to accessing data from feeds, we highly recommend the use of robust selection to help prevent null values from being returned by your queries, and breaking your content.

To make use of JSONSelect's robust selection when querying the context, there are only two things you need to do:

  • First, you must decide whether you expect a single value or multiple values every time you select something from the context, then use Bridge.Context.match or Bridge.Context.match_many appropriately.
  • Second, you must provide a default value whenever you use either of these functions, in case there are unexpected problems with the feed.

See jsonselect for the documentation on how these selectors work.

Logging

Unlike feeds logging - which provides a stream of results for each call (failures and successes included), context use only logs warnings to the console - ie. when a key is missing, no default was supplied for a match or match_many, or when a key returned more results than expected.

Saving data to the context from your deck

In the calculator and questionnaire example we mentioned in the context overview, you will want to save certain updated values to the context in order for them to be referenced again in a later viewing. In order to do this, you will use Bridge.Context.set(key, value), where key references the context variable you wish to updates, and value is its new value.

// switch the toggle state manually
state = state === "on" ? "off" : "on";

// write back to the context
Bridge.Context.set("toggle-button-state", state);

To write to a specific location in the context, which may or may not exist, you can use Bridge.Context.setPath(path, value), where path is a string of selectors.

// write the visibility of the first row in the table "newtable" to the context
Bridge.Context.setPath(".tables .newtable .rows .0 .visible", false)

// result in the context
{
"tables": {
"newtable": {
"rows": [{
"visible": false
}]
}
}
}

Fetch presentation agenda

You would like to create an agenda slide which lists all sections/slides in the created presentation, no problem! Bridge.Context.getAgenda() returns a nested set of decks suitable for producing an agenda slide.

Example response:

Returns an array of decks assigned to the presentation.

[{
"enabled": false,
"path": "awesome",
"sections": [{
"path": "awesome/were_innovative",
"title": "We're innovative",
"visible": true,
"slides": [{
"path": "awesome/were_innovative/introduction",
"title": "Introduction",
"visible": true,
"subslides:" []
}, {
"path": "awesome/were_innovative/super_stats",
"title": "Super stats",
"visible": true,
"subslides:" []
}, {
"path": "awesome/were_innovative/fancy_infographic",
"title": "Fancy infographic",
"visible": true,
"subslides:" [{
"title": ""
"visible": true
}, {
"title": ""
"visible": true
}]
}, {
"..."
}]
}, {
"..."
}],
"title": "Digital is awesome"
}]
info

LivePreso's current configuration only allows one deck assigned per presentation. This is planned to be expanded on in the future.

warning

As a result of how our screenshot server currently works, sending multiple PDFs of the same presentation may result in conflicting agendas. PDFs are unique per-snapshot, so unless the change also updates the snapshot (eg. editing an appointment) the screens will not be regenerated.

This affects instances where an appointment is created, shared, slides are sorted (slide sorting does not update the snapshot) before it is shared again - in this example the agenda will appear the same as the first share. However, if the salesperson then performs an action that updates the snapshot (edits the appointment, updates the context etc.) the next PDF share will be resolved.

This is planned to be fixed in the future, and documentation will be updated accordingly.