Comma-formatting in decimals in the editor

Comma-formatting in decimals in the editor

admanenteadmanente Posts: 7Questions: 2Answers: 1

I'm trying to implement decimal number formatting by using the comma instead of the dot. The error occurs when the Editor is going to save the data.
In PHP file i have this instance

Field::inst( 'rawProducts.olii' )->validator( 'Validate::numeric')->getFormatter( 'Format::toDecimalChar' )->setFormatter( 'Format::fromDecimalChar')->setFormatter( 'Format::ifEmpty', 0 ),

The data is rendered correctly with the comma, but when I click the save button I return the following error
This input must be given as a number.

Specifically, in the Mysql table the field is defined as float (6.2)

I've tried several options like entering the comma option in validation, replacing the setFormatter method with this function

->setFormatter( function($val, $data, $field) {return str_replace ( ',' , '.' , $val );})

I would also need to include a validation of minimum / maximum value but with this the problems multiply .

I have tried for many hours to come up with this issue but without results, no suggestions. Thanks in advance

Answers

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    Hi,

    The reason you aren't getting any where with the built in validators is that the validation function runs before the formatting function. So if you submit 3,141 that is what the numeric validator will see, and reject since it has a comma in it.

    The good news is that the built in numeric validator has an option to specify what the decimal character should be:

    ->validator( 'Validate::numeric', [
      "decimal" => ','
    ] )
    

    should do it.

    Regards,
    Allan

  • admanenteadmanente Posts: 7Questions: 2Answers: 1

    Hi Allan, thanks for your suggestions. I tried but did not work.
    I get this error when I save the data
    SQLSTATE[01000]: Warning: 1265 Data truncated for column 'olii' at row 1

    You would kindly have some other idea to suggest. Thank you

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    Can you show me the exact code you are using please? Also you also use a formatter to convert from the comma to a period?

    Allan

  • admanenteadmanente Posts: 7Questions: 2Answers: 1

    Hi Allan
    This is the part of code where I create the field instance:

    Field::inst( 'rawProducts.olii' )->getFormatter( 'Format::toDecimalChar')->setFormatter( 'Format::fromDecimalChar')->setFormatter( 'Format::ifEmpty', 0 )->validator( 'Validate::numeric', [ "decimal" => ','] ),

    Here the Editor form part
    { label: "Olii g", name: "rawProducts.olii" },

    And for the table this is the code:

    { data: "rawProducts.olii", className: "dt-body-center", render: $.fn.dataTable.render.number( '.', ',', 2 ) },

    The field in the table is float type.

    Thank you very much for your patience and support

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    ->setFormatter( 'Format::fromDecimalChar')->setFormatter( 'Format::ifEmpty', 0 )

    This is probably the cause of the issue. Although you can have multiple validators, you cannot have multiple get or set formatters. You would need to create a custom formatter function that would do the formatting that you need - in this case checking it the value is empty and also converting the decimal point.

    I'd suggest in the short term removing the ifEmpty formatter to see if that is the issue.

    Allan

  • admanenteadmanente Posts: 7Questions: 2Answers: 1
    edited June 2017

    Hi Allan
    I solved this way

    Instance field like this

    Field::inst( 'olii' )
      ->getFormatter( function($val, $data, $field) {return str_replace ( '.' , ',' , $val );})
      ->setFormatter( function($val, $data, $field) {return str_replace ( ',' , '.' , $val );}) 
      ->validator( function ( $val, $data, $opts ) {
        return $val > 100 || $val < 0  ? 'Il numero deve essere compreso fra 0 e 100' :  true
       } ),
    

    And nothing else!!!!!

    Thank you for your advice.

  • mankramomankramo Posts: 24Questions: 5Answers: 0

    Please @Alan and @rf1234 1234, is there anything wrong with the code below and if there is, what is the right way to format numbers to fourdecimal places like 1000 = 1000.0000

    Field::inst( 'nestor_exchangerates.exchangerate_amount' )
    ->validator( 'Validate::numeric', [
    "decimal" => '.'
    ] ),
    ->getFormatter( function ($val) {return (number_format($val,4));})
    ->setFormatter( function($val,$data) {return number_format($val,4);}),

  • rf1234rf1234 Posts: 2,801Questions: 85Answers: 406

    I see you are still working on your forex table :smile:

    I have a little one myself too.

    This is the PHP including the validators and formatters. The data base field is defined as DECIMAL(11,5).

    Editor::inst( $db, 'forex' )
        ->field(
            Field::inst( 'forex.currency' ),
            Field::inst( 'forex.date' )
                ->getFormatter( function ( $val, $data, $opts ) {
                        return getFormatterDate($val);                     
                    } )
                ->setFormatter( function ( $val, $data, $opts ) {
                        return setFormatterDate($val);
                    } ),
            Field::inst( 'forex.rate' )
                ->validator( function ( $val, $data, $opts ) {
                    return validatorRate($data['forex'], $val);
                } )
                ->getFormatter( function($val, $data, $opts) {
                    return getFormatterRate($val, 5);
                })
                ->setFormatter( function($val, $data, $opts) {
                    return setFormatterRate($val);
                }),
            Field::inst( 'forex.update_time' )
        )
        ->process($_POST)
        ->json();
    

    As you can see I have get and set formatters for the rate. I have two languages with different formatting. You can pass the number of decimals you would like to have as a parameter. If you don't pass anything the number of decimals will be 4.

    function getFormatterRate(&$val, $decimals = null) {
        if ( is_null($decimals) ) { //most rates have 4 decimals
            $decimals = 4;
        }
        if ($_SESSION['lang'] === 'de') {     
            return number_format($val, $decimals, ',', '.');
        } else {
            return number_format($val, $decimals);
        }
    }
    
    function setFormatterRate(&$val) {
        //replace an eventual decimal point with a comma for consistency
        //vice versa for English
        $numberString = '';
        if ($_SESSION['lang'] === 'de') {   
            $numberString = str_replace('.', ',', $val);
        } else {
            $numberString = str_replace(',', '.', $val);
        }    
        //replace the German decimal comma with a period
        if ($_SESSION['lang'] === 'de') {   
            $numberString = str_replace(',', '.', $numberString);
        }
        return $numberString;
    }
    
    function validatorRate (&$data, &$val, $empty = null) {
        if ( ! is_null($empty) ) {
            $emptyAllowed = $empty;
        } else {
            $emptyAllowed = false;
        }
        if ( isset($data['comments']) ||
             isset($data['description'])   ) {
            return true;
        } else {
            //get rid of eventual commas; periods are not harmful for numeric check
            $numberArray = explode(',', $val);
            $numberString = implode($numberArray);
            
            if ( $emptyAllowed && ( $val <= '' || $val === '0' ) ) {
                return true;
            }        
            if ( $val === '0' || $val <=  '' || ( ! is_numeric($numberString ) ) )  {
                if ($_SESSION['lang'] === 'de') {   
                    return 'Zinssatz / Devisenkurs muss numerisch und darf nicht leer sein!';
                } else {
                    return 'Rate must be numeric and may not be empty!';
                }
            } else {
                return true;
            }
        }
    }
    
  • rf1234rf1234 Posts: 2,801Questions: 85Answers: 406

    @mankramo , I forgot to mention it but I don't know whether anything is wrong with your code. If it's not working feel free to use bits and pieces of my code above which is working fine.

  • mankramomankramo Posts: 24Questions: 5Answers: 0

    Thank you very much @rf1234 for your continued assistance, I really appreciate it ;) . Your functions worked perfectly, i just took out those language conditions (My app is a mono-lang app :) for now )

This discussion has been closed.