Repeater relationship returns null

So, I have an issue where my relationship can't be found by repeater in my custom page, I want it to display every 'pergunta' inside the table formulario but I can't find the solution , this is the error returned: Call to a member function cargoFormulario() on null here's the code:
class Perguntas extends Page implements HasForms
{
use InteractsWithForms;

protected static ?string $model = Pergunta::class;
class Perguntas extends Page implements HasForms
{
use InteractsWithForms;

protected static ?string $model = Pergunta::class;
now the forms:
return $form
->schema([
Repeater::make('cargoFormulario')

->relationship()
->schema([
TextInput::make('texto')
])
]);
return $form
->schema([
Repeater::make('cargoFormulario')

->relationship()
->schema([
TextInput::make('texto')
])
]);
my model:
class Pergunta extends Model
{
protected $table = 'formularios';
protected $guarded = ['id'];
use HasFactory;

public function cargoFormulario()
{
$this->hasMany(CargoFormulario::class, 'id', 'formulario_id');
}
}
class Pergunta extends Model
{
protected $table = 'formularios';
protected $guarded = ['id'];
use HasFactory;

public function cargoFormulario()
{
$this->hasMany(CargoFormulario::class, 'id', 'formulario_id');
}
}
Only to give you guys more context about what I'm doing, a 'cargo' has many 'formulario' and a 'formulario' has many 'cargo'.
Solution:
you can also do: $form->model($this->record) then...
Jump to solution
45 Replies
hosmar27
hosmar27OP5mo ago
The custom page doesn't have a resource and I created that model ('Pergunta') after creating this page, its basically the name of the page I have models for 'Formulario', 'Cargo' and 'CargoFormulario' , if needed I can post it here
Dennis Koch
Dennis Koch5mo ago
You need to pass your record to the form $form->record($yourRecord)
hosmar27
hosmar27OP5mo ago
couldn't solve it, it returns this error 'Undefined variable $record' I've created a new custom page on a resource my code is able to pass the id in the url, but I can't get any data on form, this is how I did:
->url(fn (Cargo $record): string => route('filament.admin.resources.cargos.form', ['record' => $record]))
->url(fn (Cargo $record): string => route('filament.admin.resources.cargos.form', ['record' => $record]))
toeknee
toeknee5mo ago
That is because it is a create repeater record doesn't exist, I think you want the parent record so $livewire then $livewire->owner_record
hosmar27
hosmar27OP5mo ago
I'll try it I did some progress and could get $record filled with the selected array that I wanted, now I just need to fill the forms with it i've tried to use this in many ways but couldn't do it here's my current code:
class FormCargo extends Resource implements HasForms
{
use InteractsWithForms;
use InteractsWithRecord;

protected static string $resource = CargoResource::class;

protected static string $view = 'filament.resources.cargo-resource.pages.form-cargo';

public ?array $data = [];

public function mount(Cargo $record): void
{
dd($record);
// $this->form = $record;
}

public static function form(Form $form): Form
{
return $form
->schema([
Repeater::make('formularios')
->schema([
TextInput::make('id')
->label(function (Cargo $record): array
{
dd($record);
})
])
->statePath('data')
]);
}

public function fill($record)
{
// dd($record);
// return $record;
}
class FormCargo extends Resource implements HasForms
{
use InteractsWithForms;
use InteractsWithRecord;

protected static string $resource = CargoResource::class;

protected static string $view = 'filament.resources.cargo-resource.pages.form-cargo';

public ?array $data = [];

public function mount(Cargo $record): void
{
dd($record);
// $this->form = $record;
}

public static function form(Form $form): Form
{
return $form
->schema([
Repeater::make('formularios')
->schema([
TextInput::make('id')
->label(function (Cargo $record): array
{
dd($record);
})
])
->statePath('data')
]);
}

public function fill($record)
{
// dd($record);
// return $record;
}
the 'dd($record)' in function mount returns the correct array, just need to find a way to send the description to the TextInput label inside the Repeater I want to make a quiz by the way
toeknee
toeknee5mo ago
I am not seeing a text input in the repeater? But if you added one... you would just do: $set('my_text_input', 'value')
hosmar27
hosmar27OP5mo ago
No description
hosmar27
hosmar27OP5mo ago
I'm getting this error: Argument #1 ($record) must be of type App\Models\Cargo, null given
->schema([
Repeater::make('formularios')
->schema([
TextInput::make('id')
->label(function (Cargo $record): ?array
{
dd($record);
})
])
])
->statePath('data');
->schema([
Repeater::make('formularios')
->schema([
TextInput::make('id')
->label(function (Cargo $record): ?array
{
dd($record);
})
])
])
->statePath('data');
toeknee
toeknee5mo ago
You will if record is null.... you specificed you expect Cargo so remove Cargo from it and then you can check if it's null
hosmar27
hosmar27OP5mo ago
ok, did it and there was no error, but $record returned null in dd($record)
toeknee
toeknee5mo ago
It will return null because no record exists?
hosmar27
hosmar27OP5mo ago
yes, but I'm able to get the $record in function mount, I don't know how to send it to form here, the dd returns the correct $record
toeknee
toeknee5mo ago
public $record; in mount: $this->record = $record;
hosmar27
hosmar27OP5mo ago
I think I did not explain it really well, I'm already receiving $record in mount, but I am not receiving it in my form
toeknee
toeknee5mo ago
You are receiving it, but you are not setting it for your form to use it. I have told you above how to set it...
hosmar27
hosmar27OP5mo ago
ok, sorry
Solution
toeknee
toeknee5mo ago
you can also do: $form->model($this->record) then
hosmar27
hosmar27OP5mo ago
it worked, I'll try the rest by miself but if I have anymore problems I'll ask here
hosmar27
hosmar27OP4mo ago
Unfortunetly I'm still not able to get my repeater to work in this custom page, I created a select for testing purpouses (I'm not going to use it) and it worked, so I have no ideia where the problem is here's my current code:
class FormCargo extends Page implements HasForms
{
use InteractsWithForms;
// use InteractsWithRecord;

protected static string $resource = CargoResource::class;

protected static string $view = 'filament.resources.cargo-resource.pages.form-cargo';

public ?array $data = [];

public Cargo $record;

public function mount(Cargo $record)
{
$this->record = $record;
}

public function form(Form $form): Form
{
$form->model($this->record);

return $form
->schema([
// Select::make('select')
// ->relationship('cargoPergunta', 'cargo_id'),
Repeater::make('cargoFormularios')
->label('')
// ->disabled()
->relationship()
->schema([
TextInput::make('id')
->label(function ($record)
{
dd($record);
})
])
->deletable(false)
->reorderable(false)
])
->model($this->record)
->statePath('data');
}

public function fill($record): array
{
dd($record);
return $record;
}
class FormCargo extends Page implements HasForms
{
use InteractsWithForms;
// use InteractsWithRecord;

protected static string $resource = CargoResource::class;

protected static string $view = 'filament.resources.cargo-resource.pages.form-cargo';

public ?array $data = [];

public Cargo $record;

public function mount(Cargo $record)
{
$this->record = $record;
}

public function form(Form $form): Form
{
$form->model($this->record);

return $form
->schema([
// Select::make('select')
// ->relationship('cargoPergunta', 'cargo_id'),
Repeater::make('cargoFormularios')
->label('')
// ->disabled()
->relationship()
->schema([
TextInput::make('id')
->label(function ($record)
{
dd($record);
})
])
->deletable(false)
->reorderable(false)
])
->model($this->record)
->statePath('data');
}

public function fill($record): array
{
dd($record);
return $record;
}
my Cargo model:
public function formularios(): BelongsToMany
{
return $this->belongsToMany(Formulario::class,'cargo_formulario')->withTimestamps()->where('perguntas', true)->where('ativo',1);
}

public function cargoFormularios(): HasMany
{
return $this->hasMany(CargoFormulario::class, 'cargo_id', 'id');
}
public function formularios(): BelongsToMany
{
return $this->belongsToMany(Formulario::class,'cargo_formulario')->withTimestamps()->where('perguntas', true)->where('ativo',1);
}

public function cargoFormularios(): HasMany
{
return $this->hasMany(CargoFormulario::class, 'cargo_id', 'id');
}
my CargoFormulario model:
public function cargo(): BelongsTo
{
return $this->belongsTo(Cargo::class)->where('ativo', true);
}

public function formulario(): BelongsTo
{
return $this->belongsTo(Formulario::class)->where('ativo', true);
}
public function cargo(): BelongsTo
{
return $this->belongsTo(Cargo::class)->where('ativo', true);
}

public function formulario(): BelongsTo
{
return $this->belongsTo(Formulario::class)->where('ativo', true);
}
my Formulario model:
public function cargo(): BelongsToMany
{
return $this->belongsToMany(Cargo::class,'cargo_formulario')->withTimestamps()->where('ativo',1);
}

public function cargoFormularios(): HasMany
{
return $this->hasMany(CargoFormulario::class);
}
public function cargo(): BelongsToMany
{
return $this->belongsToMany(Cargo::class,'cargo_formulario')->withTimestamps()->where('ativo',1);
}

public function cargoFormularios(): HasMany
{
return $this->hasMany(CargoFormulario::class);
}
@toeknee can you help me?
toeknee
toeknee4mo ago
Do not tag as per #✅┊rules ->relationship() should be: ->relationship('cargoFormularios', 'cargo_id')
hosmar27
hosmar27OP4mo ago
sorry i forgot about it, it returned this error: Filament\Forms\Components\Repeater::relationship(): Argument #2 ($modifyQueryUsing) must be of type ?Closure, string given
Dennis Koch
Dennis Koch4mo ago
Do not tag as per ⁠✅┊rules
Isn't it the same as answering to your previous message in that case? 😅
TextInput::make('id')
It doesn't really make sense to edit the id in a repeater does it?
hosmar27
hosmar27OP4mo ago
I just use it for testing
toeknee
toeknee4mo ago
change to: ->relationship('cargoFormularios')
hosmar27
hosmar27OP4mo ago
I want to get the 'formularios.pergunta' there was no error but dd($record) returned null sorry, I made a mistake, I want the formularios.pergunta to be shown in the label of text input
toeknee
toeknee4mo ago
right so use formularios in the relationship and pergunta in the repeat textInput
hosmar27
hosmar27OP4mo ago
it's a belongsToMany relationship, so the repeater has to have a relationship with the pivot, according to the documentation
hosmar27
hosmar27OP4mo ago
yes. I'm using 'cargoFormularios' instead of 'formularios' because of that
Dennis Koch
Dennis Koch4mo ago
Ah, sorry was confused because of the last messages. And CargoFormulario is a Pivot model?
hosmar27
hosmar27OP4mo ago
Yes it is
Dennis Koch
Dennis Koch4mo ago
I lost track: What is the current issue you are facing? You no longer have the called X on null error, right?
hosmar27
hosmar27OP4mo ago
actualy the error is inside the textinput, the dd($record) returns null, but if I use dd in mount() it returns the correct array from Cargo , but i want to get the data inside Formulario, more specificly the 'pergunta' column
hosmar27
hosmar27OP4mo ago
btw my repeater does not show anything to, like, i have to click the button for the textInput to show up
No description
No description
hosmar27
hosmar27OP4mo ago
I think it's important to add again that I'm using a custom page inside CargoResource
Dennis Koch
Dennis Koch4mo ago
the dd($record) returns null
Makes sense since $record refers to the Repeater record then and you haven't saved anything yet?
btw my repeater does not show anything to, like, i have to click the button for the textInput to show up
Does you model have any records linked?
hosmar27
hosmar27OP4mo ago
if I comment the ->relationship it gets the data from Cargo, since it's public, you can see it in the 13 line here but if the ->relationship is in the code, it shows nothing not the CargoFormulario model, only Cargo model, but I have data in cargo_formulario table
Dennis Koch
Dennis Koch4mo ago
Yes. $record refers to the current repeater record which is still null I think you can get the original record via: $livewire->record
hosmar27
hosmar27OP4mo ago
ok, but where should I use it? 😅 sorry, filament is actually my first backend language, so it's harder for me to solve some simple things
public function form(Form $form): Form
{
$form->model($this->record);

return $form
->schema([
// Select::make('select')
// ->relationship('cargoPergunta', 'cargo_id'),
Repeater::make('cargoFormularios')
->label('')
// ->disabled()
->relationship('cargoFormularios')
->schema([
TextInput::make('id')
->label(function ($record)
{
dd($record);
})
])
->deletable(false)
->reorderable(false)
])
->model($this->record)
->statePath('data');
}
public function form(Form $form): Form
{
$form->model($this->record);

return $form
->schema([
// Select::make('select')
// ->relationship('cargoPergunta', 'cargo_id'),
Repeater::make('cargoFormularios')
->label('')
// ->disabled()
->relationship('cargoFormularios')
->schema([
TextInput::make('id')
->label(function ($record)
{
dd($record);
})
])
->deletable(false)
->reorderable(false)
])
->model($this->record)
->statePath('data');
}
Dennis Koch
Dennis Koch4mo ago
ok, but where should I use it?
What's the goal? Something like this? ->label(fn ($livewire) => $livewire->record->id)
hosmar27
hosmar27OP4mo ago
something like it, but from Formulario, like ->label(fn ($livewire) => $livewire->record->formularios.pergunta) or just ->pergunta but for that I would need to have the data from formulario where formulario_id from CargoFormulario is = to id from Formulario, same for cargo_id and id from cargo is it possible?
Dennis Koch
Dennis Koch4mo ago
Sounds like what you actually want is a Select field inside the repeater:
Select::make('formulario_id')
->relationship('formulario', 'pergunta')
Select::make('formulario_id')
->relationship('formulario', 'pergunta')
Like the example in the docs: https://filamentphp.com/docs/3.x/forms/fields/repeater#integrating-with-a-belongstomany-eloquent-relationship
hosmar27
hosmar27OP4mo ago
it can't be, I want to make something like a quiz, 'pergunta' translated to english is 'question' and 'Formulario' is 'Quiz' so the repeater will display the question in the TextInput's label, and the user will be able to answer and save in another table
Dennis Koch
Dennis Koch4mo ago
Sorry, but it really sounds like this is a bit too much nesting inside the repeater
hosmar27
hosmar27OP4mo ago
I think the same, I'll try to think about something diferent, thanks for your time and help
Want results from more Discord servers?
Add your server