Laravel-Backpack / CRUD

Build custom admin panels. Fast!
https://backpackforlaravel.com
MIT License
3.17k stars 896 forks source link

[Field Type] addClause on select, select2, select_multiple, select2_multiple, checklist, checklist_dependency #47

Closed tabacitu closed 8 years ago

tabacitu commented 8 years ago

@AurelDragut made an interesting suggestion: at some point, we'll definitely need to filter the results in these 1-n and n-n fields.

Say:

I see one way to do this right now:

But... it's not pretty... Should we do something about this? What better ways do you see to solve this?

Thanks, cheers!

tabacitu commented 8 years ago

There are a few solutions to this, available right now. Let's round them up: 1) use the select_from_array field type and give it a filtered array of results; 2) create a new field type, where you copy-paste the select2 field type and just load the options you want; 3) create a new model that extends the old one and overwrites the "all" method to restrict the query (as mentioned above);

Since there are 3 existing solutions to this possible problem, with option 1 being a very good one ( in my opinion) I'll go ahead and close this issue.

qasmaoui commented 7 years ago

hi , i have this situation a table : containing iphone brand ( apple samsung ...) Schema::create('marque_tel', function (Blueprint $table) {

        $table->increments('id');
        $table->string('nom_marque');
        //
    });

a model table containing phones models ( 5S , 6 , 7 for appel , S1 , S2 ... for samsung ) Schema::create('model_tel', function (Blueprint $table) { $table->increments('id_model'); $table->string('nom_model'); $table->date('annee_model'); $table->timestamps(); $table->integer('marque_id')->unsigned(); $table->foreign('marque_id')->references('id')->on('marque_tel'); });

a reference table contaiing the id

Schema::create('model_ref', function (Blueprint $table) { $table->increments('id'); $table->string('nom_ref'); $table->integer('model_id')->unsigned(); $table->foreign('model_id')->references('id')->on('model_tel'); $table->timestamps(); }); i managed to create admin menu item using crud for marque ( brand ) table so i list , add modify phone brands , and also i managed to create a model menu item to manage phones models ( model_tel table ) using this crud controller `<?php

namespace App\Http\Controllers\Admin;

use Backpack\CRUD\app\Http\Controllers\CrudController;

// VALIDATION: change the requests to match your own file names if you need form validation
use App\Http\Requests\Admin\marquecrudrequest as StoreRequest;
use App\Http\Requests\Admin\marquecrudrequest as UpdateRequest;

class ModelTelController extends CrudController {

    /**
     *
     */
    public function setup() {
        $this->crud->setModel("App\Larapen\Models\model_tel");
        $this->crud->setRoute("admin/model");
        $this->crud->setEntityNameStrings('model', 'model_tel');

 $this->crud->addColumn([
    'name' =>'id',
    'label' =>'id',
    ]);
  $this->crud->addColumn([
            'label' => "marque tel", // Table column heading
    'type' => 'select',
    'name' => 'marque_id', // the column that contains the ID of that connected entity;
    'entity' => 'marque_tel', // the method that defines the relationship in your Model
    'attribute' => "nom_marque",
// foreign key attribute that is shown to user
    'model' => 'App\Larapen\Models\marque_tel', // foreign key model'
        ]);
    $this->crud->addColumn([
            'name' => 'nom_model',
            'label' => "nom model",
        ]);
        $this->crud->addColumn([
            'name' => 'annee_model',
            'label' => "annee model",
        ]);

        $this->crud->addField([
            'name' => 'nom_model',
            'label' => "nom model",
        ]);
        $this->crud->addField([
            'name' => 'annee_model',
            'label' => "annee model",
            'type' => 'datetime'
        ]);
        $this->crud->addField([
        'label' => "id Marque",
        'type' => 'select',
        'name' => 'marque_id', // the db column for the foreign key
        'entity' => 'marque_tel', // the method that defines the relationship in your Model
        'attribute' => 'nom_marque', // foreign key attribute that is shown to user
        'model' => 'App\Larapen\Models\marque_tel' // foreign key model

        ]);
    }

    public function store(StoreRequest $request)
    {
        return parent::storeCrud();
    }

    public function update(UpdateRequest $request)
    {
        return parent::updateCrud();
    }
}`

my probleme now is tha i want to be able to select brand ( marque_tel ) then only model of this brend is shown when adding reference for model

many searches lead me to hasmanythrought by i dont know how to uses it with crud . and

MarcosBL commented 7 years ago

Just used the method @tabacitu proposes. I had a select2 with a model Cursos that I wanted filled only with activo=1 (active, boolean field) records in related models.

So in the same Models\Cursos.php file (to keep things together) I added a second mini-class:

class CursosActivos extends Cursos
{
    public static function boot()
    {
        parent::boot();
        static::addGlobalScope('activo', function (Builder $builder) {
            $builder->where('activo', 1);
        });
    }

}

And in my CrudController I set the select2 instead of the regular

'model' => "App\Models\Cursos"

to the new filtered one

'model' => "App\Models\CursosActivos"

Et voilá, my select2 combos only show active courses :smiley:

engbanna commented 6 years ago

I make extension for select2 field to support filter results

  1. Add filter on filed crud

    $this->crud->addField([
            'label' => ' Members',
            'type' => 'select2',
            'name' => 'user_id',
            'entity' => 'user',
            'attribute' => 'name_email_points',
            'model' => "App\Models\Member",
            'attributes' => ['required' => 'required', ],
            'filter' => ['key'=>'points', 'operator'=>'>', 'value'=>5],
        ]);
  2. update select2 field file

        @if (isset($field['model']))
            <?php
                    if(isset($field['filter']) && is_array($field['filter'])){
                        $filter = $field['filter'];
                        $key = $filter['key'];
                        $val = $filter['value'];
                        $op = (isset($filter['operator']))? $filter['operator']: '==';
    
                        $fields = $field['model']::where($key,$op ,$val)->get() ;
                    }else{
                        $fields = $field['model']::all() ;
                    }
    
                ?>
            @foreach ($fields as $connected_entity_entry)
jrbecart commented 5 years ago

Following @MarcosBL example, I had to do like this (probably because of a newer laravel version?) :

In a separate file:

<?php
namespace App\Models;
class CursosActivos extends Cursos
{
    public static function boot()
    {
        parent::boot();
        static::addGlobalScope(function ($query) {
            $query->where('activo', 1);
        });
    }
}
edrisaturay commented 1 year ago

I normally create a trait and add all my fields like this.

` protected function select2_multiple_field( $_name, $_attribute = 'name', $_wrapperClass = 'col-12', $_tab = null, $_options = null, ){ return $this->crud->addField([ 'name' => $name, 'label' => ucwords(Str::replace('', ' ', $_name)), 'type' => 'select2_multiple', 'entity' => $_name, 'attribute' => $_attribute, 'wrapper' => [ 'class' => 'form-group ' . $_wrapperClass, ], 'hint' => _('Please select the :name', ['name' => ucwords(Str::replace('', ' ', $_name))]), 'tab' => $_tab, 'options' => function ($query) { return $query->where('status', 1)->get(); }, ]);

}

`

and in the crud controller i include the trait using use ReOccuringFieldsTrait; and call it like this $this->select2_multiple_field( 'appointment_purposes', 'name', 'col-md-12', null, );