-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Add x-model support if variable is not defined in x-data #3798
Conversation
Can you add a test for this? |
Of course, I updated the PR On the other hand, I think instead of producing new modifiers, it is better to add this feature to the basic implementation of the |
btw, in the meantime, you can just put all the props in an object instead. like on the x-data add a then This will basically work as expected or close to it I think part of this being attached to the There is already a pattern for how setting undefined things behaves, so tapping into that should work. |
@ekwoka Thanks for the idea. Exactly, the functionality is very similar, and this partially solves the problem. And the meaning of |
That could be argued is a breaking change. |
@ekwoka I test
|
@ekwoka Updated PR. I suggest then, instead of adding the new
Can write shorter:
|
let value = ''; | ||
if (el.type === 'checkbox' || el.type === 'radio') { | ||
const attribute = `x-model\\.${modifiers.join('\\.')}`, | ||
items = parent.querySelectorAll(`[${attribute}="${expression}"]`); |
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 pretty sure none of the stuff here needs to be done at all. Each element with x-model will initialize and do their own checks. You don't need to try to find them.
if (typeof expression === 'string') { | ||
let parent = el.closest('[x-data]'); | ||
if (parent) { | ||
let xData = Alpine.$data(parent); |
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.
You can just call $data
on the element directly. You don't need to find the root yourself.
let parent = el.closest('[x-data]'); | ||
if (parent) { | ||
let xData = Alpine.$data(parent); | ||
if (typeof xData[expression] === 'undefined') { |
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.
This will incorrectly trigger this branch if the model is an expression and not a literal key (ie. 'info.query')
Some follow up context, what is the reason you need all the info put into Alpine and not just use native form behaviors? In your example, just making a root a |
There are conditional logic in our form, and we would like to hide/show form elements by values of other fields. |
@ekwoka PR is updated |
However, I do not even know if it is possible to do something, if the property is called before its initialization in the "x-model", the problem with the E.g.:
|
true, or at least it would keep looking up the stack for it, the non the global. You could make a fancy proxy object to store the data in that just always returns null, allowing x-model.fill to work without changing any internals of alpine. I was more on the side that model.fill should work on undefined, just allowing a plain object to be used like that. In cases where we've needed behavior like you describe, we just have the few we care about defined on the x-data (with the initial values as well) to toggle them, or have the toggle happen with a request to the server to change the form element out. depending on the concerned behavior, etc. |
When using the x-model directive, if no variable is declared in x-data, this leads to an error
Uncaught ReferenceError: variable is not defined
. Therefore, the variable must be declared in the x-data directive.Problem
The complication of the html document.
Example
In one project we have a form containing more than a hundred fields. The HTML form looks like this:
If we want to fill the form with data, the html gets clogged up even more, the form takes on the appearance of:
However, in this implementation we have a problem with waiting. While JS finishes its work and the data is parse, the form "blinks". To solve this problem, we fill the form with data in the fields themselves. All this together bloats the HTML code and it becomes difficult to read.
The problem takes on magnitude when we are using huge data. For example, we repeat the text from the textarea in both the
x-data="{textarea: 'OH NO! very long text'}"
directive and in the<textarea x-model="textarea">OH NO! very long text</textarea>
tag itself. This is contrary to the DRY principle.Solution
I suggest adding an
auto
modifier that will automatically parse the parent x-data of the x-model element, and if it is not declared, will be added whenx-model.auto
is initialized. If the variable is not declared, x-model will try to get the value from the input, select or textarea element itself.HTML form will look neater. For example for testing:
I invite discussion on this realization. Thank you.