htmlwidgets
in effect are reusable HTML/JS/CSS components (think simple Polymer or WebComponents) I don’t recommend it, but if we wanted to use an htmlwidget
with no R, it is fairly straightforward. Even if you decided not to do this, I think it will be helpful in your journey to htmlwidgets
mastery.
We’ll use the simple but powerful jsonedit
from the listviewer
package. Its JavaScript binding is very sparse, so I hope it will be a good subject.
Output from a htmlwidget
Let’s start by seeing what happens when we create our htmlwidget. The R
code would look something like this.
library(listviewer)
# give it an empty list() or {} in JavaScript
jsonedit(list())
If we open our developer tools in Chrome, we should see something like this.
screenshot of html from htmlwidget
Each htmlwidget
will be different, but the ingredients will usually contain:
- JavaScript and CSS dependencies
htmlwidgets.js
- js/css for the source libraries which are provided in the
htmlwidget
yaml - the htmlwidget binding -
jsonedit.js
- HTML tags
- usually a
<div>
with anid
andclass='..widgetname.. html-widget'
, but depending on the widget might be a differenttag
or set oftags
<script type='application/json' data-for='..widgetid..'>
- usually a
copy/paste method
Nearly every step to enlightenment in programming starts with copy/paste, so we’ll copy/paste the bits and pieces to make this. We’ll change to use the CDN for jsoneditor
. Also, we’ll change the random element id
to mywidget
. These aren’t necessary, but they might be considered an improvement.
<!doctype html>
<html>
<head>
<script src="https://cdn.rawgit.com/ramnathv/htmlwidgets/master/inst/www/htmlwidgets.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.5.6/jsoneditor.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.5.6/jsoneditor.min.css" rel="stylesheet">
<script src="https://cdn.rawgit.com/timelyportfolio/listviewer/master/inst/htmlwidgets/jsonedit.js"></script>
</head>
<body>
<div id="mywidget" class="jsonedit html-widget" style="height:100%;width:100%;"></div>
<script type="application/json" data-for="mywidget">
{"x":{"data":[],"options":{"mode":"tree","modes":["code","form","text","tree","view"]}},"evals":[],"jsHooks":[]}
</script>
</body>
</html>
To see it working, I’ll embed the iframe below, or go directly to the example.html.
easier way?
The data script
with data-for
piece can be tricky to populate. Many times, it might be easier to manually render our htmlwidget
from JavaScript. We can get rid of the <script ... data-for>
and use some more traditional looking JavaScript.
find the widget binding
// use HTMLWidgets.widgets to give us
// a list of available htmlwiget bindings
// in this case we should just have one
var widgets = HTMLWidgets.widgets;
// assume there might be lots, so filter for the one we want
// in this case, we want jsonedit
var jed = widgets.filter(function(widget){
return widget.name === "jsonedit"
})[0];
get/make all the arguments for renderValue
// the binding should have an intialize, renderValue, and resize
// to render we use renderValue with arguments
// el the DOM element in which we want to render
// x the data and options
// instance return value from initialize
// get our htmlwidget DOM element
var el = document.getElementById('mywidget');
// make our x data and options
// this varies by widget
// and if widget built robustly then might be able
// to eliminate much of this
var x = {
"data":[],
"options":{"mode":"tree","modes":["code","form","text","tree","view"]}
};
// get our htmlwidget instance with initialize
var instance = jed.initialize(el);
render our widget
jed.renderValue(
el,
x,
instance
);
To see it working, I’ll embed the iframe below, or go directly to the example.html.
Reusable Components
Resability and portability is quite nice, so if you really like an htmlwidget
, but don’t use R, you can still use them. We’d love to have some more JavaScript/HTML/CSS, or heck Python, Go, Elm folks.