BRACKETS-by-TRIAD / craftable

Admin panel builder / CRUD generator for Laravel.
https://getcraftable.com
MIT License
979 stars 192 forks source link

issue with multiselect default Value #413

Closed mzanier closed 1 year ago

mzanier commented 1 year ago

Hi,

so far i managed to add a multiselect with values based on an object (coming from controller)

public function edit(ServiceFall $serviceFall)
    {
        $this->authorize('admin.service-fall.edit', $serviceFall);

        return view('admin.service-fall.edit', [
            'serviceFall' => $serviceFall,
            'fall_status_options'=>$this->getServiceStatusOptions()
        ]);
    }

private function getServiceStatusOptions() {

    $options[] = array('id'=>'1','name'=>'Reperatur - Status 1');
    $options[] = array('id'=>'2','name'=>'Reperatur - Status 2');
    $options[] = array('id'=>'3','name'=>'Reperatur - Status 3');
    $options[] = array('id'=>'4','name'=>'Reperatur - Status 4');
    $options[] = array('id'=>'5','name'=>'Reperatur - Status 5');
    $options[] = array('id'=>'6','name'=>'Reperatur - Status 6');
    $options[] = array('id'=>'7','name'=>'Reperatur - Status 7');

    return $options;
}

so far this is allready working with my template: <multiselect v-model="form.ServiceStatus" :options="{{ json_encode($fall_status_options) }}" placeholder="Select Status" label="name" track-by="id" :multiple="false" :allow-empty="false"></multiselect>

i can also store the integer value in the database by doing this:

    public function update(UpdateServiceFall $request, ServiceFall $serviceFall)
    {

        $data = $request->validated();
        if (isset($data['ServiceStatus'])) {
          $data['ServiceStatus']=$data['ServiceStatus']['id'];
        }

        // Update changed values ServiceFall
        $serviceFall->update($data);

        if ($request->ajax()) {
            return [
                'redirect' => url('admin/service-falls'),
                'message' => trans('brackets/admin-ui::admin.operation.succeeded'),
            ];
        }

        return redirect('admin/service-falls');
    }

i tried like :value="1" for example, but that has no effect - what im doing wrong here ?

mzanier commented 1 year ago

i also tried now a different approach using relations for some simple static dropdown values

and basicly ended up with this approach:

    public function edit(ServiceFall $serviceFall)
    {
        $this->authorize('admin.service-fall.edit', $serviceFall);

        $serviceFall->load('ServiceStatus');

        return view('admin.service-fall.edit', [
            'serviceFall' => $serviceFall,
            'ServiceStatusList'=> ServiceStatus::getRows()
        ]);
    }

having a hasOne relationship to

  public function ServiceStatus(){
        return $this->hasOne(ServiceStatus::class,'id','service_status_id');
    }
class ServiceStatus extends Model
{
    use \Sushi\Sushi;

    static function getRows()
    {
        return [
            ['id' => 1, 'name' => 'admin 1'],
            ['id' => 2, 'name' => 'admin 2'],
            ['id' => 3, 'name' => 'admin 3'],
            ['id' => 4, 'name' => 'admin 4'],
            ['id' => 5, 'name' => 'admin 5'],
            ['id' => 6, 'name' => 'admin 6'],
            ['id' => 7, 'name' => 'admin 7'],
        ];
    }
}

and i also added the props etc to the forms.js

Vue.component('service-fall-form', {
    mixins: [AppForm],
    props: [
      'ServiceStatusList'
    ],
    data: function() {
        return {
            form: {
              ServiceShortDescription:  '' ,
               ServiceLongDescription:  '' ,
               service_status_id:  '' ,
               ServiceCreatedByUser:  '' ,

            },
            mediaCollections: ['gallery']
        }
    }
});

template:

{{ $serviceFall->ServiceStatus}}

<div class="form-group row align-items-center" :class="{'has-danger': errors.has('ServiceStatus'), 'has-success': fields.ServiceStatus && fields.ServiceStatus.valid }">
    <label for="roles" class="col-form-label text-md-right" :class="isFormLocalized ? 'col-md-4' : 'col-md-2'">{{ trans('admin.admin-user.columns.roles') }}</label>
    <div :class="isFormLocalized ? 'col-md-4' : 'col-md-9 col-xl-8'">
        <multiselect v-model="form.ServiceStatus" placeholder="{{ trans('brackets/admin-ui::admin.forms.select_options') }}" label="name" track-by="id" :options="{{ json_encode($ServiceStatusList) }}" :multiple="false" open-direction="bottom"></multiselect>
        <div v-if="errors.has('ServiceStatus')" class="form-control-feedback form-text" v-cloak>@{{ errors.first('ServiceStatus') }}</div>
    </div>
</div>

i see that ServiceStatus getting properly set by my load method to for example {"id":5,"name":"admin 5"} but still, its not selecting this value as default from the multiselect :/

image

timoransky commented 1 year ago

Hi @mzanier 👋

You can preselect multiselect by prefilling v-model value. In your code, if I understand correctly, you use v-model="form.ServiceStatus" for multiselect so something like this should work:

Vue.component('service-fall-form', {
    mixins: [AppForm],
    props: [
      'ServiceStatusList',
      'serviceFall'
    ],
    data: function() {
        return {
            form: {
               ServiceShortDescription:  '' ,
               ServiceLongDescription:  '' ,
               service_status_id:  '' ,
               ServiceCreatedByUser:  '' ,
               ServiceStatus: serviceFall.ServiceStatus.id
            },
            mediaCollections: ['gallery']
        }
    }
});

Notice I added serviceFall to props and added ServiceStatus to form attribute with a default value. Notice that serviceFall.ServiceStatus.id might not work out of the box, since I'm not familiar with your code that well, but the point is you can use whatever value you want, you can even pass it from controller.

Please let me know if this helped you or not 🤗