Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiselect not showing selected options in edit form in Laravel 5.1 #206

Open
Easiey opened this issue Aug 11, 2015 · 8 comments
Open

Multiselect not showing selected options in edit form in Laravel 5.1 #206

Easiey opened this issue Aug 11, 2015 · 8 comments

Comments

@Easiey
Copy link

Easiey commented Aug 11, 2015

Hello, in my application I use form with multiselect. I followed instruction in this issue: #97. I only changed things that were required by Laravel 5.1 (e.g \App\File::class instead of 'File'). Saving works perfectly fine however edit doesn't show already selected items. Below is my code:

I need to do something like: each 'ArchitectEntry' can have multiple files attached and file can be attached to multiple 'ArchitectEntries'

Related Model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use SleepingOwl\Models\Interfaces\ModelWithFileFieldsInterface;
use SleepingOwl\Models\Traits\ModelWithImageOrFileFieldsTrait;
use SleepingOwl\Models\SleepingOwlModel;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class File extends SleepingOwlModel implements ModelWithFileFieldsInterface
{
    use ModelWithImageOrFileFieldsTrait;

    protected $fillable = [
        'file_src',
        'title',
        'architect_entries'
    ];

    public function getFileFields()
    {
        return [
            'file_src' => 'documents/',
        ];
    }

    public static function getList()
    {
        return static::lists('title', 'id')->all();
    }

    public function scopeDefaultSort($query)
    {
        return $query->orderBy('title', 'asc');
    }

    public function forms()
    {
        return $this->hasMany(Form::class);
    }

    public function architectEntries()
    {
        return $this->belongsToMany('architect_entry', "architect_entry_file");
    }

}

Base model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use SleepingOwl\Models\SleepingOwlModel;
use SleepingOwl\Models\Interfaces\ModelWithOrderFieldInterface;
use SleepingOwl\Models\Traits\ModelWithOrderFieldTrait;
use SleepingOwl\Models\Traits\ModelWithImageOrFileFieldsTrait;
use SleepingOwl\Models\Interfaces\ModelWithFileFieldsInterface;

class ArchitectEntry extends SleepingOwlModel
{

    //protected $table = 

    protected $fillable = [
        'title',
        'file_src',
        'file_id',
        'sort_field',
    'description',
    'files'
    ];

    public function getSortField()
    {
        return 'sort_field';
    }

    public function files()
    {
        return $this->belongsToMany('App\File', "architect_entry_file");
    }

    public static function getList()
    {
        return static::lists('title', 'id')->all();
    }


    public function setFilesAttribute($files)
    {
        $this->files()->detach();
        if ( ! $files) return;
        if ( ! $this->exists) $this->save();
        $this->files()->attach($files);
    }


}

Admin model

<?php 

 Admin::model(App\ArchitectEntry::class)->title('whatever')->as('whatever')->with('files')->filters(function ()
{

})->columns(function ()
 {
    Column::string('title', 'Tytuł');
 })->form(function ()
 {
    FormItem::text('title', 'Title')->attributes(['placeholder' => 'Title']);
    FormItem::multiSelect('files', 'Select related files')->list(\App\File::class)->value('files.id');

 });

Does anyone know solution to this problem?
Thanks.

@pedrofaria
Copy link

This is a veeeeery old problem with javascript chosen library...

take a look at harvesthq/chosen#92 and you will found many solutions to prevent this behavior.

@tylerteh
Copy link

I encountered the same problem.
I am using SleepingOwl v.2.0.43, which I believe it is not using Chosen library.
Does anyone know solution to this problem?
Thanks.

@pedrofaria
Copy link

For me, this is a BUG on chosen... buuuut... there is a solution. Just set the width of .chosen-container on you css. maybe with !important clausule.

Regards...

@tylerteh
Copy link

I found the reason, this is caused by the changes of lists method in Laravel 5.1, as stated at http://laravel.com/docs/5.1/upgrade#upgrade-5.1.0

The lists method now returns a Collection instance instead of a plain array for Eloquent queries. If you would like to convert the Collection into a plain array, use the all method:

User::lists('id')->all();

Be aware that the Query Builder lists method still returns an array.

