CRUD: [4.1] Relationship field does not work inside repeatable

I’ve managed to get it to work in part using the Repeatable Relationship field. With the following attribute: ‘multiple’ => false, ‘data_source’ => url($this->crud->route.‘/fetch/person’),

I can add the data or register a new one in the table.

    //RELATIVE
         $this->crud->addField([
            'name'  => 'relation_relative',
            'label' => trans('contact.relative.data'),
            'type'  => 'repeatable',
            'tab'   => trans('contact.relative.tab'),
            'fields' => [
                [   'name' => 'id',
                    'type' => 'hidden',
                ],
                [   'name' => 'contact_id',
                    'type' => 'hidden',
                    'default'   =>  $this->crud->getCurrentEntryId(),
                ],        
           [
            'name'  => 'data1',
            'label' => trans('contact.relative.name'),
            'type'  => 'relationship',
            'wrapper'   => ['class' => 'form-group col-md-8'],           
            'entity'    => 'relatives.person',
            'data_source' => url($this->crud->route.'/fetch/person'),
            'attribute' => 'display_name',
            'model'     => 'App\Models\ContactPerson',
            'ajax' => false,
            'multiple' => false,
            'allows_null' => true,
            'inline_create' => ['entity' => 'contactperson'],             
            ],  
                [   'name'  => 'data2',
                    'label' => trans('contact.relative.type'),
                    'type'  => 'select_from_array',
                    'wrapper' => ['class' => 'form-group col-md-4'], 
                    'options' => ContentType::getTypeRelationRelatives(),
                ],
                [   'name'  => 'data3',
                    'label' => trans('contact.relative.label'),
                    'type'  => 'text',
                ],
            ],
        ]);
    public function fetchPerson()
    {        return $this->fetch('App\Models\ContactPerson');    }

image

The problem I have is that after saving and re-modifying, it doesn’t associate the value in the Relationship field.

image

Well if you know how to solve that part then it would be repeatable.

I share the way I found to intercept in the model and save in the related table. And the way to read it and convert to json. This can be added to the documentation.

class ContactFamily extends Model
{ 
   protected $table = 'contacts';
    public $timestamps = true;
    protected $guarded = ['id'];
    protected $fillable = ['display_name', 'civil_status', 'status', 
        'relation_parent', 'relation_spouse', 'relation_children', 'relation_relative', 'relation_other'];

    public function relatives()
    {
        $keys = array_keys(ContentType::getTypeRelationRelatives());
        return $this->hasMany('App\Models\ContactRelation','contact_id', 'id')
                        ->whereIn('data2', $keys);
    }
    public function getRelationRelativeAttribute() {
        $data = self::relatives()->get();
        return $data->toJson();
    }    

    public function setRelationRelativeAttribute($value) {
        $data = (json_decode($value, true)); //converts json into array
        $keys = self::relatives()->get()->modelKeys();
        //Insertar o actualizar registros en parent
        if(is_array($data)) {
            foreach ($data as $entry) {
                if (!empty($entry['data1'])) {
                    $id = (int) $entry['id'];
                    unset($entry['id']);
                    if (($key = array_search($id, $keys)) !== false) 
                        unset($keys[$key]);  
                    self::relatives()->updateOrCreate(['id' => $id], $entry);
                }
            }
        }
        //Eliminar registros en parent
        if(!empty($keys)) {
            foreach ($keys as $id) 
                self::relatives()->find($id)->delete();
        }    
    }    

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 17 (12 by maintainers)

Most upvoted comments

The problem with the Relationship field is resolved. What I did was upgrade the chrome browser from version 79 to 80

If you can verify what I say, it is possible that the Relationship field is not compatible with the following versions: chrome 79 firefox 66 internet explorer 11 Microsoft Edge 41 - EdgeHTML 16

As the PR #2763 is open and I think very close to be merged, let’s move any further conversation about this topic over there.

Thanks again @DanielKimmich , and sorry for making you go to the trouble of fixing this. I am very happy that you found a solution that works for you, but if the one we provided in the PR matches your expectations you could do a composer update as soon as the PR gets merged to have the latest code.

From my understanding, and what I told to @tabacitu is that relationship field in the context of a repeatable field, is only useful as a shortcut, a way to allow people write less code and have the fields displayed, because in reality we are not directly creating/editing any relation. That can be done after when you intercept the request, but does not matter if it’s a select2_from_ajax or a relationship with ajax, in request you get the selected value.

Wish you the best.

Pedro

Hey @tabacitu i did some dig around,

Couldn’t we make the function public instead of protected

https://github.com/Laravel-Backpack/CRUD/blob/400bb8827bb02fc8b6ad2d6502e3710afcb57936/src/app/Library/CrudPanel/Traits/FieldsProtectedMethods.php#L18

And add before the line:

https://github.com/Laravel-Backpack/CRUD/blob/400bb8827bb02fc8b6ad2d6502e3710afcb57936/src/resources/views/crud/fields/repeatable.blade.php#L30

$subfield = $crud->makeSureFieldHasNecessaryAttributes($subfield);

That way we could still write the fields exactly as in $crud->addField(), and expect the same guessing.

This would also work wonders for relationships, otherwise I think using relationships is a no go in repeatables, because some keys are needed beforehand like relation_type etc.

Do you see any inconvenience in this ?

Aftermath …

You referenced that repeatable strips the name from fields so I really think that making relationships work here is also an impossiblemazing job, we parse names for html etc, and that only makes sense because we are creating the relations, need validation etc.

In this scenario everything is stored in json, or handled by developer after submission so I think making relationships work here does not make much sense at all. I remember in our conversation we talked about this, and looking at it from some perspective it clearly does not worth the effort.

I think we should focus in making only fetch_and_create work in here because of the InlineCreate feature, for other scenarios you have the select2, select2_multiple, select2_from_ajax, select2_from_ajax_multiple.

Let me know how you think we should tackle this one.

On it 👍