Allow empty or existing value not in list when submit editor form

Allow empty or existing value not in list when submit editor form

asleasle Posts: 113Questions: 31Answers: 0
edited June 22 in Editor

I have a <select> list in records from the main db publikasjon with values from a field isbn.litt_isbn. I pick the first available (=0) value from the DB field as an option and after submitting it is marked used (=1). This works. But I want to be able to accept existing field value and also no(empty) value. I have problems getting theValidate::: working and I get an error when submitting

<b>Fatal error</b>
:  Uncaught Error: Call to a member function optional() on string in /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Validate.php:174
Stack trace:
#0 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Validate.php(1032): DataTables\Editor\Validate::_common('\xEF\xBB\xBF978-82-345-0...', 'isbn')
#1 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Field.php(778): DataTables\Editor\Validate::DataTables\Editor\{closure}('\xEF\xBB\xBF978-82-345-0...', Array, Object(DataTables\Editor\Field), Array)
#2 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor.php(848): DataTables\Editor\Field-&gt;validate(Array, Object(DataTables\Editor), '4096')
#3 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor.php(1071): DataTables\Editor-&gt;validate(Array, Array)
#4 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor.php(716): DataTables\Editor-&gt;_process(Array)
#5 /home/1/m/mfu/www/code/js/Editor-PHP/controllers/upload-mfu.php(118): DataTables\Editor-&gt;process(Array)
#6 {main}
  thrown in <b>/home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Validate.php</b>
on line <b>174</b>
<br/>

Her is the field in js:

{
    label: 'ISBN:',
    name: 'publikasjon.litt_isbn',
    type: "select",
    placeholder: 'Ingen ISBN valgt',
    placeholderDisabled: false
},                   //other fields after this...

And the php code for the field:

Field::inst( 'publikasjon.litt_isbn' )
            ->options(function($db, $field) {
                $options = [];
                // Get the first available ISBN with status = 0
                $row = $db
                    ->query('select')
                    ->get(['isbn'])
                    ->table('isbn')
                    ->where('status', 0)
                    ->order('id ASC')
                    ->limit(1)
                    ->exec()
                    ->fetch();

                if ($row) {
                    $options[] = [
                        'label' => $row['isbn'],
                        'value' => $row['isbn']
                    ];
                }

                // Safely get the current value
                $current = null;
                if ($field !== null && method_exists($field, 'val')) {
                    $current = $field->val(); 
                }

                // If it's not the same as the one above, and it's not already in the list, add it
                if (!empty($current) && (!isset($row['isbn']) || $row['isbn'] !== $current)) {
            $options[] = [
                'label' => $current . ' (tidligere valgt)',
                'value' => $current
            ];
        }
                return $options;
                })
                ->validator(
                Validate::dbValues('isbn', 'isbn'),
                ValidateOptions::inst()->allowEmpty(true)
            )
        ,

Is this the correct way to do the sql to get the first field? I thin there is something I dont have correct in the Validate part but I can not find it out. So my goal is 1) Show current value if exists and accept it 2) Show first available number from isbn.isbn field. 3) Accept empty value on submit

