-
-
Notifications
You must be signed in to change notification settings - Fork 312
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Props tag remove props from the attribute list #1041
Props tag remove props from the attribute list #1041
Conversation
@weaverryan friendly ping here. I think we should merge a solution for this issue before the next release. Sorry about that 😔 |
This originates from https://github.com/symfony/ux/pull/255/files#diff-ad19b699a899e152e1619ea828ba39d72a419702a33769092f35f39d65c23073R75 - because any "extra" props become attributes, which need to be strings. The idea was to give a better error now than some "cannot be cast to a string" type of error when the attributes are rendered. Perhaps we could put some check into |
<div class='user-card'> | ||
<p>{{ user.name }}</p> | ||
<p>{{ user.email }}</p> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that props that were passed to anonymous components became attributes unless you used the {% props
tag. Did I misunderstand that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No the props tag only allow to set default value on attributes or to required attributes, but all props are at first an attribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that, if we added <div {{ attributes }}>
in this component, it would break because it would try to "print" the user
as an attribute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also misunderstood. I think this could make {{attributes}}
non-stringable like Ryan says(?)
I thought that props that were passed to anonymous components became attributes unless you used the {% props tag.
Feel like this should be the case as I don't think there's any other way to make the distinction.
$loader = $this->environment->getLoader(); | ||
$templateContent = $loader->getSourceContext($this->findAnonymousComponentTemplate($name))->getCode(); | ||
|
||
$pattern = '/{%\s*props\s*(.*?)\s*%}/'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm open for a better way extract the props from the template
Ok so here is how I trying to do this now: before mounting I extract the props defined in the component template, then when we mount the component, the component only takes as props the props defined in the tag, the rest goes to the attributes object. |
Thanks for this :). I have an idea - I'm wondering if it is feasible or not. What if: A) We move the check for scalar props into B) At this point, if I understand correctly, ALL props I've passed to my anonymous component will be inside
And, voila! As long as you have WDYT? |
3495d3e
to
7afeae9
Compare
@weaverryan I think I manage to implement your solution! Tell me what you think about it! 😁 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this! I do see one test failing
src/TwigComponent/tests/Fixtures/templates/anonymous_component_none_scalar_prop.html.twig
Outdated
Show resolved
Hide resolved
This reverts commit eb6e3a2.
0fa12a5
to
416c46a
Compare
Thanks for your review! Looks like the tests failing are related to the form changed but not this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last thing! I just tried it locally - it was simple and fun to play with.
@@ -35,6 +35,10 @@ public function __toString(): string | |||
function (string $carry, string $key) { | |||
$value = $this->attributes[$key]; | |||
|
|||
if (!\is_scalar($value) && null !== $value) { | |||
throw new \LogicException(sprintf('A "%s" prop was passed when creating the component. No matching %s property or mount() argument was found, so we attempted to use this as an HTML attribute. But, the value is not a scalar (it\'s a %s). Did you mean to pass this to your component or is there a typo on its name?', $key, $key, get_debug_type($value))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw new \LogicException(sprintf('A "%s" prop was passed when creating the component. No matching %s property or mount() argument was found, so we attempted to use this as an HTML attribute. But, the value is not a scalar (it\'s a %s). Did you mean to pass this to your component or is there a typo on its name?', $key, $key, get_debug_type($value))); | |
throw new \LogicException(sprintf('A "%s" prop was passed when creating the component. No matching "%s" property or mount() argument was found, so we attempted to use this as an HTML attribute. But, the value is not a scalar (it\'s a %s). Did you mean to pass this to your component or is there a typo on its name?', $key, $key, get_debug_type($value))); |
|
||
<div {{ attributes }}> | ||
<p>{{ user.name }}</p> | ||
<p>{{ user.email }}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add and test for this:
<p>class variable defined? {{ class is defined ? 'yes': 'no' }}
This is the last thing to fix. I just tested locally. Everything works great (user
is removed from attributes
, {% props
can be used to define defaults, etc) except that if something is NOT defined in {% props
(i.e. class
) is IT being made available as a variable, and it should not be. So, in the test, we want to assert that we see:
class variable defined? no
Friendly ping @WebMamba - I think that last tweak, relative to the work you've already done, is quite minor :) |
5bc7001
to
f6ac821
Compare
Sorry for the delay I am on holiday with all my family so I don't have a lot of time for coding! Here is a fix tell me what you think about it 😁 |
Sorry for the bother on holiday - but thank you for this! It looks great now! |
An assertion in ComponentFactory is blocking us to use non-scalar values for anonymous components. @weaverryan do you know why this check was made for?