Laravel Backpack select2_multiple not Displaying Correctly - laravel

I'm working with Backpack for Laravel, and implemented a select2_multiple field. The field works correctly, though it doesn't display properly at all. It's defined as:
$this->crud->addField([ // Select2Multiple = n-n relationship (with pivot table)
'label' => "Categories",
'type' => 'select2_multiple',
'name' => 'categories', // the method that defines the relationship in your Model
'entity' => 'categories', // the method that defines the relationship in your Model
'attribute' => 'title', // foreign key attribute that is shown to user
'model' => "App\Models\Category", // foreign key model
'pivot' => true // on create&update, do you need to add/delete pivot table entries?
]);
The pivot tables exist, as do the relationships on the models. The field shows for a second, and then in quickly hidden on page load (I guess by some JS). You can see below the 'categories' label, there's just white space:
I can, however, click in the white space and it will then appear and allow me to select categories as expected (though it displays rather strangely):
This is all default functionality, I haven't edited the select2_multiple template or any of the JS. Why is this displaying so poorly?

I believe it was a bug that has since been fixed. A composer update should fix it for you.

Is the model correct?
Maybe should be
'model' => "App\Category", // foreign key model

Related

Having multiple columns (foreign keys) of the same n-n relation in Backpackforlaravel

I'm struggling with the following situation:
My entities Session & Registration are related with a many-to-many (n-n) relationship. In Registration, I have two foreign keys, player_id and hotel_id.
In the Session CrudController, I want to display the related name(s) of the Player(s) and Hotel(s).
For Player, it worked like this:
CRUD::addColumn([
// any type of relationship
'name' => 'registrations', // name of relationship method in the model
'type' => 'relationship',
'label' => 'Spieler', // Table column heading
// OPTIONAL
'entity' => 'registrations', // the method that defines the relationship in your Model
'attribute' => 'player.full_name', // foreign key attribute that is shown to user
'model' => App\Models\Registration::class, // foreign key model
]);
So I've continued to add the Hotel like this:
CRUD::addColumn([
// any type of relationship
'name' => 'registrations', // name of relationship method in the model
'type' => 'relationship',
'label' => 'Hotel', // Table column heading
// OPTIONAL
'entity' => 'registrations', // the method that defines the relationship in your Model
'attribute' => 'hotel.name', // foreign key attribute that is shown to user
'model' => App\Models\Registration::class, // foreign key model
]);
But unfortunately it doesn't work - I don't get an error message, it just keeps showing only the Player column. I think the reason for this is the same value in 'name' - because after commenting the 'name' value in Player, the Hotel information was visible. But I have no idea how to avoid it.
Currently I'm not sure if it's a bug or if I'm doing anything wrong. Would appreciate any kind of support - thanks in advance!
thank you #tabacitu, that works!
I've added
'key' => 'hotel'
and it showed up in the table.

Two fields overwriting each others values on saving in Backpack for Laravel CRUD (spatie/laravel-tags implementation issues)?

I am trying to use spatie/laravel-tags together with Backpack for Laravel. I have 2 types of tags defined. Currently I have extended the Tag model from spatie/laravel-tags as MyCategory and MyTag and added global scopes to separate the two tag types. This works to the extent that it will display the current categories and tags correctly in Backpack, but when I try to save any changes it will only save the entries in the last field, and delete everything in the first field.
Here is my current field configuration for my CRUD:
$this->crud->addField([
'name' => 'categories',
'label' => 'Categories',
'type' => 'select2_multiple',
'tab' => 'Overview',
'attribute' => 'name',
'model' => 'App\MyCategory',
'pivot' => true,
]);
$this->crud->addField([
'name' => 'tags',
'label' => 'Tags',
'type' => 'select2_multiple',
'tab' => 'Overview',
'attribute' => 'name',
'model' => 'App\MyTag',
'pivot' => true,
]);
When I check Laravel Telescope I see that the same thing happens for both fields. First all current tags (regardless of type) for the item I am saving are deleted, and the new tags from the field are added. This is then repeated for the second field, which of course deletes the tags from the first field that should also be kept.
It seems that GlobalScope on my extended Tag models does not stick around for this part. Is there any way to reintroduce the scopes into the queries run by backpack to get these tags to save correctly?
In my CrudController I created custom update and store functions. See the update example below. This seems to work fine. There are still 2 queries being run, with the second one undoing the first one, but for my purposes this is a good enough workaround to be able to have 2 fields with different tag types in the same form in Backpack, using spatie/laravel-tags.
public function update(UpdateRequest $request)
{
$request = request();
// Merge the values from the two tag fields together into the second field
$request->merge(['tags' => array_merge((array)$request->input('categories'), (array)$request->input('tags'))]);
$redirect_location = $this->traitUpdate($request);
return $redirect_location;
}

Problem setting up relations in BREAD for models using Voyager admin for Laravel

