Closed TomS- closed 4 years ago
Noticed @pfrlv responded with a confused emoji. Here is Vue's implementation - https://vuejs.org/v2/guide/computed.html#ad
Yeah, I could see the use for this. I'd probably rather do it like Vue does:
this.$watch('activeSlide', funcion(value) {...})
Thinking this doesn't need to be a directive though right? (x-watch
)
@calebporzio correct me if I'm wrong, but wouldn't this rely on taking the function approach (https://github.com/alpinejs/alpine#x-data)? I don't see any harm in that, it could be seen as advanced functionality. I just thought x-watch
or x-computed
would keep the inline/TailwindCSS nature.
@TomS-
I like the idea of having a x-watch
but only allowed on the same tag where you define x-data (like x-init
does).
I'm not sure if we need 'x-computed, though.
Wouldn't it be the same as calling a function directly when you use the variable? (https://codepen.io/SimoTod/pen/RwNBeJr)
@SimoTod I also don't believe we need x-computed for this and I do believe it would be called where you define x-data
I'm just unsure of the syntax but I was thinking for example: x-data="activeText: 'Hello'" x-watch="{ activeText: function(value) { this.$refs.text.innerText = value } }"
so you can later define @click="activeText = 'Goodbye'"
and it will auto-update the text refs innerText.
EDIT: To avoid confusion I know you can use x-text, this will be used for more advanced stuff that needs to be reactive to variable updates. Such as a slider and keeping track of the active slide in my OP.
@TomS-
Yeah, I got that. In my opinion, to keep it consistent with the core, it should be something like x-watch="{ activeText: '$refs.text.innerText = activeText' }"
When the component is initialised, alpine would deserialise the string and store the object somewhere. When a variable gets updated, the code would do a lookup on that object. if it found a match, it would pass the value to the built-in eval function. That would automatically resolve $refs
and activeText
from the proxy object.
It should be easier to implement.
@TomS- are you working at this feature? If you are not, I'd like to give it a go if @calebporzio is open to a PR. The approach i would take is the one I described in the post above.
@SimoTod I started working on it but I realised I wasn't quite ready to understand it all. I might give it a go as a personal project, but please by all means work on this. I appreciate it thank you.
The only question, more for Caleb, is: which one of the following syntax we want to use:
1) <div x-data="{foo: 'bar', baz: ''}" x-watch="{foo: 'baz = foo +
|+ foo'}">
Similar to the other x-* directives
Cons: It's a bit weird when you have a string since you need to use ` as a delimiter, we don't have access to the old value like Vue does. Also, what the watcher executes is totally disconnected from the variable and it could be anything.
2) ,<div x-data="{foo: 'bar', baz: ''}" x-watch="{foo: function (newValue, oldValue) { this.baz = newValue + '|' + oldValue }">
Closer to VueJS, I'm reevaluating it but I'm still torn.
Cons: A bit more verbose, other variables need to be prefixed by this
which is different from what we do in other directives.
Both look good to me, I like 1 with the posibility to have it call a function inside x-data like this: https://github.com/alpinejs/alpine#x-data what do you think @calebporzio
@TomS-
I think it should be something like this -> https://codepen.io/SimoTod/pen/VwYEXdj I've also made two magic properties ($oldValue and new $newValue) available in the context so they can be used.
This example is deliberately verbose to show that we can use strings, access variables defined in x-data without using "this." and access the old/new values using the magic properties.
@SimoTod That looks amazing, great work! I look forward to the PR. Hopefully @calebporzio is keen to add this to the core. I can definitely see a big use case for it.
Should https://github.com/alpinejs/alpine/releases/tag/v2.2.0 have closed this?
Technically 2.2.0 introduced a $watch magic value not an "x-watch" directive. I do believe this should be closed because with the magic value there's no reason to have a directive.
Personally I would've liked to see a x-watch directive with a syntax like x-watch:[property]="[expression]"
. This could also make for modifiers like the proposed debounce one x-watch:[property].debounce.250ms="[expression]
.
Just a personal preference that I feel would look a bit cleaner but with that said, the magic property is great!
I'm going to close this issue since the $watch
magic variable has been added. Great discussion though! If you're still interested in an x-watch
directive, it might be worth opening another issue for that discussion (and mention this issue for a paper trail).
In this example; there is a slider (let's say flickity), we want to create a custom UI that will track the active slide. AlpineJS would be good to do this because we can minipulate the UI based on the active slide.
Let's say for example on each slide we have a UI that has the title of the slide, we can use
<div @click="activeSlide = 1; activeTitle = 'Projects'">Projects</div>
Then we can use x-watch to watch the activeSlide and run a function when it changes, I'm unsure of the best implementation for this
x-watch:activeSlide="function"
orx-watch="{ activeSlide: function }
so for example we could dox-watch="{ activeSlide: $el.select(value) }"
value would be the value of the variable. I know the syntax is completely wrong, but it's the best way I can think of demostrating my thinking.