I've added some relationship fields to some creation forms that works fine (I still get an error about the id that is undefined if no objects are present in database), but only the first time I open it.
Every time next to the first (which has concluded successfully or not), the form wont show.
And, as stated in my comment, when inline creation is enabled _or the field is in AJAX mode_ (needs more tests), the fetching doesn't work.
These are my classes:
AppModelsContract
<?php
namespace App\Models;
use Backpack\CRUD\app\Models\Traits\CrudTrait;
use Illuminate\Database\Eloquent\Model;
class Contract extends Model
{
use CrudTrait;
public $identifiableAttribute = 'customer_code';
protected $table = 'contracts';
protected $guarded = ['id'];
protected $fillable = [
'customer_code',
'grouping_code',
'state',
'notes',
'agreed_at',
'expires_on',
'tariff_id',
'consumer_id',
'context_id',
];
protected $dates = [
'agreed_at',
'expires_on',
];
public function electricMeter() {
return $this->hasMany('App\Models\ElectricMeter');
}
public function gasMeter() {
return $this->hasMany('App\Models\GasMeter');
}
public function tariff() {
return $this->belongsTo('App\Models\Tariff', 'tariff_id');
}
public function consumer() {
return $this->belongsTo('App\Models\Consumer', 'consumer_id');
}
public function context() {
return $this->belongsTo('App\Models\User', 'context_id');
}
}
AppModelsTariff
<?php
namespace App\Models;
use Backpack\CRUD\app\Models\Traits\CrudTrait;
use Illuminate\Database\Eloquent\Model;
class Tariff extends Model
{
use CrudTrait;
protected $table = 'tariffs';
protected $guarded = ['id'];
protected $fillable = [
'name',
'description',
'price',
'supplier_id'
];
protected $with = [
'supplier'
];
public function contracts() {
return $this->hasMany('App\Models\Contract', 'tariff_id');
}
public function supplier() {
return $this->belongsTo('App\Models\Supplier', 'supplier_id');
}
}
AppHttpControllersAdminContractCrudController
<?php
namespace App\Http\Controllers\Admin;
use App\Enums\ContractState;
use App\Enums\MeterType;
use App\Helpers\RelationshipCrudHelper;
use App\Http\Requests\ContractRequest;
use App\Models\Consumer;
use App\Models\Tariff;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
/**
* Class ContractCrudController
* @package App\Http\Controllers\Admin
* @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
*/
class ContractCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation;
/**
* Configure the CrudPanel object. Apply settings to all operations.
*
* @return void
*/
public function setup()
{
$this->crud->setModel(\App\Models\Contract::class);
$this->crud->setRoute(config('backpack.base.route_prefix') . '/contract');
$this->crud->setEntityNameStrings('contratto', 'contratti');
}
protected function setupListOperation()
{
// Columns
}
protected function setupCreateOperation()
{
$this->crud->setValidation(ContractRequest::class);
$this->crud->addField([
'name' => 'customer_code',
'label' => 'Numero Cliente',
'type' => 'text',
'wrapper' => [
'class' => 'form-group col-md-5'
],
]);
$this->crud->addField([
'name' => 'grouping_code',
'label' => 'Codice di raggruppamento',
'type' => 'text',
'wrapper' => [
'class' => 'form-group col-md-4'
],
]);
$this->crud->addField([
'name' => 'state',
'label' => 'Stato',
'type' => 'select_from_array',
'options' => ContractState::getAllWithNames(),
'wrapper' => [
'class' => 'form-group col-md-3'
],
]);
$this->crud->addField([
'name' => 'agreed_on',
'label' => 'Stipulato il',
'type' => 'date',
'wrapper' => [
'class' => 'form-group col-md-6'
],
]);
$this->crud->addField([
'name' => 'ceased_on',
'label' => 'Cessa il',
'type' => 'date',
'wrapper' => [
'class' => 'form-group col-md-6'
],
]);
$this->crud->addField([
'name' => 'tariff_id',
'entity' => 'tariff',
'model' => 'App\Models\Tariff',
'type' => 'relationship',
'label' => 'Tariffa',
'placeholder' => 'Selezionare una tariffa',
'wrapper' => [
'class' => 'form-group col-md-4'
],
//'ajax' => true,
'inline_create' => true,
]);
/*$this->crud->addField([
'name' => 'consumer_id',
'entity' => 'consumer',
'model' => 'App\Models\Consumer',
'type' => 'relationship',
'label' => 'Utenza',
'placeholder' => 'Selezionare un\'utenza',
'inline_create' => true,
'wrapper' => [
'class' => 'form-group col-md-7 offset-md-1'
],
]);*/
$this->crud->addField([
'name' => 'notes',
'label' => 'Note',
'type' => 'textarea',
]);
/*$this->crud->addField([
'name' => 'context_id',
'entity' => 'context',
'model' => 'App\Models\User',
'type' => 'relationship',
'label' => 'Utente (Contesto)',
'placeholder' => 'Selezionare un contesto'
]);*/
}
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
protected function setupShowOperation() {
$this->crud->set('show.setFromDb', false);
$this->setupListOperation();
}
public function fetchTariff() {
$this->fetch(Tariff::class);
}
public function fetchConsumer() {
$this->fetch(Consumer::class);
}
}
AppControllersAdminTariffCrudController
<?php
namespace App\Http\Controllers\Admin;
use App\Helpers\RelationshipCrudHelper;
use App\Http\Requests\TariffRequest;
use App\Models\Supplier;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
/**
* Class TariffCrudController
* @package App\Http\Controllers\Admin
* @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
*/
class TariffCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation;
/**
* Configure the CrudPanel object. Apply settings to all operations.
*
* @return void
*/
public function setup()
{
$this->crud->setModel(\App\Models\Tariff::class);
$this->crud->setRoute(config('backpack.base.route_prefix') . '/tariff');
$this->crud->setEntityNameStrings('tariffa', 'tariffe');
}
protected function setupListOperation()
{
// Columns
}
protected function setupCreateOperation()
{
$this->crud->setValidation(TariffRequest::class);
$this->crud->addField([
'name' => 'name',
'label' => 'Nome',
'type' => 'text'
]);
$this->crud->addField([
'name' => 'description',
'label' => 'Descrizione',
'type' => 'textarea'
]);
$this->crud->addField([
'name' => 'price',
'label' => 'Prezzo',
'type' => 'number',
'attributes' => [
'step' => 'any'
],
'suffix' => '€',
'wrapper' => [
'class' => 'form-group col-md-4'
]
]);
$this->crud->addField([
'name' => 'supplier_id',
'entity' => 'supplier',
'type' => 'relationship',
'label' => 'Fornitore',
'model' => 'App\Models\Supplier',
'placeholder' => 'Selezionare un fornitore',
'inline_create' => true,
'wrapper' => [
'class' => 'form-group col-md-8'
],
]);
}
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
protected function setupShowOperation() {
$this->crud->set('show.setFromDb', false);
$this->setupListOperation();
}
public function fetchSupplier() {
return $this->fetch(Supplier::class);
}
}
I expected that I could open and close the modal indefinite times.
In console I get these errors:
This is the error that I get when there aren't objects available (no entries in the database):
create:572 Uncaught TypeError: Cannot read property 'id' of undefined
at Object.success (create:572)
at l (bundle.js?v=4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5:2)
at Object.fireWith [as resolveWith] (bundle.js?v=4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5:2)
at T (bundle.js?v=4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5:2)
at XMLHttpRequest.<anonymous> (bundle.js?v=4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5:2)
This is the error that I get with the modal every time I want to add a new object (except for the first time):
create:498 Uncaught TypeError: $fields.forEach is not a function
at HTMLButtonElement.<anonymous> (create:498)
at HTMLButtonElement.dispatch (bundle.js?v=4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5:2)
at HTMLButtonElement.g.handle (bundle.js?v=4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5:2)
I tried to reach the file that should handle this logic, but I haven't found it.
When I run php artisan backpack:version the output is:
### PHP VERSION:
PHP 7.4.0 (cli) (built: Nov 27 2019 10:14:18) ( ZTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.0, Copyright (c), by Zend Technologies
### LARAVEL VERSION:
v7.20.0@682ea946bc136aa686d5a64940ab3d4a24d5a613
### BACKPACK VERSION:
4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5
UPDATE
Using inline_create prevents the fetching of the relatable entities.
Commenting it out, makes all the items (tariffs in my code) appear.
Hello @rinodrummer
Thanks for the report.
I could find one of the bugs, it was introduced by me in my previous update to inline create, when adding the ability to pass the main form fields along with the request to get the dialog for inline create.
I am sorry for that, I just pushed a PR with the proper fix #3064
Can you give it a test @rinodrummer ?
Thanks,
Pedro
@pxpm Sorry for my stupid question, but how can I pull your PR in my project?
I already tried composer update, but nothing changed.
Not a stupid question, @rinodrummer - don't worry.
I think the easiest way would be to do composer require backpack/crud:"dev-fix-inline-main-modal-fields-inclusion as 4.1.99" (dev dash the branch name). That will make composer pull that branch, instead of the usual one, but use it as if it were the version 4.1.99.
Then when you're done testing, you should do composer require backpack/crud:"4.1.*" to go back to normal.
Alternatively, you can make the edits above directly in your composer.json file, then run composer update.
Thanks @tabacitu!
@pxpm, I tested it: the modal error is gone, but the other 2 are still there.
If you have any question, I'm here to help.
@pxpm I have solved this:
create:572 Uncaught TypeError: Cannot read property 'id' of undefined
at Object.success (create:572)
at l (bundle.js?v=4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5:2)
at Object.fireWith [as resolveWith] (bundle.js?v=4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5:2)
at T (bundle.js?v=4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5:2)
at XMLHttpRequest.<anonymous> (bundle.js?v=4.1.15@6c751de946a9c8511dd32eb7bfa3ca6a568849f5:2)
I would like to push it and make you check, but I can't find your merge in my fork.
Sorry if I'm not experienced on working on a big project like this, but I really would like to help.
No problem @rinodrummer - not everybody's done open-source work already, and navigating how to do this on Github isn't really straightforward, I know.
Ok so in order to be able to create a PR with it, you should:
cd vendor/backpack/crud
git remote -v
git remote add upstream https://github.com/rinodrummer/CRUD.git
git push upstream master
fix-inline-main-modal-fields-inclusion branch if that's where you started your changes from, and that's where you want your PR to be merged.Let me know if your experience is different, it's been a while since I did it like this. And I think it's about time we create a tutorial on how to do this.
Cheers!
Thanks @tabacitu!
I successfully pushed on-top and created this PR: #3071.
Excellent. Thank you @rinodrummer for taking the time to submit this, let's close the issue then in order to have only one conversation about this - inside the PR.
We'll reopen if somehow the PR gets scrapped, but that rarely happens.
Cheers!
Wait, no. Since there are two PRs for this issue let's leave it open until they're both merged.
I'm going to close this since we can't reproduce it. @rinodrummer please let me know if you're still having it - if a composer update doesn't fix it for you.
Anybody else who's getting this, please reply here with details, so we know it's not done and have more info to work with, and we'll reopen.
Cheers!
@tabacitu Sorry for the time, but I've been a bit busy.
After updating Backpack to the latest version (4.1.25), I still have this problem:
create:659 Uncaught TypeError: Cannot read property 'id' of undefined
at Object.success (create:659)
at l (bundle.js?v=4.1.25@23fb1ed5153d5465d49d2fe1ca265a5985c78877:2)
at Object.fireWith [as resolveWith] (bundle.js?v=4.1.25@23fb1ed5153d5465d49d2fe1ca265a5985c78877:2)
at T (bundle.js?v=4.1.25@23fb1ed5153d5465d49d2fe1ca265a5985c78877:2)
at XMLHttpRequest.<anonymous> (bundle.js?v=4.1.25@23fb1ed5153d5465d49d2fe1ca265a5985c78877:2)
(It's an error that seems to refer to $relatedKeyName in result[0].)
Also now every InlineCreate form (even the ones the worked with the past versions) doesn't work (the AJAX request gets a 419 error status when getting the modal).
Hello @rinodrummer
Check if you are sending csrf token in the request.
Best,
Pedro
@pxpm I've checked, and CSRF token is not sent, but how can I send it?
This is my relationship field in my CRUD Controller:
$this->crud->addField([
'name' => 'invoice_id',
'entity' => 'invoice',
'type' => 'relationship',
'label' => 'Fattura',
'model' => 'App\Models\Invoice',
'placeholder' => 'Selezionare una fattura',
'data_source' => url('api/context/invoices'),
'include_all_form_fields' => true,
'minimum_input_length' => 0,
'ajax' => true,
'inline_create' => [
'force_select' => false,
'entity' => 'invoice',
'modal_class' => 'modal-dialog modal-lg'
],
'wrapper' => [
'class' => 'form-group col-md-7'
],
]);
EDIT: Finally found out the solution to this bug! It's the data_source field.
@pxpm, for the $relatedKeyName issue, I think that this code snippets should fix the console error:
resourcesviewscrudfieldsrelationshipfetch_or_create.blade.php:221
function (result) {
// if data is available here it means a paginated collection has been returned.
// we want only the first to be default.
$data = null;
if (result) {
if (typeof result.data !== "undefined"){
$data = result.data;
} else {
$data = result;
}
if ($data) {
if (Array.isArray($data)) {
if ($data.length > 0) {
$data = $data[0];
} else {
return resolve(null);
}
}
$key = $data[$relatedKeyName];
$value = processItemText($data, $relatedAttribute, $appLang);
$pair = { [$relatedKeyName] : $key, [$relatedAttribute] : $value};
$return = {...$return, ...$pair};
$(element).attr('data-current-value', JSON.stringify($return));
return resolve($return);
}
}
return resolve(null);
}
resourcesviewscrudfieldsrelationshipfetch_or_create.blade.php:603
//null is not allowed we fetch some default entry, but they may not exist
if(!$allows_null && !$item && $selectedOptions == null) {
fetchDefaultEntry(element).then(result => {
if (result) {
$(element).append('<option value="'+result[$modelKey]+'">'+result[$fieldAttribute]+'</option>');
$(element).val(result[$modelKey]);
$(element).trigger('change');
}
}).catch((err) => console.error);
}
Let me know if it helps.
I found another bug related to CSRF token and inline creation forms: the form opens right only the first time, all the next times it throws the same CSRF token mismatch error.

Thanks @rinodrummer !
What was the problem/solution with data_source exactly? I don't understand that part unfortunately.
Thanks @rinodrummer !
What was the problem/solution with
data_sourceexactly? I don't understand that part unfortunately.
@tabacitu, sorry for the misleading comment and the late answer, but I only found out that removing it solves the problem, but obviously it has to be solved in another way, possibly letting it stay there. I'm gonna investigate a bit more.
@rinodrummer if the problem is in data_source, it seems you are using a custom api. When you remove it, if you have a fetchInvoice defined, backpack will pick it up as the data_source using fetchOperation.
My guess is that when you remove it, the fetch operation picks up and sends the results as expected by backpack fields and might be slightly different from the returned results from your api.
I could not reproduce the error you showed in the gif: https://recordit.co/2irfcFKXGB
I understand the fact that the problem is related to a custom data_source, but why this field interferes with the inline creation?
This field should only be capable of picking data and filling the select2 field, I don't see any relation to the inline creation.
The only possible relation I think is that the data_source gets interrogated when the form gets submitted, but in my case, the form is not even shown.
data_source could relate to inline_create when an JS error is triggered, inline create could not work properly if there are other previous JS errors.
That's the only reason I can think about for inline_create failing related with data_source on main field.
Applying this fixes, I have no errors in console except the token mismatch one. That is hard to test, because sometimes fails even with non-AJAX requests.
@rinodrummer thanks for the fixes provided. Could you please share with me how can I reproduce the error that those fixes apply to ?
Thanks again for all the time you spent helping us to find those nasty bugs! _o_
Best,
Pedro
Sorry for the later answer, but I have been very busy.
I think that the errors emerge when some relationship fields aren't setted properly.
I'm trying my best to check how to reproduce the bug, but I find extremely hard to find out where is the problem.