Closed Rocketpilot closed 7 months ago
Interesting use case. Ive got some ideas on how to make it work. I’ll kick it around and get back to you.
Figured out a simple work around for your issue. Just add a boolean :required that checks all the variables.
<label for="phone-personal">Personal Phone</label>
<input
type="phone"
id="phone-personal"
name="phone-personal"
:required="!($validate.value('phone-personal') || $validate.value('phone-cell') || $validate.value('phone-work'))"
/>
<label for="phone-cell">Cell Phone</label>
<input
type="phone"
id="phone-cell"
name="phone-cell"
:required="!($validate.value('phone-personal') || $validate.value('phone-cell') || $validate.value('phone-work'))"
/>
<label for="phone-work">Work Phone</label>
<input
type="phone"
id="phone-work"
name="phone-work"
:required="!($validate.value('phone-personal') || $validate.value('phone-cell') || $validate.value('phone-work'))"
/>
Thanks for that - I'll mull over it. I would say though, and this might well be beyond your plausible use-cases for the plugin, that one motivation for a built in approach is that for business security reasons we're required to avoid anything with unsafe-eval, so I'm migrating our so-far limited use of Alpine to the new Alpine-CSP build, which doesn't permit any inline javascript expressions.
Makes sense. My plugin does lean on inline js but it can work without it with some work arounds. You can instead use Alpine.bind(). You will need to also add an Alpine.data() for the form or somewhere higher up in the DOM, even if it returns an empty {}, since Alpine requires data somewhere for plugins to work.
I tested the following code and it works. Note in the Alpine.bind() the use of explicit function instead of an arrow function. You need to do it this way to can access magic variables like my $validate off of the this
<form x-data="form" x-validate>
<label for="phone-personal">Personal Phone</label>
<input
type="phone"
id="phone-personal"
name="phone-personal"
x-bind="phones"
/>
<label for="phone-cell">Cell Phone</label>
<input
type="phone"
id="phone-cell"
name="phone-cell"
x-bind="phones"
/>
<label for="phone-work">Work Phone</label>
<input
type="phone"
id="phone-work"
name="phone-work"
x-bind="phones"
/>
</form>
<script>
document.addEventListener("alpine:init", () => {
Alpine.data("form", () => {
return {};
});
Alpine.bind("phones", function () {
return {
":required"() {
return !(
this.$validate.value("phone-personal") ||
this.$validate.value("phone-cell") ||
this.$validate.value("phone-work")
);
},
};
});
});
</script>
This is a very clear explanation and in fact helps me understand a lot of weird stuff about Alpine that the official docs don't really help with. I think it might be useful for other people struggling, too. Thank you very much!
Yeah building a plugin definitely was a learning experience with Alpine. Maybe I should fire up my blog again and post about what I've learned regarding Alpine.
This might be a bit of an edge case, but I was wondering about a validation rule for the following pattern:
I guess this is an extension of x-validate.group. I don't think I can use the same name attribute for each input as the user may add more than one phone number.
It's sort of almost working but it's not picking up the provided error message from the div I've wrapped it in.