F
Filament8mo ago
Mdk

Including a relationship form from a different Resource doesn't display repeater items in it

I'm trying to cut down on my duplicated code, so inside a OrderResource I created this method
public static function getProductsForm()
{
return [
Forms\Components\Repeater::make('orderProducts')
->relationship('orderProducts')
->schema([
Forms\Components\Select::make('product_id')
->relationship('product', 'name',
modifyQueryUsing: fn (Builder $query) => $query->enabled())
->live()
->searchable()
->preload()
[....]
]),
Forms\Components\TextInput::make('discount')
->numeric()
->rules(['regex:/^\d{1,6}(\.\d{0,2})?$/'])
->minValue(0)
->suffix('€'),
Forms\Components\TextInput::make('total')
->label('Total')
->disabled()
->readOnly()
->dehydrated(false)
];
}
public static function getProductsForm()
{
return [
Forms\Components\Repeater::make('orderProducts')
->relationship('orderProducts')
->schema([
Forms\Components\Select::make('product_id')
->relationship('product', 'name',
modifyQueryUsing: fn (Builder $query) => $query->enabled())
->live()
->searchable()
->preload()
[....]
]),
Forms\Components\TextInput::make('discount')
->numeric()
->rules(['regex:/^\d{1,6}(\.\d{0,2})?$/'])
->minValue(0)
->suffix('€'),
Forms\Components\TextInput::make('total')
->label('Total')
->disabled()
->readOnly()
->dehydrated(false)
];
}
Calling it from the OrderResource itself works fine, but now I'm also adding it to a different resource, ShipmentResource
Forms\Components\Section::make()
->heading(__('Order informations'))
->relationship('order')
->headerActions([
Forms\Components\Actions\Action::make('openShipment')
->label(__('View Order'))
->url(fn($record) => OrderResource::getUrl('edit', ['record' => $record->order->id]))
])
->schema([
Forms\Components\Group::make()
->columnSpanFull()
->columns(2)
->schema(OrderResource::getOrderForm()),
Forms\Components\Group::make()
->columnSpanFull()
->columns(2)
->schema(OrderResource::getProductsForm())
]),
Forms\Components\Section::make()
->heading(__('Order informations'))
->relationship('order')
->headerActions([
Forms\Components\Actions\Action::make('openShipment')
->label(__('View Order'))
->url(fn($record) => OrderResource::getUrl('edit', ['record' => $record->order->id]))
])
->schema([
Forms\Components\Group::make()
->columnSpanFull()
->columns(2)
->schema(OrderResource::getOrderForm()),
Forms\Components\Group::make()
->columnSpanFull()
->columns(2)
->schema(OrderResource::getProductsForm())
]),
Thing is, the order details are displayed fine, the discount and total as well, but the repeater is not showing at all (unless I make it non-disabled, then the add button appears)
29 Replies
Mdk
MdkOP8mo ago
it seemed to work earlier, when the code for both getOrderForm and getProductsForm was merged into a single method, but I'd like to keep them separated for better modularity
Andrew Wallo
Andrew Wallo8mo ago
And they are utilizing the same resource model? What exactly isn’t working? Like are you getting an error or what? I would trying utilizing a Trait instead and see if it works.
Mdk
MdkOP8mo ago
empty repeater, as if the relationship doesn't return any item but if i open the order page, the items are correctly shown how could i turn that into a trait? if i try removing any of the ->relationship() parts, I do get an error about a non-existant relation
Andrew Wallo
Andrew Wallo8mo ago
Just put the methods such as getOrderForm(), etc inside a Trait and inside your resource utilize the Trait.
Mdk
MdkOP8mo ago
so it IS reading the relationship chain correctly, but then fails to read the items ah so you're saying i should use the trait in both resources then instead of reading from the other one
Andrew Wallo
Andrew Wallo8mo ago
Yes definitely better to do that Also you have an “order” relationship defined on the Shipment resource on the layout component. Is that being chained to your repeater?
Mdk
MdkOP8mo ago
uh... i guess not? how do I do that? i thought that nest the included form in a group that has the order relation would've worked since the discount and total are shown correctly
Andrew Wallo
Andrew Wallo8mo ago
What is the order relationship being used for though? It’s not really clear how it’s being used..
Mdk
MdkOP8mo ago
ah, i'm sorry
Andrew Wallo
Andrew Wallo8mo ago
Try removing the order relationship and see if the repeater shows.
Mdk
MdkOP8mo ago
order has orderProducts (which is a pivot table for products included), shipment has order_id to join it does not, as it tries to load orderProduct on the shipment itself but it's a method of Order
Andrew Wallo
Andrew Wallo8mo ago
Alright well idk how I can help you here. It’s hard to tell, but I would still suggest using a trait instead either way.
Mdk
MdkOP8mo ago
i'm trying to refactor into that right now VPS ain't cooperating it's weird tho, cause it worked when getOrderForm contained both sections (order + products)
Andrew Wallo
Andrew Wallo8mo ago
Make the methods non-static in your trait as well.
Mdk
MdkOP8mo ago
trait didn't fix nor break it let me try unstaticing wait, how do i call them from a static method if they're not static themselves?
Andrew Wallo
Andrew Wallo8mo ago
Use Livewire $livewire in closure.
Mdk
MdkOP8mo ago
thanks, let me try
Andrew Wallo
Andrew Wallo8mo ago
Honestly the static non-static thing may not be the issue but it’s worth a try. Your issue could just be some small mistake you made, but that’s all I can really help you with here.
Mdk
MdkOP8mo ago
yep, that didn't help but thanks
Andrew Wallo
Andrew Wallo8mo ago
Sorry. Better to keep the methods in a trait either way though.
Mdk
MdkOP8mo ago
yup, but i'll switch back to static just for simplicity funny thing, i tried adding a random dump just to see where I'd get ->collapsed(fn($operation,$record) => dump($record)/*$operation === 'edit'*/) the dump does show in the order page, doesn't show in the shipment so it's like.. it's not loading it at all? or is it just cause there are no items so that collapsed function doesn't get called?
->afterStateUpdated(function ($state, $set, $record) {

$product = Product::find($state);

$set('name', $product->name);

$set('price', $product->price);

$record->calculateTotal();

})
->afterStateUpdated(function ($state, $set, $record) {

$product = Product::find($state);

$set('name', $product->name);

$set('price', $product->price);

$record->calculateTotal();

})
i'm getting a "Call to a member function calculateTotal() on null" there when adding an item so yeah, $record isn't getting a value which is weird, as it should be the order itself but the order fields are correctly shown even putting the whole code straight into the form of shipment doesn't work maybe it's some bug with the repeater?
Andrew Wallo
Andrew Wallo8mo ago
And both resources are using the same model?
Mdk
MdkOP8mo ago
no, orderResource uses Order, shipmentResource uses Shipment
Andrew Wallo
Andrew Wallo8mo ago
Well then maybe that’s why.
Mdk
MdkOP8mo ago
but that's also why I added ->relationship('order') to the group i thought that made it load the order relation and worked with that just a little later on I've got this, and it works
Forms\Components\Group::make()
->relationship('order')
->schema([
Forms\Components\Section::make('Shipping address')
->relationship('customer')
->schema(CustomerResource::getFormContent()),
])
Forms\Components\Group::make()
->relationship('order')
->schema([
Forms\Components\Section::make('Shipping address')
->relationship('customer')
->schema(CustomerResource::getFormContent()),
])
Andrew Wallo
Andrew Wallo8mo ago
$record is always relative to the model on the resource, not a relationship.
Mdk
MdkOP8mo ago
oh well, that sure changes thing then again, i'm only using $record for debugging purposes there
Andrew Wallo
Andrew Wallo8mo ago
Idk what to tell you man. Just based on the fact that they are using different models, attributes, etc. would suggest to me to keep them separated. Duplicated code is sometimes necessary
Mdk
MdkOP8mo ago
well, even duplicating isn't fixing it now that repeater just wants to stay empty tell you what, since the user isn't even supposed to edit order stuff from the shipment page, i'll just make a method on the Order model to generate an HTML recap of those products ok, this is gonna WOW you ->content(fn($record) => $record->getProductsList()), apparently, when you're inside a group with a relation, $record is indeed the related model and not the original one ($record there being Order::class instead of Shipment::class) i'm getting all sort of weirdness when it comes to including relationship stuff Case in question: Shipment -> belongsTo(Order) -> belongsTo(Customer)
Forms\Components\Group::make()
->relationship('order')
->schema([
Forms\Components\Section::make('Shipping address')
->relationship('customer')
->schema(
CustomerResource::getFormContent()
),
])
Forms\Components\Group::make()
->relationship('order')
->schema([
Forms\Components\Section::make('Shipping address')
->relationship('customer')
->schema(
CustomerResource::getFormContent()
),
])
this works and displays every field perfectly wait, nevermind, i'm the idiot in this case forgot to go down yet another relationship
Want results from more Discord servers?
Add your server