简体   繁体   中英

Passing a string to function but expecting an array

I have a select dropdown that on change I want it to run a function and pass along the select's value into that function. However, the function is expecting a variable holding an array, and what's being passed in is a string (the select's value).

You can see it working (or not working) in the code below. The selected value should represent its corresponding variable.

How can I accomplish this?

 var str = ["Paul", "John", "Melissa", "Mike"]; var int = [8, 4, 55, 7]; var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2]; var main = document.querySelector('#main'); var sel = document.querySelector('select'); function testFunc(arr){ arr.forEach((i) => { var p = document.createElement('p'); p.innerHTML = i; main.appendChild(p); }); } testFunc(mix); sel.addEventListener('change', testFunc(sel.value)); 
 <select> <option value="str">String</option> <option value="int">Integer</option> <option value="mix">Mixed</option> </select> <div id="main"></div> 

EDIT:

I should note that the data arrays are coming in dynamically and I really would like to avoid manipulating them as to not cause additional code and confusion in future edits.

There are two issues in your code:

  1. In the event handler function, by specifying parenthesis after the function you are calling the function when the page loads. Just call the function inside of a function body. This will make the function invoked only when the event fires.

  2. sel.value is a string but the function expects an array. To evaluate the array dynamically change testFunc(mix) to testFunc('mix') (wrap the parameter value with quotes) and use window object like:

     arr = window[arr] 

Replace:

sel.addEventListener('change', testFunc(sel.value));

With

sel.addEventListener('change', function (){testFunc([sel.value])});

 var str = ["Paul", "John", "Melissa", "Mike"]; var int = [8, 4, 55, 7]; var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2]; var main = document.querySelector('#main'); var sel = document.querySelector('select'); function testFunc(arr){ arr = window[arr] arr.forEach((i) => { var p = document.createElement('p'); p.innerHTML = i; main.appendChild(p); }); } testFunc('mix'); sel.addEventListener('change', function (){testFunc(sel.value)}); 
 <select> <option value="str">String</option> <option value="int">Integer</option> <option value="mix">Mixed</option> </select> <div id="main"></div> 

as i understand you want do to this:

let model = {
    str : ["Paul", "John", "Melissa", "Mike"];
    int : [8, 4, 55, 7];
    mix : ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2];
}


function testFunc(key){
    var arr = []
    if(model[key]){
        arr = model[key]
    }


    //TODO: clear parent node...
    arr.forEach((i) => {
        var p = document.createElement('p');
        p.innerHTML = i;
        main.appendChild(p);
    });
}
arr = eval(arr);

 var str = ["Paul", "John", "Melissa", "Mike"]; var int = [8, 4, 55, 7]; var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2]; var main = document.querySelector('#main'); var sel = document.querySelector('select'); function testFunc(arr){ arr = eval(arr); arr.forEach((i) => { var p = document.createElement('p'); p.innerHTML = i; main.appendChild(p); }); } testFunc(mix); sel.addEventListener('change', function(){testFunc(this.value)}); 
 <select> <option value="str">String</option> <option value="int">Integer</option> <option value="mix">Mixed</option> </select> <div id="main"></div> 

A few things to change:

  • Don't call the function that you pass to the addEventListener method. Instead pass a function reference. It can be an inline function expression. But don't call it.

  • Make your different arrays properties of one object variable, so you can easily reference them based on a value that is selected.

  • Clear the output whenever the selection is changed.

  • Trigger the initial change based on the item that is selected on page load.

Here is a working version:

 var arr = { str: ["Paul", "John", "Melissa", "Mike"], int: [8, 4, 55, 7], mix: ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2] }; var main = document.querySelector('#main'); var sel = document.querySelector('select'); function testFunc(arr){ main.innerHTML = ""; // clear the previous result arr.forEach((i) => { var p = document.createElement('p'); p.innerHTML = i; main.appendChild(p); }); } sel.addEventListener('change', () => testFunc(arr[sel.value])); testFunc(arr[sel.value]); // initial load 
 <select> <option value="str">String</option> <option value="int">Integer</option> <option value="mix">Mixed</option> </select> <div id="main"></div> 

If your arrays are defined in the global scope and there is nothing you can do about that, then just copy references to them in your new object:

// Defined beforehand: you cannot change this:
var str = ["Paul", "John", "Melissa", "Mike"],
var int = [8, 4, 55, 7],
var mix = ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2]

// In your part of the code, still create array as in above solution:
var arr = {str: str, int: int, mix: mix};
// If you have ES6 support you can shorten the above to:
var arr = {str, int, mix};

If I don't misunderstood your requirement then you've to do slight changes on your exiting JS variables and make it to Object . After that try like this way to append new paragraph elements on every change event of drop-down menu by removing the existing one with main.innerHTML=''

addEventListener : https://developer.mozilla.org/en-US/docs/Web/Events/change

Object Structure : https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics

 var data_types = { str: ["Paul", "John", "Melissa", "Mike"], int: [8, 4, 55, 7], mix: ["Paul", 9, "John", 5, "Melissa", 67, "Mike", 2] } var main = document.querySelector('#main'); var sel = document.querySelector('select'); function testFunc(event) { main.innerHTML = ''; // You can use “this” to refer to the selected element. if (!event.target.value) alert('Please Select One'); var arr = data_types[event.target.value]; arr.forEach((i) => { var p = document.createElement('p'); p.innerHTML = i; main.appendChild(p); }); } document.addEventListener('DOMContentLoaded', function() { document.querySelector('select[name="data-types"]').onchange = testFunc; }, false); 
 <select name="data-types"> <option value="str">String</option> <option value="int">Integer</option> <option value="mix">Mixed</option> </select> <div id="main"></div> 

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