Rendering Custom Output in a Repeater Item
I'm using a Repeater with a custom action which opens a modal dialog. This process collections a large amount of information, some to be displayed, some not. It's unlikely going to match the object it will be saved into, so I will be manipulating it. I intend to show a structured rendered view of some of the output.
The data is available in an array in the action method:
https://gist.github.com/martinedge/6331a0404c49ed7b2989151ca0e15bbe
At the moment I'm using StateUpdated to move the 'processed_message' to info_message' which is a 'PlaceHolder'.
The attached picture gives you an idea of what I'm looking to achieve. Not sure if a blade can be injected or what the best approach is. Cheers!
61 Replies
But yes, best preference is to be able to inject a fresh blade or refresh the rendering of a blade that represents the repeater item during an OnChangeState javascript call. Do we know if this is possible?
I also tried using new HtmlString() to see if it would bring it in without converting the HTML to text, but alas no luck
(Bump) I will also post this on laravel daily to see if I have any luck, happy to chase the answer myself if someone even has an inkling on how to address this
I'm going to try and create a custom component or field and see if that will give me a bit more control
Maybe you could do it with a View or ViewField.
Yeah, that's what I'm looking at at the moment. I'll have to follow those instructions more carefully, because getContent() is expecting a string, which is created by using evaluate on a Closure, which implicitly calls htmlspecialchars() somewhere
View field would be better because it has ViewData components, which means I could properly layout the blade outcome as it needs to be
it's just a matter of making sure that the State changed attempt to update the ViewData (rather than just hitting the field with a single value) updates each of those individual items
It will be nice to nail this one this morning, as my list of "i have no idea how"'s is getting smaller, and this is a biggun!
Just so I understand correctly are you trying to render the custom view inside each repeater item or does the repeater itself determine the view of a single element.
the first one
I'm trying to render the contents of an item
all variables presently being populated are in there as hidden fields, but I could also populate the payload of the custom field
just not sure how you go about that with Set
because $set("myField", "blah"); obviously wouldn't address the individual ViewData components
so for example, if I did
ViewField::make('myField')->view('theview')->viewData(['phone' => 'myphone', 'access_fee' => 90.00]);
how would the $set be constructed to set each portion
or is it the same way
Yea. I’m seeing similar issues where repeater actions don’t have a context to what repeater item they are in.
$set("myField", ["phone" => 'myphone']);
oh, I figured that bit out that's fine
For that I've just created 'myCustomRepeater' which extends 'Repeater' and created an 'editAction' which essentially follows the same behaviour as the deleteAction
so if you look at https://internal-development.asmorphic.com/ - you can add as many repeater items as you want, hit the 'edit' and it will populate the correct one each time
It does mean it's not a reusable 'Repeater' as such (generically) - but that's fine if I'm say building a 'reusable Contact card' which invokes a modal with custom forms geared towards that
God I hate how Debugbar affects the layout. 😂
haha totally =]
Especially on my phone.
Ok, so you need the data from the slideOver passed back to the repeater item.
yeah which it does
eg;
$arguments["item"] is the uuid
so its then a matter of what the ViewField requires to address its internal components
Sorry, trying to think through it all. Having trouble making all the connections in my head with the shared code.
OK, I'll explain it a bit more - and at worse I can get the code somewhere visible
It’s should a simple enough. I’m just getting lost in all the arrays. Lol.
hahah
so $component is the repeater in itself, which comprises of all items
And discord mobile doesn’t syntax highlight
the item, is passed into the repeaters action method via $arguments
->action(function (array $arguments, array $data, AgilitySignupRepeater $component, Set $set, Get $get): void {
$items = $component->getState();
$items[$arguments["item"]]["imei_field"] = $data["imei_field"] ?? null;
})
that then automatically populates the imei_field here:
AgilitySignupRepeater::make('services')
->relationship() // what is this for?
->schema([
Hidden::make("imei_field"),
...
(ignore the what is this here for, we've moved past that haha)
Nice comment
That's before I knew make('services') <-- that services takes the place of the relationship name
oh and I should have mentioned, I also populate the item when filling the modal with:
So we have the full circle, it's just a matter of now defining this 'ViewField' with a custom view blade, and being able to receive the contents of ViewData items individually, and being able to use them in the view
and wallah, we have the ability to do 'whatever we want'
the docco on how to set ViewData items is a little vague tho
as in set via Set $set
I think you might be able to use $get() in the blade view.
Yep, but it will get it from the core form, the core form payload is what needs updating via the modal action()
Might need the statePath too though since it’s in a repeater.
yah, so really the main thing to figure out in the modal action, is if this will work:
$set('myViewField', ['variable1' => $data['variable1'], 'variable2' => $data['variable2']]);
Forms\Components\ViewField::make('testVariable')->view('forms.components.custom-output')->viewData(["testVariable" => "myInitialValue"]) <-- to set 'testVariable' via Set $set
I think the problem here is that you have two form contexts.
sorta, but they aren't really connected as such, because I'm dehydrating the contents out to an array and that's being passed back to the other form
Try injecting $livewire in you action. Then you can use the raw data_get and data_set on the main form from the action.
OK, so like this: ->action(function (array $arguments, array $data, Livewire $livewire, AgilitySignupRepeater $component, Set $set, Get $get): void {
I think it’s Component $livewire
ah yes I did see that somewhere
hm, that doesn't have any methods about raw or data
thats' from Livewire\Livewire\Component tho
What I’m getting at is that your action has a form, but you also have the main form where your repeater is. So I’m not totally sure $get and $set are going to work that way.
yeah, I do have another alternative to that, so I believe in this case the scope of $get and $set in the action is the repeater item
(the modal)
but
It’s no on the livewire instance
It’d be like data_set($livewire, statePath, value)
if I have the values populated in the array - I can use:
where the scope is the item itself
OK, hopefully dd will show me what it sees (as I still to-date haven't used dd())
I usually use ray() so it doesn’t halt the execution unless I need it to.
I'm sure he totally appreciates being used like that =]
OK, well, let me go and try all of those variants and I'll see what I come up with, happy to share the code with you (at least) when I'm (hopefully) done so you can bag me out on my hackery
No worries. I’m off all week so if you’d like to share anything I’m happy to help. Just let me know. I think this is an interesting problem. And could even have some insight / value to core.
Of course I feel like I’m relearning livewire since v3 came out.
Absolutely! will do. I would be more than chuffed if I can make something clean of the solution so it's useful to the core as well
Oh, see, I have the luxury of essentially being a laravel/filament/livewire virgin
Free of charge too. I’m not after a consultancy fee or anything like that.
My last MVC/ORM I was working with for 15 years we built ourselves, but that was an "attempt" at framework
that's awesome! thankyou 🙂 I'll keep you posted
But the beers will be on me if I solve all of this (c:
Helped out someone else today with their plugin. It was fun. Also challenging to figure it out since it wasn’t typical use case.
Sounds good.
I bet it's interesting to see just how others can twist things to get a square peg in a round hole
Feel free to add me to the repo if you need to. I have no problem being removed when it’s figured out.
Cool, will do, is your github user the same as your user here?
That’s every one of my plugins and probably why I’m even on the team. Lol.
Yes. awcodes
haha "Its easier just to have him as one of us"
Just helps me to see how everything is working together. I’m good at debugging and working through it but definitely helps to have a more holistic view of the situation.
easy - just have to import it - it's in bitbucket atm
Sounds good though. Have a good one. Talk soon.
Cheers - you too!
OK - getting somewhere now I put my old XDebug tools back in place.
To Modal:
From Modal:
It's still running htmlspecialchars over it, so I'll have to figure out why that's the case, but I'm at least able to access the values and modify them. I have also noticed it appears to revert itself.
Up initial submit (see attached)
a short time later:
So there is likely still a point of reference with the older stale data I will need to hunt down. I don't see why it would be re-addressing the form schema and resetting everything.
The mostly final outcome (some tidying to do, but it works.) - thanks to @awcodes !
hey, sorry to bump up this, are you using the default repeater in this image? or custom?
cant find a way to add action to the default one
It’s a custom repeater.
Only thing that would really benefit here is if the entire viewData payload was a Closure not just each fields value. Code would be a lot cleaner and scalable.