Search code examples
javascriptpythonhtml-selectwebassemblypyodide

Pass dropdown menu selection to Pyodide


I am trying to pass the value selected by the user from the dropdown menu to the Python code in Pyodide. In the simplified example below, I am trying to:

  • Read the user-selected input file
  • Convert file contents to lowercase
  • Append the user-selected value of "strand" (for example, the string "negative")
  • Write the results to file 'out.txt' that can be downloaded by the user

For the input file with contents Hello World!, I expect that the output file to have:

hello world!
negative

Instead, I got:

hello world!
[object HTMLSelectElement]

Full page code:

<!doctype html>
<html>
  <head>
      <script src="https://cdn.jsdelivr.net/pyodide/v0.22.1/full/pyodide.js"></script>
  </head>
  <body>
    Input file:
    <button>Select file</button>
    <br>
    <br>
    Strand:
    <select id="strand" class="form-control sprites-arrow-down" name="strand" value>
      <option id="val" value="positive" selected>positive</option>
      <option id="val" value="negative">negative</option>
    </select>
    <br>
    <br>
 
    <script type="text/javascript">
      async function main() {
          // Get the file contents into JS
          const [fileHandle] = await showOpenFilePicker();
          const fileData = await fileHandle.getFile();
          const contents = await fileData.text();
          
          var d = document;
          d.g = d.getElementById;
          var strand = d.g("strand");
          
          // Create the Python convert toy function
          let pyodide = await loadPyodide();
          let convert = pyodide.runPython(`
from pyodide.ffi import to_js
def convert(contents, strand):
    return to_js(contents.lower() + str(strand))
convert
      `);

          let result = convert(contents, strand);
          console.log(result);
          
          const blob = new Blob([result], {type : 'application/text'});
          
          let url = window.URL.createObjectURL(blob);
          
          var downloadLink = document.createElement("a");
          downloadLink.href = url;
          downloadLink.text = "Download output";
          downloadLink.download = "out.txt";
          document.body.appendChild(downloadLink);
          
      }
      const button = document.querySelector('button');
      button.addEventListener('click', main);
    </script>
  </body>
</html>

The code is based on this post: Select and read a file from user's filesystem


Solution

  • I used the method shown in the answer here: Get selected value in dropdown list using JavaScript to access the selected value and pass it to Pyodide.

    Here is how to get the selected value, such as negative:

    var e = document.getElementById("strand");
    var strand = e.value;
    

    And the complete page code is:

    <!doctype html>
    <html>
      <head>
          <script src="https://cdn.jsdelivr.net/pyodide/v0.22.1/full/pyodide.js"></script>
      </head>
      <body>
        Input file:
        <button>Select file</button>
        <br>
        <br>
        Strand:
        <select id="strand" class="form-control sprites-arrow-down" name="strand" value>
          <option value="positive" selected>positive</option>
          <option value="negative">negative</option>
        </select>
        <br>
        <br>
     
        <script type="text/javascript">
          async function main() {
              // Get the file contents into JS
              const [fileHandle] = await showOpenFilePicker();
              const fileData = await fileHandle.getFile();
              const contents = await fileData.text();
    
              var e = document.getElementById("strand");
              var strand = e.value;
                        
              // Create the Python convert toy function
              let pyodide = await loadPyodide();
              let convert = pyodide.runPython(`
    from pyodide.ffi import to_js
    def convert(contents, strand):
        return to_js(contents.lower() + strand)
    convert
          `);
    
              let result = convert(contents, strand);
              console.log(result);
              
              const blob = new Blob([result], {type : 'application/text'});
              
              let url = window.URL.createObjectURL(blob);
              
              var downloadLink = document.createElement("a");
              downloadLink.href = url;
              downloadLink.text = "Download output";
              downloadLink.download = "out.txt";
              document.body.appendChild(downloadLink);
              
          }
          const button = document.querySelector('button');
          button.addEventListener('click', main);
        </script>
      </body>
    </html>