spin button wrong values

7 posts, 0 answers
  1. Ibrahim Imam
    Ibrahim Imam avatar
    69 posts
    Member since:
    Jul 2007

    Posted 30 Nov 2010 Link to this post

    hello


    i am using the radnumeric textbox with spin buttons and dynamic Increment Steps depending on previous user input.
    during testing i discovered the following wrong behaviour:

    Value of the Textbox set on server: 50
    Increment Step: 0.127
    after clicking 3 times (numbers vary) the value in the textbox is wrong because it decrements by 0.128.
    so it shows the value 49.618 (=50-(2*0.127)-0.128) instead of 49.619 (=50-(3*0.127))
    this seems to occur for prime numbers after 0. for example 0.127 or  0.05
    when the user then sends the values my custom validations on the server reject the value.

    i checked the javascript code for the textbox and as a temporary solution i set the "KeepNotRoundedValue" to true.
    the value in the textbox is then wrong but sending and saving to server works. the value is then changed to the correct value.
    this auto correct after sending will confuse some users so i need a clean solution.

    another question regarding the spin button:
    is it possible to customize the behaviour? in my use case i only allow specific values for example:
    the value in the textbox is 98 and the step value is set to 5. valid values are 93,88, and so on.
    if the user now enters 95 and then uses the decrement spin button it changes the value to 90 which is not allowed.
    i would like to set the next valid number when using the spin button or better have some auto-rounding to the next valid number when the value is changed
  2. Radoslav
    Admin
    Radoslav avatar
    1566 posts

    Posted 06 Dec 2010 Link to this post

    Hi Ibrahim,

    To achieve the desired functionality without using the KeepNotRoundedValue property you could try setting the NumberFormat.DecimalDigits property to 3:
    <telerik:RadNumericTextBox runat="server" ID="RadNumericTextBox1" ShowSpinButtons="true">
                <IncrementSettings Step="0.127" />
                <NumberFormat DecimalDigits="3" />
    </telerik:RadNumericTextBox>

    On the following link I attached a small video which demonstrates how the RadNumericTextBox works on my end when the DecimalDigits is set to 3.

    Regarding your second question:
    You could handle the client side OnButtonClick  event and check if the entered value is valid, if the user enters invalid value you could change it manually to one of the valid values for the RadNumericTextBox:
    <telerik:RadNumericTextBox runat="server" ID="RadNumericTextBox1" ShowSpinButtons="true">
        <IncrementSettings Step="0.127" />
        <NumberFormat DecimalDigits="3" />
        <ClientEvents OnButtonClick="ButtonClicked"/>
    </telerik:RadNumericTextBox>

    <telerik:RadCodeBlock runat="server">
       <script type="text/javascript">
     
            function ButtonClicked(sender, eventArgs)
            {
                var numericTextBox = $find("<%=RadNumericTextBox1.ClientID  %>");
                var enteredValue = numericTextBox.get_value();
                if(eventArgs._buttonType == 2)
                {
                    // Spin Button up pressed
                    if(!Validate(enteredValue))
                    {
                        // Change enteredValue to valid value for the RadNumericTextBox1
                        // For example if the enteredValue is 95, change it to next valid value - 98
                    }
                }
                else
                {
                     // Spin Button down pressed
                     if(!Validate(enteredValue))
                     {
                        // Change enteredValue to valid value for the RadNumericTextBox1
                       // For example if the enteredValue is 95, change it to next valid value - 93
                     }
                }
            }
            function Validate(enteredValue)
            {
                // Check if enteredValue is valid value
            }
               
        </script>
    </telerik:RadCodeBlock>

    Please give it try and let me know if you experience any problems.

    Greetings,
    Radoslav
    the Telerik team
    Browse the vast support resources we have to jumpstart your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
  3. Ibrahim Imam
    Ibrahim Imam avatar
    69 posts
    Member since:
    Jul 2007

    Posted 06 Dec 2010 Link to this post

    i create the columns at runtime and already set the decimal amount in the

    void ux_ApplyGrid_ItemCreated(object sender, Telerik.Web.UI.GridItemEventArgs e)
    event using:
     ((RadNumericTextBox)item["NewOffer"].Controls[0]).NumberFormat.DecimalDigits = BidData.BidTargetCategories[dataItem["PositionId"].ToString()].DecimalsAmount;

    i tried to reduce the value a few times with the spin button and then clicked save.
    i get the error message and the value inside the textbox was something like
    59.000000000001

    i will check the custom solution also
  4. Ibrahim Imam
    Ibrahim Imam avatar
    69 posts
    Member since:
    Jul 2007

    Posted 06 Dec 2010 Link to this post

    i now tried to implement my auto correction function based on your code snippet.
    during debugging i found that the get_value() method returns the "old" value before the action of the spin button.
    besides that after setting a value the spin action is performed so it subracts the value after setting it (in case i click spin button down)

    another thing i noted during debugging:
    var difference = initialValue - enteredValue;
    also produces wrong values sometimes (for example 95.0000000002). i researched and it seems to be a javascript problem that incorrect numbers appear. i worked around this issue by using the following "rounding" calculation (as rounding is only possible to no decimals in JS):
    var roundingprecision = 1000000; // rounding is exact up to 6 digits
    var difference = Math.round((initialValue - enteredValue) * roundingprecision) / roundingprecision; 

    here is my current code. the find logic wouldn't have worked in my case as i create the buttons in code behind.
    it works with the sender for me:

    function SpinButtonClicked(sender, eventArgs)
    {
        var numericTextBox = sender;
        var enteredValue = numericTextBox.get_value(); // should be the new value after spin button action, currently wrong
        var initialValue = numericTextBox._originalValue; // the value last received from the server
        var stepSize = numericTextBox._incrementSettings.Step;
     
        var difference = initialValue - enteredValue;
     
        if (difference < 0) //make difference always a positive value
        {
            difference = difference * (-1);
        }
     
        var errorDifference = difference % stepSize;
     
        if (errorDifference != 0) // entered value not valid
        {
            if (eventArgs._buttonType == 2)// Spin Button up pressed
            {
                numericTextBox.set_value(enteredValue + errorDifference); // add the errorDifference to actual entered value -> auto round up to next valid value
            }
            else  // Spin Button down pressed
            {
                numericTextBox.set_value(enteredValue - errorDifference); // subtract the errorDifference to actual entered value -> auto round down to next valid value
            }
        }
    }

    because of above mentioned problems i think the better solution is to handle the OnValueChanged event.
    this will work for manual entries also which is ok in my scenario
    here is my code which seems to work correctly so far:
    the downside is the risk of an endless recursion if the calculation is wrong as the set_value method triggers the event again.
    is there a way to not handle the event if i used the set_value() method?

    function ValueChanged(sender, eventArgs)
    {
        var numericTextBox = sender;
        var enteredValue = numericTextBox.get_value();
        var initialValue = numericTextBox._originalValue;
        var stepSize = numericTextBox._incrementSettings.Step;
     
     
        var difference = customRound (initialValue - enteredValue);
     
        var errorDifference = difference % stepSize;
     
        if (errorDifference != 0) // entered value not valid
        {
            var correctedValue =customRound( enteredValue - (stepSize - errorDifference));
            numericTextBox.set_value(correctedValue);
        }
    }
     
    function customRound(value)
    {
        var roundingprecision = 1000000;
     
        return Math.round(value * roundingprecision) / roundingprecision
    }

  5. Radoslav
    Admin
    Radoslav avatar
    1566 posts

    Posted 07 Dec 2010 Link to this post

    Hello Ibrahim,

    I am glad that you achieved the desired functionality. Additionally to avoid the endless recursion you could try setting a flag which keeps value when the set_value function is called explicitly:
    var setValueFunctionCalled = false;
    function ValueChanged(sender, eventArgs)
    {
       var numericTextBox = sender;
       var enteredValue = numericTextBox.get_value();
       var initialValue = numericTextBox._originalValue;
       var stepSize = numericTextBox._incrementSettings.Step;
     
       var difference = customRound(initialValue - enteredValue);
     
       var errorDifference = difference % stepSize;
       if (errorDifference != 0) // entered value not valid
       {
           var correctedValue = customRound(enteredValue - (stepSize - errorDifference));
           if (!setValueFunctionCalled)
           {
               setValueFunctionCalled = true;
               numericTextBox.set_value(correctedValue);
           }
        }
     }

    I hope this helps.

    Greetings,
    Radoslav
    the Telerik team
    Browse the vast support resources we have to jumpstart your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
  6. Ibrahim Imam
    Ibrahim Imam avatar
    69 posts
    Member since:
    Jul 2007

    Posted 07 Dec 2010 Link to this post

    thanks for the fast reply.
    EDIT:
    unfortunately the recursion check strategy doesn't work that simple as there are many textboxes in the grid so multiple changes are possible.
    if i change first textbox and correct the value the variable is set to true.
    when i then change the next value the auto correct won't work anymore.

    as for the spin button issues
    1. setting the eventArgs._cancel property to false solved the issue that the value is changed again after setting the value manually
    2. i guess there is no way of getting the new value as the built in spin button action is performed after the custom method, right?
  7. Radoslav
    Admin
    Radoslav avatar
    1566 posts

    Posted 07 Dec 2010 Link to this post

    Hello Ibrahim,

    Indeed if you have the multiple RadNumericTextBox into the RadGrid the suggested approach with the Boolean flag would not work, however you could try keeping such a flag for every RadNumericTextBox. For example:
    var setValueFunctionCalled = new Array();
    function ValueChanged(sender, eventArgs)
    {
       var numericTextBox = sender;
       var enteredValue = numericTextBox.get_value();
       var initialValue = numericTextBox._originalValue;
       var stepSize = numericTextBox._incrementSettings.Step;
     
       var difference = customRound(initialValue - enteredValue);
       var errorDifference = difference % stepSize;
       if (errorDifference != 0) // entered value not valid
       {
           var correctedValue = customRound(enteredValue - (stepSize - errorDifference));
           if (!setValueFunctionCalled[sender._textBoxElement.id])
           {
               setValueFunctionCalled[sender._textBoxElement.id] = true;
               numericTextBox.set_value(correctedValue);
           }
        }
     }

    In this case every boolean item in the setValueFunctionCalled is associate with the textbox by its ID. Please give it try and let me know if it helps you.

    Additionally you could not get the new value after performing spin button actions. You could get it into the OnValueChanged event only.

    I hope this helps.

    Best wishes,
    Radoslav
    the Telerik team
    Browse the vast support resources we have to jumpstart your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
Back to Top