diff --git a/_includes/tutorial/building-inputs.md b/_includes/tutorial/building-inputs.md index a67445a3c..c748bf9e3 100644 --- a/_includes/tutorial/building-inputs.md +++ b/_includes/tutorial/building-inputs.md @@ -196,7 +196,7 @@ Shiny.inputBindings.register(incrementBinding); Both the behavioral JavaScript code and the Shiny binding code should generally be run when the page loads. (It's important that they run before Shiny initialization, which occurs after all the document ready event handlers are executed.) -The easiest way to do this is to put both chunks of JavaScript into a file; in this case, we'll use the path `./www/js/increment.js`, which we can then access as `http://localhost:8100/js/increment.js`. +The cleanest way to do this is to put both chunks of JavaScript into a file. In this case, we'll use the path `./www/js/increment.js`, which we can then access as `http://localhost:8100/js/increment.js`. If you're using an `index.html` style user interface, you'll just need to add this line to your `` (make sure it comes after the script tag that loads `shiny.js`): @@ -214,4 +214,4 @@ On the other hand, if you're using `ui.R`, then you can define this function bef ) } -Then in your `shinyUI` page definition you can call `incrementButton` wherever you want an increment button rendered. Notice the line that begins with `singleton` will ensure that the `increment.js` file will be included just one time, in the ``, no matter how many buttons you insert into the page or where you place them. \ No newline at end of file +Then in your `shinyUI` page definition you can call `incrementButton` wherever you want an increment button rendered. Notice the line that begins with `singleton` will ensure that the `increment.js` file will be included just one time, in the ``, no matter how many buttons you insert into the page or where you place them. diff --git a/_includes/tutorial/building-outputs.md b/_includes/tutorial/building-outputs.md new file mode 100644 index 000000000..7840a4833 --- /dev/null +++ b/_includes/tutorial/building-outputs.md @@ -0,0 +1,84 @@ +## Building Outputs + +Similar to custom inputs, if you have some knowledge of HTML/CSS/JavaScript you can also build reusable, custom *output* components. + +Output values are received from the server and are directed to an *output binding*, which then + + + + + + + + + + +### Write an Output Binding + +Each custom output component needs an *output binding*, an object you create that tells Shiny how to identify instances of your component and how to interact with them. (Note that each *instance* of the output component doesn't need its own output binding object; rather, all instances of a particular type of output component share a single output binding object.) + +An output binding object needs to have the following methods: + +
+
+ find(scope) +
+
+

+ Given an HTML document or element (scope), find any descendant elements that are an instance of your component and return them as an array (or array-like object). The other output binding methods all take an el argument; that value will always be an element that was returned from find. +

+ +

+ A very common implementation is to use jQuery's find method to identify elements with a specific class, for example: +

+
exampleOutputBinding.find = function(scope) {
+  return $(scope).find(".exampleComponentClass");
+};
+
+
+ getId(el) +
+
+ Return the Shiny output ID for the element el, or null if the element doesn't have an ID and should therefore be ignored. The default implementation in Shiny.InputBinding reads the data-output-id attribute and falls back to the element's id if not present. +
+
+ renderValue(el, data) +
+
+ Called when a new value that matches this element's ID is received from the server. The function should render the data on the element. The type/shape of the `data` argument depends on the server logic that generated it; whatever value is returned from the R code is converted to JSON using the RJSONIO package. +
+
+ renderError(el, err) +
+
+ Called when the server attempts to update the output value for this element, and an error occurs. The function should render the error on the element. err is an object with a message String property. +
+
+ clearError(el) +
+
+ If the element el is currently displaying an error, clear it. +
+
+ showProgress(el, show) +
+
+
+
+ +### Register Output Binding + +Once you've created an output binding object, you need to tell Shiny to use it: +
Shiny.outputBindings.register(exampleOutputBinding, "yourname.exampleOutputBinding");
+ +The second argument is a name the user can use to change the priority of the binding. On the off chance that the user has multiple bindings that all want to claim the same HTML element as their own, this call can be used to control the priority of the bindings: + +
Shiny.outputBindings.setPriority("yourname.exampleOutputBinding", 10);
+ +Higher numbers indicate a higher priority; the default priority is 0. All of Shiny's built-in input component bindings default to a priority of 0. + +If two bindings have the same priority value, then the more recently registered binding has the higher priority. + +### Example + + diff --git a/tutorial/index.html b/tutorial/index.html index 69454a56f..2a54d94a0 100644 --- a/tutorial/index.html +++ b/tutorial/index.html @@ -265,6 +265,14 @@ hljs.initHighlightingOnLoad(); + +
+ +{% capture building_outputs %}{% include tutorial/building-outputs.md %}{% endcapture %} +{{ building_outputs | markdownify }} + +
+