Answers

  • asleasle Posts: 113Questions: 31Answers: 0
    edited June 22

    I think the error is with the Validate. It does not get the value to validate. When I run this

    ->validator(
            Validate::dbValues(),
            ValidateOptions::inst()->allowEmpty(true)
        )
    

    I get an error:
    Table for database value check is not defined for field publikasjon.litt_isbn
    But if I try this:

    ->validator(
            Validate::dbValues(),
            ValidateOptions::inst()
                ->table('isbn')
                ->field('isbn')
                ->allowEmpty(true)
        )
    

    I get this error:

    Fatal error: Uncaught Error: Call to undefined method DataTables\Editor\ValidateOptions::table() in /home/1/m/mfu/www/code/js/Editor-PHP/controllers/upload-mfu.php:78 Stack trace: #0 {main} thrown in /home/1/m/mfu/www/code/js/Editor-PHP/controllers/upload-mfu.php on line 78

  • allanallan Posts: 64,613Questions: 1Answers: 10,683 Site admin

    The ValidateOptions class doesn't have table or field methods. See the API reference docs for the class here.

                ->validator(
                    Validate::dbValues('isbn', 'isbn'),
                    ValidateOptions::inst()->allowEmpty(true)
                )
    

    from your first post looks more correct to me. You need to specify the table / column information for the validator since it can't derive it automatically from the options function (since it is a custom options function - which looks fine).

    What happens if you use that?

    Allan

  • asleasle Posts: 113Questions: 31Answers: 0
    edited June 23

    I tried your suggestion now and when I try to add a value or no value and update I get this:

    <b>Fatal error</b>
    :  Uncaught Error: Call to a member function optional() on string in /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Validate.php:174
    Stack trace:
    #0 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Validate.php(1032): DataTables\Editor\Validate::_common('\xEF\xBB\xBF978-82-345-0...', 'isbn')
    #1 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Field.php(778): DataTables\Editor\Validate::DataTables\Editor\{closure}('\xEF\xBB\xBF978-82-345-0...', Array, Object(DataTables\Editor\Field), Array)
    #2 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor.php(848): DataTables\Editor\Field-&gt;validate(Array, Object(DataTables\Editor), '4096')
    #3 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor.php(1071): DataTables\Editor-&gt;validate(Array, Array)
    #4 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor.php(716): DataTables\Editor-&gt;_process(Array)
    #5 /home/1/m/mfu/www/code/js/Editor-PHP/controllers/upload-mfu.php(116): DataTables\Editor-&gt;process(Array)
    #6 {main}
      thrown in <b>/home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Validate.php</b>
    on line <b>174</b>
    <br/>
    

    The value I am sending to the table publikasjon while the select value is coming from table isbn . Is there some logic I am missing? Also The existing value (if present) does not show. It shows always "Ingen ISBN valgt" if I leave the placeholder code in the field definition:

    {
        label: 'ISBN:',
        name: 'publikasjon.litt_isbn',
        type: "select",
        placeholder: 'Ingen ISBN valgt',
        placeholderDisabled: false
    },
    
  • rf1234rf1234 Posts: 3,118Questions: 91Answers: 429

    If you select the placeholder "No ISBN selected" (translated it from Swedish) you are sending exactly that to the server. That is not going to work because it is not an empty string. Try this please:

    {
        label: 'ISBN:',
        name: 'publikasjon.litt_isbn',
        type: "select",
        placeholder: 'Ingen ISBN valgt',
        placeholderDisabled: false,
        placeholderValue: "" //the placeholder value is empty
    },
    
  • asleasle Posts: 113Questions: 31Answers: 0

    Thanks, I still get the same error:
    <b>Fatal error</b>
    : Uncaught Error: Call to a member function optional() on string in /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Validate.php:174
    Stack trace:
    #0 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Validate.php(1032): DataTables\Editor\Validate::_common('', 'isbn')
    #1 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Field.php(778): DataTables\Editor\Validate::DataTables\Editor{closure}('', Array, Object(DataTables\Editor\Field), Array)
    #2 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor.php(848): DataTables\Editor\Field->validate(Array, Object(DataTables\Editor), '4096')
    #3 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor.php(1071): DataTables\Editor->validate(Array, Array)
    #4 /home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor.php(716): DataTables\Editor->_process(Array)
    #5 /home/1/m/mfu/www/code/js/Editor-PHP/controllers/upload-mfu.php(116): DataTables\Editor->process(Array)
    #6 {main}
    thrown in <b>/home/1/m/mfu/www/code/js/Editor-PHP/lib/Editor/Validate.php</b>
    on line <b>174</b>
    <br/>

    Also the current value is still not showing. If the record has a value the select still shows only 2 options, "Ingen ISBN valgt"(selected) and the first available value from isbn.isbn.

  • allanallan Posts: 64,613Questions: 1Answers: 10,683 Site admin

    Gah - I messed up the parameters for the dbValues method - sorry. Per the docs it is:

    dbValues( ValidateOptions $cfg=null, string $column=null, string $table=null, Database $db=null, array $valid=null)
    

    So you would use:

    ->validator(
      Validate::dbValues(
        ValidateOptions::inst()->allowEmpty(true),
        'isbn', // column
        'isbn' // table
      ),
    

    Allan

  • asleasle Posts: 113Questions: 31Answers: 0

    Thanks, this solved the update. I am able to update now (after adding the missing parenthes, no problem). The value, empty value or the value from "isbn.isbn" is added to the record but I am not able to read it back. The value shows in Datatables but in Editor it still is "Ingen ISBN valgt". The select does not show the current value. Any idea why? Here is my code now on the controller:

    Field::inst('publikasjon.litt_isbn')
            ->options(function ($db, $field) {
            $options = [];
            // Get the first available ISBN (status = 0)
            $row = $db
                ->query('select')
                ->get(['isbn'])
                ->table('isbn')
                ->where('status', 0)
                ->order('id ASC')
                ->limit(1)
                ->exec()
                ->fetch();
            if ($row) {
                $options[] = [
                    'label' => $row['isbn'],
                    'value' => $row['isbn']
                ];
            }
            // Get the current value in the record being edited
                $current = null;
                    if ($field !== null && method_exists($field, 'val')) {
                $current = $field->val();
                    }
                if (!empty($current) && (!isset($row['isbn']) || $row['isbn'] !== $current)) {
                    $options[] = [
                        'label' => $current . ' (tidligere valgt)',
                        'value' => $current
                    ];
                }
            return $options;
                 }) 
                ->validator(
                    Validate::dbValues(
                        ValidateOptions::inst()->allowEmpty(true),
                        'isbn', // column
                        'isbn' // table
                    )) 
    
  • rf1234rf1234 Posts: 3,118Questions: 91Answers: 429

    If you are using my and Allan's code suggestions everything should be fine - since you are not using a getFormatter which isn't required because ISBN is a simple string.

    Hard to tell without a test case, I guess. Could you provide one, please?

  • asleasle Posts: 113Questions: 31Answers: 0

    I am not sure what you mean but I made a test page here that you can create, edit and delete records.
    https://dev.mfu.no/code/admin-test.html
    If you look at the child data of a record you can find one with a valid ISBN number but it does not show in Editor. If you add the ISBN number suggested you will see it in the child row but not in Editor. The next time you edit or create a record you see a new ISBN number so it seems that logic is working.

Sign In or Register to comment.