2

I want to have a little validation when user enter value into apex:inputText it compares it with apex:column, if difference is more than 10%, it would alert the user.

Probably it would be triggered using onblur and would change style of apex:column, but I am not sure how can I compare them two?

Many thanks,

~dzh

EDIT: Code excerpt

<script type="text/javascript">
function a(){
var price=document.getElementById('{!$Component.quotedConsumption.Rec.AQQ}').value;
alert(price);}
</script>
     <apex:column headerValue="Current annual Consumption" value="{!Rec.AQ}" id="currentConsumption"/> 
         <apex:column headerValue="Annual consumption quoted for" >
          <apex:inputtext value="{!Rec.AQQ}" required="true" onblur="a()" id="quotedConsumption"/>
         </apex:column>

The error I am getting in console:

Uncaught TypeError: Cannot read property 'value' of null 
3
  • Hi @dzh, can you provide us with some code that you have tried already and details of where you are stuck.
    – BarCotter
    Commented Feb 24, 2014 at 14:56
  • @BarCotter Updated the body. Getting stuck to the fact that value is not being populated. Also tried getElementById('{!$Component.quotedConsumption}')
    – dzh
    Commented Feb 24, 2014 at 16:30
  • So strange, this is what appears in JS source var price=document.getElementById("").value;
    – dzh
    Commented Feb 24, 2014 at 17:24

4 Answers 4

2

I think you can do this with jQuery. Use the .closest method to find the row you are in and then get the value from the other field. Something like this (warning, I didn't test this code in a browser).

<apex:includeScript value="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" />
<script type="text/javascript">
  j$ = jQuery.noConflict();
  function checkValues(e) {
    thisRow = j$(e).closest('tr'); //edited
    var currentConsumption = thisRow.find('[id$="currentConsumption"]').text();
  }
</script>

<apex:column headerValue="Current annual Consumption">
  <apex:outputText value="{!Rec.AQ}" id="currentConsumption" />
</apex:column>
<apex:column headerValue="Annual consumption quoted for" >
  <apex:inputtext value="{!Rec.AQQ}" required="true" onblur="checkValues(this)" id="quotedConsumption"/>
</apex:column>
1
  • Many thanks for this tip, it helped me to build a working version!
    – dzh
    Commented Feb 25, 2014 at 13:17
1

I found a work around for your issue using the below code

<script type="text/javascript">
function a(obj){
var price = obj.value;
alert(price);}
</script>
         <apex:column headerValue="Annual consumption quoted for" >
          <apex:inputtext value="{!Rec.AQQ}" required="true" onblur="a(this)" id="quotedConsumption"/>
         </apex:column>

hope it works out.

1
  • heh, it does work, however, how do I find out the value of adjacent apex:column ?
    – dzh
    Commented Feb 24, 2014 at 18:34
1

Big thanks to codebandit, Mark Pond and mostly Daniel Hoechst. All of your answers helped to build this!

Here's JavaScript that worked for me:

<apex:includeScript value="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" />
<script type="text/javascript">
 j$ = jQuery.noConflict();

 function compareValues(element) {

                thisRow = j$(element).closest('tr');
                var currentConsumption = thisRow.find('[id$="currentConsumption"]').text();

                // get the references to these two DOM elements and create vars for calculation
                var thisElement = element,               
               // compareToElement = document.getElementById(compareTo),
                quotedValue = parseFloat(thisElement.value),
                currentValue = parseFloat(currentConsumption),
                largerValue = null,
                smallerValue = null,
                percentDifference = null;

            // make sure we have got values to work with
            if (!isNaN(quotedValue) && !isNaN(currentValue)) {

                // find the larger and smaller values
                largerValue = Math.max(currentValue, quotedValue);
                smallerValue = Math.min(currentValue, quotedValue);

                // calculate the percentage difference between these numbers, force the parse as base-10
                percentDifference = parseInt((largerValue - smallerValue) / ((largerValue + smallerValue) / 2) * 100, 10);

                // alert the user of the difference value
                if (percentDifference > 10) {
                    alert('Warning: The quoted value differs more than 10% of current consumption!');
                }

            } else {
                // one of the elements is null
                alert('One of the elements to compare is null or isn\'t a number.');
            }
        }
</script>

And VF:

<apex:inputtext value="{!Rec.AQQ}" required="true" onblur="compareValues(this)" id="quotedConsumption"/>
1

You can use the {!$Component.whateverName} within the column markup and when the table is rendered, this reference is relative to the row where the markup occurs.

You can pass this id value as a string as well as the reference to the current input element to the function and then retrieve the DOM element from there and perform the math on the values to find the percentage difference between the two values.

Relevant documentation: Best Practices for Accessing Component IDs

Your page markup will look something like this:

<apex:page id="thePage">
    <script type="text/javascript">
        function compareValues(element, compareTo) {

            // get the references to these two DOM elements and create vars for calculation
            var thisElement = element,
                compareToElement = document.getElementById(compareTo),
                quotedValue = parseFloat(thisElement.text),
                currentValue = parseFloat(compareToElement.value),
                largerValue = null,
                smallerValue = null,
                percentDifference = null;

            // make sure we've got values to work with
            if (thisElement && compareToElement && !isNaN(quotedValue) && !isNaN(currentValue)) {

                // find the larger and smaller values
                largerValue = Math.max(currentValue, quotedValue);
                smallerValue = Math.min(currentValue, quotedValue);

                // calculate the percentage difference between these numbers, force the parse as base-10
                percentDifference = parseInt((largerValue - smallerValue) / ((largerValue + smallerValue) / 2) * 100, 10);

                // alert the user of the difference value
                if (percentDifference > 10) {
                    alert('More than 10% difference: ' + percentDifference);
                } else {
                    alert('Less than 10% difference: ' + percentDifference);
                }

            } else {
                // one of the elements is null
                alert('One of the elements to compare is null or isn\'t a number.');
            }
        }
    </script>

    <apex:pageBlock>
        <apex:pageBlockTable id="thePageBlockTable">
            <apex:column headerValue="Current annual Consumption">
                <apex:outputText value="{!Rec.AQ}" id="currentConsumption" />
            </apex:column>
            <apex:column headerValue="Annual consumption quoted for" >

                <!-- the Component.currentConsumption reference is relative to _this_ row in the table -->
                <apex:inputtext value="{!Rec.AQQ}" required="true" 
                    onblur="compareValues(this, '{!$Component.currentConsumption}')" id="quotedConsumption"/>

            </apex:column>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>
4
  • Hi, many thanks for this reply. I can see you've put a lot of effort into constructing the logic of this. Unfortunately it didn't work fully, as onblur call is rendered literally: <input id="j_id0:j_id3:j_id4:j_id5:0:quotedConsumption" type="text" name="j_id0:j_id3:j_id4:j_id5:0:quotedConsumption" onblur="compareValues(this, '{$!Component.currentConsumption}')"> I did however use your logic to build a complete solution that worked for me!
    – dzh
    Commented Feb 25, 2014 at 13:16
  • The reason that you received the literal string in the onblur is because there was a typo in my example. {!Component vs {!$Component
    – Mark Pond
    Commented Feb 25, 2014 at 20:37
  • Yes, I have noticed and fixed that before posting here. Note that result includes $.
    – dzh
    Commented Feb 26, 2014 at 10:59
  • 1
    Yours had a typo as well, which is why it was rendered literally. '{$!Component.currentConsumption} the exclamation point and dollar sign are reversed. Glad you got it sorted out.
    – Mark Pond
    Commented Feb 26, 2014 at 18:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .