Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to display htmlwidgets inside openCPU apps?

Tags:

r

opencpu

We want to display an htmlwidget inside an OpenCPU application.The html is generated by Leaflet without problems, however we have some troubles to display it within the OpenCPU app. We used the following function to generate the Leaflet Map:

leafmap1 <- function(ecoregion='10105',wdpa_id='1500'){
require(leaflet)
require(shiny)
require(htmlwidgets)
m <- leaflet() %>%
addTiles() %>%  # Add default OpenStreetMap map tiles
addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")
m 
}

The JavaScript is as follows:

function SochiCtrl($scope){
$scope.ecoregions = ['10105']
$scope.wdpa_ids = ["1500"]
$scope.ecoregion = $scope.ecoregions[0]
$scope.wdpa_id = $scope.wdpa_ids[0]    
$scope.makeChart = function(){
   var req = ocpu.rpc("leafmap1", 
    {"ecoregion": $scope.ecoregion, "wdpa_id": $scope.wdpa_id}, function(output){   
    $('#map').html(output)
   }).fail(function(text){
     alert("Error: " + req.responseText);
   });
}
$scope.$watchCollection('[ecoregion, wdpa_id]', function(newValues){
  console.log(newValues)
  $scope.makeChart({ecoregion: newValues[0], wdpa_id: newValues[1]})
})
}

Now the app shows the Leaflet frame but I have some problems getting the json from OpenCPU I got the following error No method asJSON S3 class: htmlwidget. I also tried with:

m <- toJSON(m, force= TRUE) 

but it doesn't seem to work.
enter image description here

The full code is available at: https://github.com/Arevaju/ocpuleaflet.

Thanks a lot for your help and congratulations for your great work!!

like image 278
arevaju Avatar asked Nov 26 '15 12:11

arevaju


1 Answers

Sorry as this is not a tested answer, but this is easier to explain a proposed approach here than in a comment.

What I propose is to have your function leafmap1 return plain text (HTML) instead of the leaflet object.

You can see that the leaflet object inherits the class htmlwidget. For this class, there exists a method for the generic function toHTML that would allows retrieving such HTML code.

Assumed a leaflet object:

 m = leaflet() %>% addTiles()

Let's have a look at it's class:

class(m)
[1] "leaflet"    "htmlwidget"

Get the underlying generated html:

> (out <- unclass(htmlwidgets:::toHTML(m)))
[[1]]
<div id="htmlwidget-7863" style="width:100%;height:400px;" class="leaflet html-widget"></div>
[[2]]
<script type="application/json" data-for="htmlwidget-7863">{"x":{"calls":[{"method":"addTiles","args":    ["http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",null,null,{"minZoom":0,"maxZoom":18,"maxNativeZoom":null,"tileSize":256,"subdomains":"abc","errorTileUrl":"","tms":false,"continuousWorld":false,"noWrap":false,"zoomOffset":0,"zoomReverse":false,"opacity":1,"zIndex":null,"unloadInvisibleTiles":null,"updateWhenIdle":null,"detectRetina":false,"reuseTiles":false,"attribution":"&copy; <a href=\"http://openstreetmap.org\">OpenStreetMap\u003c/a> contributors, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA\u003c/a>"}]}]},"evals":[],"jsHooks":[]}</script>
[[3]]
NULL
attr(,"html_dependencies")
attr(,"html_dependencies")[[1]]
[...]

Third slot contains dependancies (javascript+css) so I guess those are already loaded in your report.

You may return the concatenation of the first two components (function result):

return(paste(out[[1]], out[[2]], sep="\n"))
like image 176
Eric Lecoutre Avatar answered Oct 13 '22 18:10

Eric Lecoutre