13
13
14
14
use Symfony \Component \EventDispatcher \EventSubscriberInterface ;
15
15
use Symfony \Component \PropertyAccess \PropertyAccessorInterface ;
16
+ use Symfony \UX \LiveComponent \Attribute \AsLiveComponent ;
16
17
use Symfony \UX \LiveComponent \Util \ModelBindingParser ;
17
18
use Symfony \UX \TwigComponent \ComponentStack ;
18
19
use Symfony \UX \TwigComponent \Event \PreMountEvent ;
20
+ use Symfony \UX \TwigComponent \MountedComponent ;
19
21
20
22
/**
21
23
* Parses the "data-model" key, which triggers extra props to be passed in.
@@ -54,8 +56,9 @@ public function onPreMount(PreMountEvent $event): void
54
56
unset($ data ['dataModel ' ]);
55
57
$ data ['data-model ' ] = $ dataModel ;
56
58
57
- // the parent is still listed as the "current" component at this point
58
- $ parentMountedComponent = $ this ->componentStack ->getCurrentComponent ();
59
+ // find the first parent of the component about to be rendered that is a Live Component
60
+ // only those can have properties controlled via the data-model attribute
61
+ $ parentMountedComponent = $ this ->getCurrentLiveComponent ($ this ->componentStack );
59
62
if (null === $ parentMountedComponent ) {
60
63
throw new \LogicException ('You can only pass "data-model" when rendering a component when you \'re rendering inside of a parent component. ' );
61
64
}
@@ -76,4 +79,20 @@ public static function getSubscribedEvents(): array
76
79
PreMountEvent::class => 'onPreMount ' ,
77
80
];
78
81
}
82
+
83
+ private function getCurrentLiveComponent (ComponentStack $ componentStack ): ?MountedComponent
84
+ {
85
+ foreach ($ componentStack as $ mountedComponent ) {
86
+ if ($ this ->isLiveComponent ($ mountedComponent ->getComponent ()::class)) {
87
+ return $ mountedComponent ;
88
+ }
89
+ }
90
+
91
+ return null ;
92
+ }
93
+
94
+ private function isLiveComponent (string $ classname ): bool
95
+ {
96
+ return [] !== (new \ReflectionClass ($ classname ))->getAttributes (AsLiveComponent::class);
97
+ }
79
98
}
0 commit comments