I'm building a website in Laravel and using Voyager for an admin interface for the database. When I create a new model, I also create a seed file to set up the permissions and BREAD for that table.
This works great if the model isn't related to any other models. But when I add relations to the BREAD seeds, they only partway work. I can display the relation in my browses or reads, but any nothing happens if I try to change the related data during an edit. If I save the BREAD in Voyager - that is, making no changes and simply saving what is already there - the relation suddenly starts to work.
Example: Events are related to locations by a belongsTo relation. My event model is set up correctly and checking data in tinker demonstrates proper behavior. My event seed file contains this to set up the BREAD relationship:
$dataRow = $this->dataRow($eventDataType, 'event_belongsto_location_relationship');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'relationship',
'display_name' => 'Location',
'required' => 1,
'browse' => 1,
'read' => 1,
'edit' => 1,
'add' => 1,
'delete' => 0,
'details' => [
'model' => 'App\\Location',
'table' => 'locations',
'type' => 'belongsTo',
'column' => 'location_id',
'key' => 'id',
'label' => 'name',
'pivot_table' => 'locations',
'pivot' => '0',
],
'order' => 6,
])->save();
}
The seed file runs without error.
When I refresh and seed the database, the relationship shows up in the BREAD:
and I can change the location in my edit screen:
and the event record saves without error, but the new location isn't saved.
All I have to do to "fix" this problem is go back to the Tools - BREAD menu, select my events table, and edit the BREAD, and save it. I don't have to change anything. Just save it. And as far as I can tell, the only thing that changes in the database row for this relationship is update timestamp.
Do you have any idea what might be going wrong? I can't figure out what about my seed is incorrect and what changes between the seeding and the saving.

Relationships in Laravel Backpack - Not sure I understand

I installed backpack on the latest version of Laravel 6.
Upon running this command as a test:
php artisan make:migration:schema create_posts_table --schema="user_id:unsignedInteger:foreign,
name:string, slug:string, description:text, keywords:string:nullable"
The command created a Post model in Models/Post
I would like to see the names of the users from the "user" table in my "post" CRUD.
First question:
I generate my CRUD with:
php artisan backpack:crud post
I see the CRUD, at the top of the CRUD I would like to pass the users name from the User table in the select dropdown.
I tried this:
protected function setupCreateOperation()
{
$this->crud->setValidation(PostRequest::class);
// TODO: remove setFromDb() and manually define Fields
//$this->crud->setFromDb();
$this->crud->setColumnDetails([
'label' => 'User', // Table column heading
'type' => 'select',
'name' => 'user_id', // the column that contains the ID of that connected entity;
'entity' => 'backpackuser', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => 'App\Models\backpackuser' // foreign key model
]);
}
But I am getting the error:
Symfony\Component\Debug\Exception\FatalThrowableError
Too few arguments to function Backpack\CRUD\app\Library\CrudPanel\CrudPanel::setColumnDetails(), 1
passed in C:\laragon\www\backpack\app\Http\Controllers\Admin\PostCrudController.php on line 41 and
exactly 2 expected
My problem "I think" is related to the "'entity' => 'backpackuser',"
From what I understand I need to add the relation method here but what I don't get is that Backpack did not create it when running the first command, is this normal?
Also, which model shall I user to pass the user details into a select field?
App/User or App/Models/BackpackUser ?
Thank you.
setColumnDetails() has two parameters:
the name/key of the column you're modifying
the attributes you're modifying and their new values
It looks like you've only provided the second parameter. Hence the error "Too few arguments to function setColumnDetails(), 1
passed and
exactly 2 expected."
Try:
$this->crud->setColumnDetails('user_id', [
'label' => 'User', // Table column heading
'type' => 'select',
'entity' => 'backpackuser', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
]);
Pro tip: you don't need to specify the model. If on your Post model you have the backpackuser() relationship properly defined, Backpack will pick up the model from that relationship.
Yes, you should create a relationship manually and add it to the Post model.
In this case (see Users in the Posts CRUD), you need to add relation method into Post, not User.

How to add a default ordering of ListEntries table in Backpack for Laravel?

When a user first visits the page, the ListEntries table is ordered ascending by id and none of the ordering icons in the table header are active.
I would like to have the ListEntries table ordered by a column of my choosing, including having the icon next to this column active (either ascending or descending).
Is there a way to have the ListEntries table ordered by a column of my choosing when a user visits the page?
In your Controller's setup() method you can use:
$this->crud->orderBy('name', 'DESC');
Anything you pass to the orderBy() statement will be used on the Eloquent query.
By default, columns for real attributes (that have a correspondent column in the database) should be orderable. But you can also manually specify 'orderable' => true for columns, or define your own order logic. Note that relationship columns (1-n, n-n), model_function or model_function columns are NOT orderable by default, but you can make them orderable with orderLogic.
Hope it helps.
This can be done by manipulating the request object, which may be frowned upon in some circles.
This solution will also update the order icon on the appropriate column.
There are a number of ways to accomplish this, but one way would be to add the following to the setupListOperation() method of your Controller.
/** #var \Illuminate\Http\Request $request */
$request = $this->crud->getRequest();
if (!$request->has('order')) {
$request->merge(['order' => [
[
'column' => 'column-index-here',
'dir' => 'asc'
]
]]);
}
Use this key orderable it is a boolean
this->crud->addColumn([
'label' => 'Category',
'type' => 'select',
'name' => 'category_id', // the db column for the foreign key
'entity' => 'category', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'orderable' => true,
'orderLogic' => function ($query, $column, $columnDirection) {
return $query->leftJoin('categories', 'categories.id', '=', 'articles.select')
->orderBy('categories.name', $columnDirection)->select('articles.*');
}
]);
Reference

Resources