Allow empty or existing value not in list when submit editor form
Allow empty or existing value not in list when submit editor form
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->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(118): 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/>
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
I think the error is with the Validate. It does not get the value to validate. When I run this
I get an error:
Table for database value check is not defined for field publikasjon.litt_isbn
But if I try this:
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
The
ValidateOptions
class doesn't havetable
orfield
methods. See the API reference docs for the class here.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
I tried your suggestion now and when I try to add a value or no value and update I get this:
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:
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:
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.
Gah - I messed up the parameters for the
dbValues
method - sorry. Per the docs it is:So you would use:
Allan
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:
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?
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.
Hi asle,
I used your test page and created two entries. Yes, there is only one ISBN to select but that is either ok or you have a problem with your options instance which looks a bit "weird" to me.
I created one record that has the one and only ISBN and another one that doesn't have the ISBN filled. Looks fine in the data table and also in the respective Editor pop up.
As I can see you are loading only this one ISBN option from the server:
Roland
It doesn't show in Editor because the options list only has a single option - which doesn't match the value of the ISBN in the row that was selected, hence it shows the placeholder.
You have
->limit(1)
in the options for getting the values for the ISBN. I don't quite understand what the intention is here - what's the point of having aselect
which only has a single option? Also, presumably you don't want to just list all ISBN's that would be insane. Is free text with an ISBN validator an option for you? As I say, I'm not clear on what the intention with this field is.One thing, it looks like you are expecting the options to update per row. That isn't the case for the way it is configured. If you need to load different options for
select
based on a row, you need to usedependent()
and have it make an Ajax request to get the options to show for that row.Allan
Something in addition to Allan's last remark. If you are requiring updated options per row you would need to load them when needed.
That could be on "select" or on "preOpen" for example. You would pass the id to the server and retrieve the array of label / value pairs.
Sorry - yes, use
preOpen
rather thandependent()
for this. Good point @rf124!Allan
Sorry for the confusion. I will try to explain. I have a table ISBN that contains 1000 valid ISBN numbers. Every record (publication) should get a unique ISBN but not required when the record is created. When creating or editing a record my idea was to show the first free ISBN number. When the number is used it is marked "1" so the next record can choose the next free ISBN number (marked 0). This logic works now. The choosen number is added and marked "1". If the record has a ISBN number, display it. If not show "No valid ISBN". So I force to use the first free number in the ISBN list. Choosing "No valid ISBN" and updating should delete the current number and choosing the displayed number enters that in the record.
Is using a <select> list a bad approach for this? As you see the ISBN is correct in the datatable so it would also be if I used a text field in Editor. I am a bit stuck since I thought the only problem was displaying the current value but I understand this is not so logical.
Since you have that limitation all you would need to do is to update the options on "preOpen". Just use my logic above and retrieve the relevant options which are:
a) "create": The empty option plus the next available ISBN
b) "edit": The empty option plus the next available ISBN OR the selected ISBN (if any)
Don't know whether that is working with the placeholder and the placeholderValue. If not just modify my code like this for example:
It could be something like this (provided that the placeholder and placeholderValue stuff still works). You would only need to call the server in case the record doesn't exist yet or no ISBN has been selected yet.
This would retrieve the option in case it hasn't been saved yet (using Editor's db handler and Editor`s "raw" method):