So I think the solution is to use Custom Form Elements.

@turistua
Copy link

It seems I have similar problem. Laravel 5.1 and the latest sleeping-owl 2 version.

Currently sleeping-owl 2.x uses bootstrap-multiselect component, but not choosen as mentioned above.

I managed the getList() function as required in laravel 5.1

public static function getList()
{
    return static::lists('name', 'id')->all();
}

When I try to edit form with multiselect field, currently selected options are not active (I see "Nothing selected" text instead of it, also checkboxes from dropdown are not selected).

But form contains list of options, and I can create entity with multiselect field, edit it, etc.

Any prediction why edit form is not filled by previously set values for multiselect field?

Thank you in advance.

@tylerteh
Copy link

@turistua
Your getList() function is good.
The problem is caused by the values() function in
/vendor/sleeping-owl/admin/src/SleepingOwl/Admin/Models/Form/FormItem/MultiSelect.php

At line 121, if you change

$result = $result->lists($part);

to

$result = $result->lists($part)->all();

then your multiselect field should be working properly.

This solution is quick but not in a proper way.
Because the /vendor/ directory is not in version control.
When you deploy the same project in other server, you might need to repeat this trick.

For me, I choose to use Custom Form Elements.
This is how I did:

  1. Create /app/Forms/MultiSelect2.php
<?php

namespace App\Forms;

use SleepingOwl\Admin\Exceptions\ValueNotSetException;
use Illuminate\Database\Eloquent\Relations\Relation;
use SleepingOwl\Admin\Models\Form\FormItem\MultiSelect;

class MultiSelect2 extends MultiSelect
{
    protected $name;
    protected $label;

    function __construct()
    {
        parent::__construct($this->name, $this->label);
    }

    /**
     * @throws ValueNotSetException
     * @return mixed
     */
    public function values()
    {
        $result = $this->form->instance;

        if (is_null($this->value)) {
            throw new ValueNotSetException;
        }

        $parts = explode('.', $this->value);

        foreach ($parts as $part) {
            if ($result instanceof Relation) {
                $result = $result->lists($part)->all();
            } else {
                $result = $result->$part();
            }
        }

        if (count($result) == 0 && ! $this->form->instance->exists) {
            return $this->getDefault();
        }

        return $result;
    }

    public function setName($name)
    {
        $this->name = $name . '[]';
        return $this;
    }

    public function setLabel($label)
    {
        $this->label = $label;
        return $this;
    }
}
  1. Register MultiSelect2 in /app/admin/bootstrap.php
FormItem::register('multiSelect2', \App\Forms\MultiSelect2::class);
  1. Usage in model configuration
FormItem::multiSelect2('clusters')
    ->setName('clusters')
    ->setLabel('Business Clusters')
    ->list(\App\Cluster::class)
    ->value('clusters.cluster_id')
;

@MurDaD
Copy link

MurDaD commented Dec 20, 2015

@tylerteh mentioned a good way to solve this problem, but I think it must be updated a little

The main problem (for me) is: Integrity constraint violation: 1052 Column 'id' in field list is ambiguous That's because field 'id' goes without table selector. You can add selector with ->select() method

So, your values() method in file /vendor/sleeping-owl/admin/src/SleepingOwl/Admin/Models/Form/FormItem/MultiSelect.php should look like this

public function values()
{
    $result = $this->form->instance;
    if (is_null($this->value))
    {
        throw new ValueNotSetException;
    }
    $parts = explode('.', $this->value);
    $key = '';
    foreach ($parts as $part)
    {
        if ($result instanceof Relation)
        {
            $result = $result->select($key.'.*')->lists($part)->all();
        } else
        {
            $key = $part;
            $result = $result->$part();
        }
    }
    if (count($result) == 0 && ! $this->form->instance->exists)
    {
        return $this->getDefault();
    }
    return $result;
}

MurDaD added a commit to MurDaD/admin that referenced this issue Dec 20, 2015
This fixes "Integrity constraint violation: 1052 Column 'id' in field list is ambiguous" for Laravel 5.1+
@djkaushiksk1
Copy link

I'm having issues with my multi-select .It works fine but after sometime it submits empty string and it bypasses all the validation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants