简体   繁体   中英

Read dynamic HTML elements using R

First of all, I'd like to say that I am completely new to R. I've read the documentation and cannot find a way to fix the following scenario:

I have made a chart using google charts library (org-chart) and it works. The thing is that every node in the hierarchy has an input that I have to read and send to R when the user clicks a button or clicks enter. And here are my problems

  1. I don't know how to set reactivity to the dynamically created nodes
  2. I don't knwo how many nodes do I have to read because they are completely random. My idea is to set a class on every node and iterate later but I am not sure.

What I have done just to test is:

library(shiny)
# Define server logic for random distribution application
shinyServer(function(input, output) {
    output$num <- renderText ({
        paste('Number has changed to : ', input$qty_1)
      })
})

where $qty_1 is

<input name="qty_1" id="qty_1" value="10" type="number"></input>

But no luck.

PS I am using Shiny framework to develop the backend.

My HTML is

<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script>

    <style type="text/css">
        input[type="number"] {
            background-color : #fdfdd2;
        }
    </style>

    <script>
    "use strict";
        var tree = {
            name: "ROOT",
            desc: "Root",
            qty : 0,
            parent: '',
            children: {
                name: "FIRST",
                desc: "first",
                qty : 0,
                parent: 'ROOT',
                children: [{
                    name: "SECOND",
                    desc: "second",
                    qty : 0,
                    parent: 'FIRST',
                    children: {}
                }, {
                    name: "THIRD",
                    desc: "third",
                    qty : 0,
                    parent: 'FIRST',
                    children: [{
                        name: "FOURTH",
                        desc: "fourth",
                        qty: 0,
                        parent: 'THIRD',
                        children:{}
                    },{
                        name: "FIFTH",
                        desc: "fifth",
                        qty : 0,
                        parent: 'THIRD',
                        children: [{
                            name: "SIXTH",
                            desc: "sixth",
                            qty : 0,
                            parent: 'FIFTH',
                            children: {}
                        }]
                    }]
                }]
            }
        }
    </script>

    <script type="text/javascript">
        google.charts.load('current', {packages:["orgchart"]});
        google.charts.setOnLoadCallback(drawChart);

        function drawChart() {
            var data = new google.visualization.DataTable();
            data.addColumn('string', 'Name');
            data.addColumn('string', 'Desc');
            data.addColumn('string', 'Qty');

            // For each orgchart box, provide the name, description, and quantity to show.
            addRows(data, tree);

            // Create the chart.
            var chart = new google.visualization.OrgChart(document.getElementById('chart_div'));

            // Draw the chart, setting the allowHtml option to true for the tooltips.
            chart.draw(data, { allowHtml: true });
        }

        function addRows(data, Tree) {
            if (jQuery.isEmptyObject(Tree)) return;

            appendToChart(data, Tree.name, Tree.desc, Tree.qty, Tree.parent);

            var children = Tree.children;

            if (Object.prototype.toString.call( children ) == '[object Array]'){ // more than 1 child
                for (var i = children.length - 1; i >= 0; i--) {
                    addRows(data, children[i]);
                }
            }
            else
            {
                addRows(data, children);
            }
        }

        function appendToChart(data, name, desc, qty, parent) {
            data.addRows([
                //[name, parent, desc]
                [{ v:name, f: name + '<div style="color:red; font-style:italic">' + desc + 
                    '</div><input id="qty" size="4" value="' + qty + '" type="number"></input>' }, parent, desc]
            ]);
        }

    </script>
    </head>
    <body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-12">
                <div id="chart_div"></div>
            </div>
        </div>
    </div>

    <script>
    $(function(){
        $(document).on('keypress', function(e) {
            if (e.which == 13)
                if ($.isNumeric($("#qty").val()))
                    alert($("#qty").val());
                else
                    alert("not a number");
        });
    });
  </script>
  </body>

</html>

There are a few things you could try:

  1. add the shiny.js to your head (I generally also put the shiny jquery version):

    <script src="shared/jquery.js" type="text/javascript"></script>

    <script src="shared/shiny.js" type="text/javascript"></script>

  2. Wrap your numeric inputs in a <div class="shiny-input-container"> so that shiny recognizes them as inputs and binds them, they will need a name attribute that you can then use to refer to them in the server.R . For ex, you could do in your addRows function:

[{ v:name, f: name + '<div style="color:red; font-style:italic" >' + desc + '</div><div class="shiny-input-container"><input name="qty-'+name+'" size="4" value="' + qty + '" type="number"></input></div>' }, parent, desc]

  1. Since you are adding inputs by js, you should call Shiny.unbindAll() at the beginning at the drawChart function and Shiny.bindAll() at the end to get all the Shiny input bindings working.

In the server.R you can then refer to the inputs, they will all have a name like qty-name , you can filter them out of the input list by doing grepl("qty",names(input)) . For example to print them all you could do, in server.R :

observe({
   lapply(names(input)[grepl("qty",names(input))],function(x){
        print(paste(x,input[[x]]))
   })
}) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM