PDA

View Full Version : dynamically set element name in form validation script



rizlaa
08-22-2006, 11:32 AM
i have a javascript function which sets the value of a column in a form. the column to be updated is passed as a parameter to the function.

i am currently doing the following:
function updateCol(colNum)
if (colNum == "f02")
document.forms["form1"].f02[0].value = 'U';
else if (colNum == "f04")
document.forms["form1"].f04[0].value = 'U';
}

is there any way of switching the code fragment
document.forms["form1"].f02[0].value
to using the colNum parameter???

thereby removing the need for the if else clause?

DimX
08-22-2006, 11:39 AM
What is this column exactly? What element?
The easiest way is perhaps this:


eval("document.forms['form1']." + colNum + "[0].value = 'U';");

(some quote problems may occur, escape " with \" )

mwinter
08-22-2006, 12:47 PM
eval("document.forms['form1']." + colNum + "[0].value = 'U';");

Yikes! Never use the eval function to do that.



document.forms.form1.elements[colNum + '[0]'].value = 'U';

Bracket notation can always be used to generate and access property names at run-time. The contents of the brackets can be any legal expression. Once evaluated, it will be converted to a string and that string becomes the property name used.

See How do I access a property of an object using a string? (http://www.jibbering.com/faq/#FAQ4_39) in the comp.lang.javascript FAQ, particularly the linked document (which provides a much more complete explanation of bracket notation).

Mike

rizlaa
08-22-2006, 03:46 PM
I have tried your double brackets method

document.forms.form1.elements['f0' + colNum + '[rowNum - 1]'].value = 'U';
and also tried
document.forms.form1.elements['f0' + colNum + '[' + (rowNum - 1) + ']'].value = 'U';

(rowNum is the calculated row i put [0] in my original post to keep it simple)

but this gives me a
document.forms.form1.elements[...]' is null or not an object error

any ideas as to why this would be??

mwinter
08-22-2006, 04:06 PM
Not without seeing your code in action (post a link if you still have trouble). However, I would start by checking what the generated property name really is. In your original post, it seemed to be a string. Was that also a simplification?

For example, you might try including:



alert(colNum + ' ' + rowNum + ' ' + ('f0' + colNum + '[' + (rowNum - 1) + ']'));

before trying to access the form element. A sequence like "2 5 f02[4]" is what you should expect if colNum is 2 and rowNum is 4, but is the result very different?

Mike

rizlaa
08-23-2006, 10:39 AM
I have typed in your alert as specified and the alert box that popsup shows the output as you have stated. "2 5 f02[4]".

have tried the following with the same error being displayed:
document.forms.form1['f0' + colNum + '[' + (rowNum - 1) + ']'].value = 'U';

The above should equate the values in the [] as in the alert test?
any additional help much appreciated (i'm afraid my app is not externally visible.)

mwinter
08-23-2006, 02:04 PM
I have typed in your alert as specified and the alert box that popsup shows the output as you have stated. "2 5 f02[4]".

Then you should know the values that cause it to fail: the last message to appear before the error should display values that refer to a form control that doesn't exist.

For example, can colNum ever reach double digits? With the currently suggested code, that would produce a leading sequence like "f013", which is unlikely to exist. Similarly, could rowNum ever be zero? That would produce a trailing sequence like "[-1]".



have tried the following with the same error being displayed:
document.forms.form1['f0' + colNum + '[' + (rowNum - 1) + ']'].value = 'U';

The above should equate the values in the [] as in the alert test?

Yes.

Try the following snippet:



function test() {
var colNum = 1,
rowNum = 1;

alert(document.forms.myForm.elements['f0' + colNum + '[' + (rowNum - 1) + ']'].value);
}



<form id="myForm" name="myForm" action="">
<div>
<input name="f01[0]" value="Some value">
<input type="button" value="Test" onclick="test();">
</div>
</form>

If you include that in a simple HTML document and click the button, a dialogue box will display "Some value".



i'm afraid my app is not externally visible.

Fine, but unless you post code, no-one here can help you debug the problem.

At the minimum, you need to include the form element and its contents, the function where you attempt to access the form controls, as well as the functions that call it and those that it calls. Ideally, though, you would create a separate, and simpler test case - you might even find the error yourself doing that.

Mike

Twey
08-23-2006, 02:53 PM
eval("document.forms['form1']." + colNum + "[0].value = 'U';");Wouldn't that be better translated as:
document.forms.form1.elements[colNum][0].value = 'U';?

mwinter
08-23-2006, 03:09 PM
document.forms.form1.elements[colNum][0].value = 'U';

It would seem that I was getting caught up in the thought of PHP-like control names, like "f02[0]", rather than several controls with the same "f02" name.

Cheers, Twey (and apologies to the OP).

Mike

Twey
08-23-2006, 03:16 PM
(sets "number-of-times-Mike's-been-wrong" counter to 3) :)

DimX
08-23-2006, 03:21 PM
Wouldn't that be better translated as:
document.forms.form1.elements[colNum][0].value = 'U';?
Yes but, how do you know that column is a form element (input, select, textarea)?
I suggested the eval function only because it would work for sure, even if column isn't a form element.

rizlaa
08-23-2006, 03:44 PM
TWEY,

thanks for that the following worked:
document.forms.form1.elements["f0" + colNum][(rowNum - 1)].value = 'U';

mwinter
08-23-2006, 03:58 PM
(sets "number-of-times-Mike's-been-wrong" counter to 3) :)

That said, what you posted isn't quite what the OP needs:



document.forms.form1.elements['f0' + colNum][rowNum - 1].value

There's still the concern about the range of values for colNum, though. If it can reach double figures and the control names become "f14", rather than "f014", then other action needs to be taken:



Number.prototype.pad = function(length, radix, character) {
return (+this).toString(+radix || 10).pad(length, character || '0');
};

String.prototype.pad = function(length, character) {
var result = String(this);

while (result.length < length) result = character + result;
return result;
};

These two methods can be used to pad the number to the required length (if the number version is used, the string version must also be included). For example:



document.forms.form1.elements['f' + colNum.pad(2)][rowNum - 1].value

Be careful to ensure that colNum is a number, not a string containing a number.




Yes but, how do you know that column

Column? I assume you're referring to colNum.



is a form element (input, select, textarea)?

Refer to them as form controls, to avoid confusion. A form element is a form element (<form action="...">...</form>).



I suggested the eval function only because it would work for sure, even if column isn't a form element.

I'm not sure what you're trying to imply, here. If you think that eval will somehow magically cope with a control that doesn't exist, you're wrong. If instead you mean that the expression isn't meant to evaluate to a form control at all, it's quite clear that the OP has no such intention (only form controls have a value property). Even then, the eval function still wouldn't be the right way to do it: you'd just drop the elements collection.



function getProperty(name) {
return document.forms.form1[name];
}

Calling getProperty with a string such as 'action', for example, would return the value of the action property (the action attribute, in HTML). Calling it with 'elements' would return a reference to the elements collection.

The eval function is not meant to be used to construct property names in this manner. Ever! If you find yourself wanting to use the eval function, it's likely that you just don't know a better way of doing something (and if that's the case, ask!)

Mike