Skip to content

Instantly share code, notes, and snippets.

  • Save anonymous/458ea8ff7f968faa719f6e52d46848b9 to your computer and use it in GitHub Desktop.
Save anonymous/458ea8ff7f968faa719f6e52d46848b9 to your computer and use it in GitHub Desktop.
# Steve Counter
I'm trying to create a simple button that counts the number of times it's been clicked.
## 1. Append to the screen in response to clicks
First, let's create a button:
```eve disabled
commit @browser
[#button text: "click me!"]
```
Now let's add a new click div to the page on each click:
```eve disabled
search @browser @event
[#click]
commit @browser
[#div text: "clicked!"]
```
Ok, looks like this only adds one "clicked!" div no matter how many times I click the button. What happens if I change the commit to a bind?
```eve disabled
search @browser @event
[#click]
bind @browser
[#div text: "clicked!"]
```
That doesn't seem to change anything... I tried adding random whitespace to each program and hitting the refresh button a few times to make sure that it's not an Eve bug here. That didn't work.
Ok, let's see what the documentation has to say about bind and commit. (First, I had to realize that we're on v0.2 which was only apparent to me after reading posts in their blog.) Sounds like bind is for reactive updates and commit is for one-time updates, so my initial impression that commit is what I'm looking for here seems on point.
According to their documentation, the following code should use commit to add a bunch of lines to the screen as the time changes (where a bind would've updated the time in place). However, I am skeptical it's going to work when I run it because there isn't a database listed in search:
(At this point, I am not able to add another Eve block of code, because the interface isn't popping up with the plus button. So I added it with three backtics on top and bottom. However, it doesn't seem like the editor is registering that as code so I'm going to save it to a gist and load it from that gist.)
```eve disabled
search
[#time seconds]
commit @browser
[#div text: seconds]
```
No way! It's working! The number of seconds in each minute are being appending to the screen. The fact that this works without specifiying a search database makes me wonder how search works. That is, what is the implicit database that it's searching from.
(One strange bug is that once the seconds go past the vertical edge of the screen, the button's height collapses and it becomes smaller than the text that it contains.)
Ok, so now let's apply what I've learned to see if I can get "clicked!"s to appear on every button click. First, let's uncheck the time code from above.
```eve disabled
search @event
[#click]
commit @browser
[#div text: "clicked!"]
```
It seems like the @event database is implicit because it adds a single "clicked!" to the page (no matter how many times I click) whether or not I add that database to the search. (But only searching the @browser database seems to prevent it from working.)
One possibility this isn't working is that it doesn't see each new click event as unique so it doesn't trigger a new commit. Let's try adding the event timeStamp to the search:
```eve disabled
search @event
[#click timeStamp]
commit @browser
[#div text: "clicked!"]
```
That seems to break everything... so I'm going to uncheck this block. Potentially Eve doesn't have that attribute of events in their model.
Ok, I have more more idea. Let me add two buttons to the screen and see if I can get seperate divs to add to the screen in response to clicks to either with a single search:
```eve disabled
commit @browser
[#button id: 1, text: "click me 1!"]
[#button id: 1, text: "click me 2!"]
```
```eve disabled
search @event
[#click element]
commit @browser
[#div text: "clicked {{element}}!"]
```
Ok, I wasn't able to get the element.id part working but if I just put the element in the div, I do get a new div for each button:
clicked ⦑49⦒!
clicked ⦑50⦒!
By accident I came up with a way to append things to the screen in response to an event:
```eve disabled
commit @browser
[#button text: "Click me first"]
```
```eve disabled
search @event
[#click element]
commit @browser
[#div text: "Element {{element}} was clicked. Now click me."]
```
First click the button. Then click the text that appears below it. Then click the text that appears below that. If you follow this pattern, you can do it to generate as many pieces of text as you like. Why this doesn't work if you just click the button a bunch of times, I have no idea.
# 2. Update records in place
Ok, so I'm declaring failure on adding something on the screen in response to a click. Let's see now if I can update the record of a div in the browser:
```eve disabled
commit @browser
[#button text: 1]
```
```eve disabled
search @event
[#click element]
commit @browser
element.text := "2"
```
To my suprise, the above code works insofar as it get the button to move from 1 to 2. However, it does not move from 2 to 3 or beyond. There are two problems:
1. The main problem is that whenever I try to reference element.text on the right-hand side of setting element.text, everything breaks. For example, the following, which tries to continuously append the word "clicked" to the button, does not work:
```eve disabled
search @event
[#click element]
commit @browser
element.text := "{{element.text}} clicked"
```
2. Even if the above did work, I'd still need to figure out how to parse a string to a number so I can add one to it.
(Before I continue here, I should note that I am worried that someone reading this code will have trouble following because it's unclear which boxes to check and leave unchecked. I should probably come up with a convention for that.)
# 3. Let's try with a counter object
```eve disabled
commit
[#counter num: 0]
```
```eve disabled
search
[#counter num]
bind @browser
[#button text: num]
```
```eve disabled
search
[#click]
counter = [#counter]
bind
counter.num := counter.num + 1
```
So the above code doesn't seem to work. I wonder if it never even runs because in the search of the last block I am asking it to search for a click event that's also a counter. I need some way to bring the counter record in scope, a way to join it to the button.
## Add the counter to the button
Although it might seem like cheating to look at the example code for creating a counter, I promise you it's not because I've been reading it this entire time and it's been hours and I'm still not here. However, I am going to lean more heavily on the example here because they show me how to join the counter to the button.
```
commit
[#counter num: 0]
```
```eve
search
counter = [#counter]
bind @browser
[#button text: counter.num, counter: counter]
```
```eve
search @event @browser
[#click element: element]
commit @browser
[#div text: element.counter.num]
```
So on the bright side, it seems like I was able to add the counter to the button. However, I'm not able to get the num property from the counter record. Maybe I need to add in whatever database the counter has been commited to?
Yes! If I add @session to the above search, things start to work:
```
search @event @browser @session
[#click element: element]
commit @session
element.counter.num := element.counter.num + 1
```
Oh baby! We're cooking with fire now.
Seems like one of my key misunderstandings is that records that aren't stored in @broswer and @event, are implicitly stored in the @session. My clue to figuring this out (besides copying from the example) was that when I didn't include @browser in my search above (it used to just be @event), I wasn't able reference element.text. I guess listing the databases is what lets the Elm runtime know which tables to "join in".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment