Solving Limitations with the Kendo AutoComplete Control

The Kendo AutoComplete control provides a great user interface for type ahead functionality. It works seamlessly with bound JSON data from an AJAX data source and provides a tidy, yet customizable, view of the data. Some of the functionality of the behavior is customizable, and it exposes a decent set of events. You can view the demo of the control here.

Even though the control has a decent number of features, the API is still really lax in offering you specific information that was selected. Even though you may have sent an array of JSON object with 20 properties, you can only access the selected value (please vote for my request to change that behavior). However, there is a way to work around that limitation, which is to create a custom template. The autocomplete control has a template attribute that takes a string for the UI to use as each data item. Internally in this template, the “data” object refers to the data source bound to this template, and is a way to display multiple properties of data in the same line item.

Let’s briefly look at the Kendo AutoComplete basic configuration, which is the following. (Note that this article expects you to have a familarity with the control; I won’t be going over it in detail here.)

   placeholder: 'Name Search',
   delay: 500,
   dataTextField: 'Name',
   dataValueField: 'ID',
   filter: 'contains',
   minLength: 3,
   dataSource: ..

Out of the box, this auto complete wires up to a data source, matching a Name as the text and ID as the value. The kendo datasource ties the control to the backend data store (an example for another time). Now suppose you had this JSON:

{ "ID": 1, "Name": "Ted", "Address": "101 Test Rd", "Phone": "555-555-5555", "Email": "" },
{ "ID": 2, "Name": "Bob", "Address": "21 Other Rd", "Phone": "567-555-5555", "Email": "" }

When the type ahead behavior occurs, after typing 3 characters, the control sends back a request with the current text and displays the response in the dropdown. But it only shows the value in the Name property (“Ted”, “Bob”).

This is where the template property comes into play

   '<div class="item" data-address="#:data.Address#" data-phone="#:data.Phone#" data-email="#:data.Email#">' +
   '<div><strong>#:data.Name#</strong><div>' +
   '# if (data.Address != null) { # <div>#:data.Address#</div> # } #' +
   '<div>#:data.Phone#, #:data.Email#</div>' +
   dataSource: ..

With the template property, this provides a custom UI to the user. You can see the “data” object reference; this is the actual underlying JSON data at execution time. Templates work great but we still have the unfortunate problem of not being able to access the “Address”, “Phone”, or “Email” attributes of the JSON object outside of displaying in the list. This is where the data attributes on the root DIV come into play. Using those attributes, we can extract them out from the selected item during the select event:

select: function (e) {
   var $item = e.item.find("div.item");

On select, e.item refers to the HTML representing the current item. Finding the DIV wrapper we have our data attributes on, the data can be extracted and pushed somewhere. In this case the fields are populated into an edit form.

Hopefully this was a good overview as a means to grab additional useful, meaningful information that I could not find available anywhere else in the Kendo AutoComplete control API. Using this technique, we can gain additional meaningful information to populate another portion of the UI when something changes.


AJAX File Uploads with HTML 5

I see on StackOverflow the question often how to upload a file via AJAX.  It turns out it is actually not that difficult. We utilize a solution using the Html 5 FileReader component. The idea is have the file reader read a PDF file contents, and transfer those contents to a hidden field (stored in the $hidden variable). A portion of the script we use is shown below.

$("#FileUpload").on('change', function (e) {
var $self = this;
var file = $self.files[0];

var fileReader = new FileReader();
fileReader.addEventListener('load', function () {
   var result = fileReader.result;


Once a file is read, it invokes the “load” event with the contents of the file; the contents of the file are then stored in a hidden field. Since the contents are in the HTML file, it’s possible then to send those HTML contents to the server, or be a part of a normal postback lifecycle.

The idea with “readAsDataURL” is it creates a URL like the following: “data:text/html,sdafadf34533543sefkafdsadf90809as8dfasdf90asdf9fsdf” where the contents of the PDF are really large. You’ll need to extend what is acceptable as a part of your content.

On the server side, the solution is as simple as splitting the contents after the first comma like:

//Strip off the "data:text/html," portion of the data URL posted back to the server
fileContents.Substring(fileContents.IndexOf(",") + 1);

This is one of many solutions; there are a wide variety of JQuery or other solutions out there.

Watch Your Scoping

I recently found a bug in a plugin and so I figured that would be a good time to offer a public service announcement as to why you have to be careful with scoping in JavaScript.  The plugin I’m featuring is just a quick example of the problem.  Suppose your had the following HTML snippet:

< div id="section1" class="section" >
First Button
< span id="sp1" >0< /span >
< /div >
< div id="section2" class="section" >
Second Button
< span id="sp2" >0< /span >
< /div >
< div id="section3" class="section" >
Third Button
< span id="sp3" >0< /span >
< /div >

Pretty simple. The idea of my plugin was to target the root DIV tag, and then parse down to the BUTTON and SPAN at an individual level. Now, as I think about writing this, the reality is of the situation, I should have considered the JQuery Widget API, as I think that would have been better situated for what I am about to do. I was under the gun to get this feature completed, and this solution was not optimal, but it worked and did get the job done. Anyway, the JQuery plugin is below:

$.fn.parse = function() {
  return this.each(function() {
    var spn = $(this).find("span");
    btn = $(this).find("button");
    btn.on("click", function(e) {
       var n = parseFloat(spn.html());
       n += 1;
       btn.html(btn.html() + "(clicked)");

The idea is that the span and button are retrieved within the context of the root DIV, and when the button is clicked, both elements are updated to indicate that a click occurred. You’ll notice though, that while the span gets the proper update, the button does not (always targets the last). This is simply because the button doesn’t include “var” declaration. This means the button is scoped beyond the current context of the each() callback. Because of this, the last button was selected and thus the last button is represented in the query.

This produces the result:


Adding VAR was the immediate solution. Another reminder why you need to make sure you variables are scoped correctly.

Just to brainstorm, another solution could be to, using the current reference within the button click, access the button through the callback and even target the SPAN that way, rather than relying on variables.

You can view the Gist here.

Single Page Binding with Kendo UI ListView

If you’ve looked at the demos on the Kendo UI site, you’ll notice the ListView and DataSource combination are a pretty capable combination. The ListView gives you full control over the user interface, while supporting common functionality like paging, sorting, and more. The DataSource provides read and update functionality to a local or remote data source, even giving you full control over these processes (for instance, you can use JQuery directly for AJAX communication). The pager natively pages through the contents of the listview automatically for you. The three widgets offer great functionality for the developer.

While the combination works well, I personally ran into a snag using the Kendo UI core version (open source). With the pager component natively paging the content, the data source required a complete dataset downloaded from the server. If your ListView will be presenting 30 records, all 30 must be retrieved from the server; if 3,000, all 3,000 must be retrieved from the server. Now natively the data source control supports server paging, most examples illustrated using the Telerik MVC wrappers for handling the server-side processing, and as such, I wasn’t sure whether it was supported. If it works, I would recommend using the kendo pager as it offers the smoothest navigation; but if not, this workaround worked just as well, with some added effort. In order to get around this, I ended up using the Bootstrap Paginator plugin.

The bootstrap paginator allows you control over the number of pages to show, and provide delegation on user interaction, with the example below.

            currentPage: 1,
            totalPages: 10,
            onPageClicked: function(e, evt, type, page){
                //Reload the listview - listview uses custom AJAX option

The currentPage option sets the current page in the list, within the range of total pages. It’s possible to preload these from an MVC model, especially when you factor in postbacks (the pager needs reinitialized on postbacks), as in the following:

   currentPage: @Model.CurrentPage,
   totalPages: @Model.TotalPages

When the user clicks on a page, it fires the onPageClicked callback handler, which subsequently triggers an AJAX action back to the server. We’ll need the new page index from the event handler; we can get it directly from the plugin, or store the current index in a hidden variable. Either way, this piece of information needs passed back to the server.
If you looked in the example online, it has a custom AJAX action as shown below.

    dataSource: {
       transport: {
           read: function(o) {
              var index = // Get index from hidden variable or wherever

                  type: "post",
                  url: "@Url.Action("Action", "Controller"),
                  data: { index: index, otherParams: "OTHER PARAMS" },
                  success: function(d) { o.success(d); },
                  error: function(d) { o.error(d); }

Here we trigger the postback to the server, and pass in the list of form data values, as well as the currently selected page index. Since the items per page is hard-coded in this scenario (at say 10, for example), we can quickly calculate the starting index and ending index of the current page.

There are many ways to implement this solution; this is one quick, simple way to introduce paging with large lists of data, where each page is dynamically loaded at paging time.

Working with CheckBoxList

I know the content of this post is outdated for most users, as most users have moved on to something other than ASP.NET Web Forms. But for those of you still using web forms, and even for those using MVC, I have some code I’m about to remove (as the requirements changed), and as such, want to post it in case it helps someone else.

There are times when a series of options are presented in a CheckBoxList, such as a list of rows. For this, typically what’s used is the CheckBoxList control, which renders a table. In each cell of the table is a checkbox defined as <input type=”checkbox” />. Each of these checkboxes represented a role; however, to add to the speciality of the situation, the first item displays an “All” item. This “All” item represents all of the items in the list, but does not check the other items. Instead, it’s a manually inserted item with no entry from the database, nothing from the underlying Roles table. To start, here is the CheckBoxList control:

<asp:CheckBoxList ID="RolesList" runat="server" 
   DataTextField="RoleName" DataValueField="RoleKey"
   RepeatLayout="Table" RepeatColumns="3" 
   RepeatDirection="Horizontal" />

To show the all item in the list, the following code was used. Noticed the CSS class used.

Dim item As New ListItem("All", "")
item.Attributes("class") = "AllItem"

In script, we grab all of the inner checkboxes, and do it in a way we don’t have to understand the underlying markup (as server controls hide the underlying client markup in this case). The :checkbox pseudo selector grabs all of the checkboxes generically as shown below:

var roles = $("#RolesList").find(":checkbox");

With this list, we can attach to the clicking of all the items. The first item of the list is the “All” item (note that the trick I used to identify this special item was to add an AllItem class definition). If the “All” item was checked, the handler removed checkboxes from all of the other checkboxes. Otherwise, when checking another item that’s not the “All” item, the handler removes the check from the first item. How it was done is shown below: () {
	var allItem = $(this).parent().hasClass("AllItem");

	if (allItem) {
		if (this.checked == true) {
			roles.not(":first").attr("checked", false);
	else {
		roles.eq(0).attr("checked", false);

To begin, we check if the current checkbox has the AllItem; the CheckBoxList control attaches the AllItem class to the parent SPAN element above the INPUT element, which is why the parent() method is used. To set the checked on the first item, I used the .eq(0) method, or finding the first item in the list of roles, as checked (which happens to be our “All” item). Otherwise, the not() method is used to remove all but the All checkbox and clear those check marks.

And voila, we have list with a special “All” item as the first designated item.

Using JQuery FullCalendar with ASP.NET MVC and Entity Framework

I had a need to use a calendar component in my application. Calendars are hard to come by, that also act as a scheduling component. In comes JQuery FullCalendar, a plugin that renders a calendar with event components.

To set this up

1. Create an Entity Framework model with all of the AdventureWorks entities.  Choose whatever template you like. Leave the context name as the default “AdventureWorksEntities”.

2. Create a new MVC project. Add a new controller named OrderHistoryController. The OrderHistoryController that I used is defined as the following:

public class OrderHistoryController : Controller
// GET: /OrderHistory/
public ActionResult Index()
return View();

public ActionResult List(long start, long end)
var epoch = new DateTime(1970, 1, 1);
var startDate = epoch.AddMilliseconds(start);
var endDate = epoch.AddMilliseconds(end);

var ctx = new AdventureWorksEntities();
var data = ctx.SalesOrderHeaders
.Where(i => startDate <= i.OrderDate && i.OrderDate <= endDate)
.GroupBy(i => i.OrderDate)
.Select(i => new { OrderDate = i.Key, Sales = i.FirstOrDefault()}).Take(20).ToList();

return Json(data.Select(i => new
title = (i.Sales.Customer != null) ? i.Sales.Customer.AccountNumber : “Untitled”,
start = i.OrderDate.ToShortDateString(),
allDay = true


The Index action serves up the view.  Once the view is loaded, an AJAX request is made back to the server, looking for any orders.  Using LINQ, we load up some of those records.  I used a GroupBy statement so that I could get one record back per date for a given month, as a way to test with a single record per day.

JSON is the preferred mechanism to return to the client.  We’ll need to massage the data a little bit in order to work with the full calendar.   For instance, we’ll have to convert the date appropriately.  For simplicity, I used ToShortDateString to get the date and parse it in JavaScript.  However, it would have been more appropriate to convert the date to Epoch time (time since 1/1/197o).

3.  Download JQuery FullCalendar from the following URL:  Copy the JS and CSS files to your project, in the Content and Scripts folder (or whatever folder structure you are using).  The files includes are:

  • fullcalendar.css – the core CSS file
  • fullcalendar.print.css – the CSS stylesheet for printing a calendar
  • fullcalendar.js – the core JS file
  • fullcalendar.min.js – the minified JS file
  • gcal.js – Google calendar integration

4.  Add scripts to your page

Rather than adding all the scripts to every page, I added the scripts to the OrderHistory view.  To do this, I started by creating a bundle.  Open up Bundle.config and add the following:

bundles.Add(new ScriptBundle(“~/bundles/calendar”).Include(






));bundles.Add(new StyleBundle(“~/Content/calendar”).Include(




We use these bundles within the view. To setup the calendar, all that we need to do is add a DIV to a page with an ID, like <div id=”container”></div>. The FullCalendar plugin simply attaches to

    header: {
        left: ‘prev,next today’,
        center: ‘title’,
        right: ‘month,agendaWeek,agendaDay’
    editable: true,
    eventClick: function(i, evt, view) {
    events: function (start, end, callback) {
            type: “post”,
            url: ‘@Url.Action(“List”, “OrderHistory”)?start=’ + start.getTime().toString() + “&end=” + end.getTime().toString(),
            success: function (d) {
                var list = [];
                for (var i = 0, len = d.length; i < len; i++) {
                    var item = d[i];
                    item.start = new Date(item.start);


            error: function (e) {


The plugin supports a variety of members defined in the documentation that can be specified at initialization time. The key is the events property, which defines the source of the events. The source can be a static list, a pointer to a page or web service, or even a function callback. The latter option gives you the most flexibility, and I’ve demonstrated it’s usage in this example. The callback gets a start and end parameter. These parameters are dates, converted to epoch time (in milliseconds) as they are sent to the server. JQuery is used to make the call to the server, and as the results come back, the process does some massaging first. For instance, a date is coming back to the client in string form, and converts the date back to a date form.

Once our final list is complete, and to load them into the calendar, they are passed to the callback. The plugin handles all of the loading of data into the calendar. Remember from the MVC controller, it returned a title, start (date), and an allDay indicator. Using this data is what the FullCalendar plugin uses as the data source. More parameters

Building JQuery Widgets Part 2

In this article, we’re going to look at some of the finer aspects of the plugin we last build a little bit ago.  Let’s start by looking again at the _init method.  As I mentioned previously, this method runs when the plugin is initialized, after the _create method runs (if there is one).  On init, we have this definition.

_init: function() {

this.options = $.extend({

title: “Interactive Help”,

buttonText: “OK”,

alertIfHidden: true,

beforeShowCallback: null,

afterShowCallback: null,

nextCallback: null,

startingCallback: null,

finishCallback: null

}, this.options);    this._elements = [];

this._currentIndex = 0;

this._total = 0;



Notice the use of the $.extend method; this method is very handy for establishing default values.  The method takes the values passed into the first parameter, and passes it to the second object, only if a value doesn’t already exist.  This is a great way to ensure a field exists, and helps you from having to write a lot of code that checks for a property’s existence.  What I mean by that is if you didn’t use the extend method, if your plugin tries to use this.options.startingCallback, when startingCallback was never supplied in the options, then an startingCallback is undefined an an exception is the result.  Our implementation of extend above ensures a title, buttonText, etc. field exists on the options object, so we don’t have to do that type check.

Notice that we have some options with a “callback” extension; these are the equivalent to an event in .NET or some other object-oriented language.  An event in an object-oriented language is defined explicitly, allowing the consumer of that event to attach to it and receive notification when the event occurs.  Widgets have the same functionality, in a different way.  We can attach to the event handler by supplying a JavaScript function, and then invoke that function at the appropriate time At various points in the plugin, we’ll invoke the callback by doing the following:

if (!!this.options.nextCallback)

this.options.nextCallback(this, { index: this._currentIndex, total: this._total });

We invoke the method, if it exists, and pass in any additional parameters.  Another important point to note is that you as a developer can interact with the consumer through these callbacks.  For instance, take a look at the code below.

var args = $.extend({
oldElement: el,
oldLeft: (!!pos && !!pos.left) ? pos.left : null,
oldTop: (!!pos && !! ? : null,
element: null,
selectorFunction: null,
left: null,
top: null
}, def);if (!!this.options.beforeShowCallback)
this.options.beforeShowCallback(this, args);

if (!!args.element)
el = args.element;

if (!el && typeof(args.selectorFunction) !== “undefined”)
el = args.selectorFunction({ element: this.element });
if (!!el) {
pos = this._getElementPosition(el);

In this example, we construct an event argument that has specific parameters.  These parameters are passed to the beforeShow event, through the beforeShowCallback (notice the use of extend to ensure certain parameters exist).  After it’s called, the widget interrogates the argument object for any changes the user may have made.  For instance, the user may have supplied an element, or even a function for selecting the element.  In this way, users can provide the widget input at the time the event has executed, something we also have the ability to do in object-oriented languages.

When creating widgets that others on your development team, or possibly the world if  you release your widget to the public, the difficulty comes with how to let them know how to use your plugin, what parameters are available for each callback, and other aspects requiring documentation.  Without good documentation, that supply the parameters being passed in at initialization time or supplied by a callback, the consumer of the widget will have difficulty using it.  While we don’t always like documentation, providing it is key to your widget’s success.  Sure, the above average developer will read the source, but the rest of your audience will be left in the dark without good direction.

Building JQuery Widgets Part 1

JQuery provides an extensive reusability system in the form of plugins and widgets.  Plugins are native to JQuery and reside as a function that can be defined either statically, or per a range of elements.  We’ll touch on JQuery plugins in a later post.  JQuery widgets, on the other hand, are  a part of the JQuery UI framework.  At a minimum, from the JQuery UI download page (, all you need to download is the core feature, the widget feature, and the mouse feature (for mouse-oriented widgets).

This now allows us to create a widget as so:

 $.widget(‘ui.HelpBox’, { /* Definition of Widget */ });

JQuery begins a widget by using the $.widget  method (added on by JQuery UI).  This is the point the widget gets defined; the definition of the widget comes in the form of a class definition, as we’ll see soon.  It may be beneficial to see how you would create a widget, to add some perspective.  Below is how we would instantiate our HelpBox widget.

$(“#SomeElement”).HelpBox({ /* options */ });

Here you can see a widget is applied to an element. A widget is linked to an element within the DOM. It is at this point we are actually instantiating our HelpBox widget, and providing the initial settings for the widget (or options).

Jumping back to our widget definition, when its created, the _create and _init methods are invoked.  In most scenarios, the _init method is sufficient.  Below is the body of the widget defined in the “Definition of Widget” section in the comment above, in addition to some other methods.


_init: function() { . . },   _buildUI: function() { . .},

add: function(elementSelector, descriptionHTML, name) { . . },

_finish: function() { . . },

getSize: function() { . . },

next: function() { . . },

run: function() { . . },

_show: function(def) { . . },

stop: function() { . . }


We are essentially building the API of the widget, much like building an object’s API using the prototype definition. Usually a JavaScript class has additional variables used to track pieces of information pertinent to the class. During the init method, this is where we will do that, as shown  below.

_init: function() {

this.options = $.extend({

title: “Interactive Help”,

buttonText: “OK”,

beforeShowCallback: null,

afterShowCallback: null,

startingCallback: null,

doneCallback: null

}, this.options);

this._elements = [];

this._currentIndex = 0;

this._total = 0;



During init, we add instance variables to the widget using “this.variable”, which appends a variable to the widget instance. The “this” pointer points to an instance of the widget, which also allows us to call additional method. Notice the use of the extend method? This JQuery method is pretty handy; what it does is compare the first object against the second, and anywhere a member doesn’t exist in the second object, the default value provided in the first object is added to it, and returned from the method. So you can see the first object that’s statically defined is ensuring certain options have been defined by the user. This way, they won’t cause undefined errors later on.

Let’s turn to constructing the user interface:

_buildUI: function() {

var self = this;   self._outerElement = $(“<div/>”).addClass(“HelpBoxWrapper”).css(“display”, “none”);

self._titleElement = $(“<div/>”).addClass(“HelpBoxTitle”).html(“<h3>” + this.options.title + “</h3>”);

self._bodyElement = $(“<div/>”).addClass(“HelpBoxDescription”);

self._buttonRowElement = $(“<div/>”).addClass(“HelpBoxButtons”).append(

$(“<a />”).attr(“href”, “#”).html(this.options.buttonText)

.click(function() {;



self._outerElement.append([self._titleElement.get(0), self._bodyElement.get(0), self._buttonRowElement.get(0)]);


At the core of each widget is an element.  This element is referred to by “this.element”, a reference to the JQuery object containing that element.  Here we are creating some DIVs and other elements, applying CSS to the elements, which will be the user interface of the widget.  The user interface has a button, which listens to the click event.  On click of the button, it invokes a next method, a method that performs an action on the widget.  We’ll look at that in the next post.  Notice how we store a reference to each element of the widget as a variable reference (self is a pointer to this, this widget).

Usages of Widgets

Using widgets is a little awkward.  What looks like the same syntax is actually not the same.  Let’s look at how we may initialize the widget again:

$("#SomeElement").HelpBox({ buttonText: "Okay", title: "Help" });

This is the point of initialization. This calls _create and _init. We provided some options, which override the defaults that we specified in the _init method (“Okay” overrides “OK” as the default button text). Now, to call a method (like the run method) using the JQuery widget, the following is the syntax.


We don’t actually call a method on the object; we use the widget instance to invoke the method. It’s a little awkward at first, but eventually you get used to it. To call our add method, with parameters, you simply pass in the parameters like so:

$("#SomeElement").HelpBox("add", "#MyTargetElement", "My target description");

You can see that all interaction with the widget goes through the widget, rather than the widget’s API. You can also override the options by first specifying the “options” collection, then the name of the option, and lastly provide the new value.

I hope this was an informative look at using JQuery Widgets in your applications.

Knockout and Binding Lists

I have been using Knockout in an MVC project where I have been binding list-oriented data in the user interface.  I’ve been trying to use a more efficient approach to loading the UI by pushing the view with no data bound from the server, then following up with a subsequent request to serve up JSON, which populates the list.  This is the technique I’m focusing on in this article.  This means that the page builds an empty document model, then populates the model on document ready.  In my page, I build an empty view model:

function viewModel() {
var self = this;

self.listData = ko.observableArray([]);

Initially we start with an empty list.  At this point, on initial load, it’s beneficial to show something to the user that we have no data.  In order to do this, I found adding some computed properties for determining status was helpful.  These properties also existed in the model:

self.hasLoadedListData = ko.observable(false);
self.emptyListData = ko.computed(function() { return self.listData.length > 0; });

Here we have two properties, one for determining if we bound any data to the UI at all, and the second for determining whether the list is empty.  The difference between the two is that we may not want to show the list if there isn’t any data to bind; however, once we bound, we may want to instead show a “no records found” message, which the emptyListData property is used for.  Additionally, if we have no data to bind, and the observable points to a null value, we can get an exception too.  However, I’m going to shortly circumvent that by using the “if” binding.  In the user interface, we can setup the view to use these properties as so:

<div data-bind=”if:hasLoadedListData”>
<div data-bind=”if:emptyListData”>
No records found.
<div data-bind=”ifnot:emptyListData”>
<!– data template –>

Now it’s time to load the data.  Once data is passed to the model, it loads the view with the data at the time it’s populated.  I’m not going to get into the aspects of where the data comes from. Assuming we can get JSON from some data store, the JSON we would use, requested from JQuery, can then be passed to the view model, as in the following:

type: “post”,
url: “…”,
data: { .. },
success: function(d) {
viewModel.itemData(d.Data); //array data in Data property

Here we get the data in JSON form, grab the array data from the Data property (as it’s recommended to return an object as the root object, not an array, for security purposes), and push it to the model.  There is an interesting point here; when we push the data in, the data in the array is not observable by its nature.  While this data would load into the user interface, any changes made to the values of the individual objects themselves are not observable and do not participate in two-way binding.  You could do a conversion like:

from (var i = 0, len = d.Data.length; i < len; i++)
viewModel.itemData.push({ firstName: ko.observable(d.Data[i].firstName), .. });

Through this conversion, each object is observable and participates in two-way binding.

Now that we have our data, it loads into the user interface, either through the observable templates as I blogged about before, or through an inline template.