-1

The following function creates input fields where the user specifies type, name and a number of classes that he would like to add for the input element. Sometimes, the user is going to want to set other attributes for the element, such as step, or any other DOM attribute. That's why I want to use optional arguments:

function createInputField(type, name, classList, optional){
    var input = document.createElement('input');
    input.type = type;
    input.name = name;

    for(var i=0; i<classList.length; i++){
        input.classList.add(classList[i]);
    }

    for(key,value) in optional{ // Ugly fake code. How do I implement this in Javascript?
        input.getAttribute(key) = value;
    }    

    return input;
}

input = createInputField("number", "numberfield", ["red", "top"], {"step":"0.05"})

How do I implement this functionality in Javascript?

Sahand
  • 7,980
  • 23
  • 69
  • 137
  • 1
    Which version of JS are you supporting/targeting? Are you talking about [`...rest` parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters)? An `options` object? JS doesn't require the function to be called with the number of parameters it defines, you can access all of them via [`arguments`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments). – jonrsharpe Jan 02 '18 at 14:13
  • See [Default parameters - JavaScript | MDN](https://developer.mozilla.org/tr/docs/Web/JavaScript/Reference/Functions/Default_parameters). – akinuri Jan 02 '18 at 14:14
  • `if (optional) Object.keys(optional).forEach(k => input.setAttribute(k, optional[k]));` – baao Jan 02 '18 at 14:16

2 Answers2

1

Just use normal object enumeration:

for (var key in optional) {
    var value = optional[key];
    input.setAttribute(key, value);
}

This doesn't have to do anything with the argument optional itself being optional so that you can omit it in the call. Just provide an empty object ({}) when you don't want to pass any extra dom attributes.

If you want to be able to completely omit it (like calling createInputField("number", "x", ["red"]), you can either wrap the loop inside an if (typeof optional == "object") condition, or you use default parameters:

function createInputField(type, name, classList = [], optional = {}) {
    …
}
Sahand
  • 7,980
  • 23
  • 69
  • 137
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Bergi, it appears that your code generates an error, since `input.getAttribute(key) = value;` seems to generate `ReferenceError: Invalid left-hand side in assignment`. I have edited it to correct the error. – Sahand Jan 02 '18 at 17:47
  • @Sandi Yeah, thanks, I just blindly copied the assignment line from the OP. – Bergi Jan 02 '18 at 18:48
1

This is what you need:

if(optional && typeof optional === 'object') {
   for(var key in optional) {
      if(input.hasOwnProperty(key)) {
         input.getAttribute(key) = optional[key];
      }
   } 
}
Nikola Andreev
  • 624
  • 4
  • 18
  • It was like pseudo code. I update it now, thanks lofihelsinki! – Nikola Andreev Jan 02 '18 at 14:38
  • One more thing, needs to be `if(optional.hasOwnProperty(key))` – lofihelsinki Jan 02 '18 at 14:50
  • Why? We are in for each loop, that guarantees the optional[key] existence. – Nikola Andreev Jan 02 '18 at 15:11
  • You need to check if the property `key` belongs to Object `optional` and is not i.e. a property inherited from a prototype class. Those might be included in the loop too. It is explained here: https://stackoverflow.com/questions/12735778/for-in-and-hasownproperty – lofihelsinki Jan 02 '18 at 15:16
  • Thanks, i got it. – Nikola Andreev Jan 02 '18 at 15:26
  • @lofihelsinki [N, it doesn't need to](https://stackoverflow.com/a/45014721/1048572). – Bergi Jan 02 '18 at 18:49
  • That's right in this example, since we know `optional` is just a plain object: `{"step":"0.05"}`. However, there's nothing to prohibit passing a non-plain object to the function `createInputField`. So we can't be sure `optional` doesn't i.e. extend some other type of object. Therefore i would add `hasOwnProperty` – lofihelsinki Jan 02 '18 at 21:43