The Hard Parts of UI Development

One-Way Data Binding User Interactions

Will Sentance

Will Sentance

The Hard Parts of UI Development

Check out a free preview of the full The Hard Parts of UI Development course

The "One-Way Data Binding User Interactions" Lesson is part of the full, The Hard Parts of UI Development course featured in this preview video. Here's what you'd learn in this lesson:

Will completes the application schematic for one-way data binding by adding user interactions. The handleClick and handleInput functions are triggered by the user. The C++ DOM calls the callback function, which updates the data and triggers the dataToView function to rerun.


Transcript from the "One-Way Data Binding User Interactions" Lesson

>> However, this is not a closed system, right? This is a system that's all about the user actions that come along. And so along come our user actions. I've not missed anything, have I? No, yeah, okay, perfect, user actions come along, user actions. And our first user action is, let's say again, forgive me for being so over the top here but one minute.

And it's going to be clicking on input, clicking on input, which will, which will. Flash a little smile at the camera there, [LAUGH] which will send an event to the click. Sorry, to the click handler here saying, please place this handleclick function, or at least the reference to its position in JavaScript memory in the queue of functions to be executed.

And that's where it'll first go, handleclick at around one minute will appear in this callback queue. At around one minute, let's put in the one minute as well so we know it's there at one minute. Okay, and now the event loop. Well, you tell me, Alexa, what's happening here as a specialist in acing, what's happening here?

>> Well, first, the event loop checks if all our global code is-
>> Uh-huh.
>> Done running.
>> Sorry, so let's make sure our global execution context is there, yep.
>> And if the call stack is empty, which it is.
>> Which it is cuz we're at about one minute here, exactly.

>> So then it will allow the handleclick function to come back into the call stack.
>> Perfect, or yeah, be called back into JavaScript to be executed on the call stack because the event loop was checking very quickly. Sorry, yeah, keep going, sorry. [LAUGH]
>> And then it's gone from the callback queue.

>> Right, right, right, so gone from the callback queue. When something gets added to the call stack by JavaScript, it automatically gets parens, which mean only one thing, people. What's gonna be added to our parens? Exactly, this is building up suspense, which means, everybody, a brand new what?

>> Execution context.
>> Machik thinks they're above.
>> There's a very good choir, I'm like not trying to it.
>> [LAUGH] Which means, okay, Machik, it creates a brand new?
>> Execution context.
>> Thanks, Machik.
>> [LAUGH]
>> To be fair, though, that was vaguely problematic, but I feel that was problematic by me to there demand you to repeat it.

>> [LAUGH]
>> I don't know, that's actually vaguely. All right, that's like making sure, yeah, that's not fair. Thank you, Machik, you're right, you have, I don't know. It starts off as kind of funny and cute doing it and then it starts to become problematic and odd. All right, not you, me.

All right, so there we go.
>> [LAUGH]
>> Good, all right, so handleclick, what's the only thing that it's allowed to do? Machik, what's the only thing that it's allowed to do at least? Well, there are only two things, but the first of those things allowed to do?

>> Handle the click, it just sets the post to blanks.
>> Exactly, so in other words, the only thing it's allowed to do is change data, right, to change data. So that's replaced undefined with an empty string, maybe I'll clear that fully in a second.
>> And then it calls the data.

>> And then it calls, exactly, calls that, perfect. So post is set to an empty string, and then we call our converter function, dataToView. And we create a brand new, everyone, together.
>> Execution context.
>> Execution context, beautiful, and that goes on the call stack. That goes on the call stack.

See, I apologize for that, okay. Now, jsInput.value, I mean, I think if UI engineering can become a bit tedious, that's no bad thing because tedious means predictable. Tedious means I'm running through the same function on my data change every single time. Tedious means not figuring out a complex flow of changes to data that I haven't fully tracked in memory.

And a complex flow of changes of view that do not have corresponding data tracked in memory based on a series of handlers being run. No, change data, only thing that can change, and then run my dataToView. I'm calling it dTV, dataToView here. That is going to set my value, so post is now an empty string, right?

So Machik, what's its-
>> So it's gonna be an empty string now.
>> Yeah, perfect, exactly, thank you. Empty string, which is now gonna be set as the value on our input. I'm sorry I keep switching my single quotes and double quotes, it's just trying to make sure they show up.

There you go, that's an excuse. And that now is showing up on the page itself cuz that bit's automatic, the render step there is automatic. Perfect and we are, but we are going to be a bit over the top here, right? Go ahead, Machik.
>> We forgot the other part last time, [LAUGH] I think.

>> I'm just saying the text content was not set, I mean, we didn't do.
>> We did, undefined.
>> On the view.
>> Okay, I guess it's an empty string, right? Yeah, okay, but we don't see an empty string.
>> We didn't have the, actually the-
>> We wrote dataToView has a track of all, exactly, of all of the information.

It's not directly displaying whatever the data is, it's conditional on that data determining, exactly. In this case, we basically said text context will be post, which is undefined, which is, helpfully, text content turns that into an empty string. And therefore, we really don't have any text here, so the div stays empty.

And that's good, that's what we want. So now, this time, though, well, more or less the same, I guess.
>> Yeah, it's empty still. Exactly, jsDiv., what matters is we can track it all through one function. So data is now that, I should probably be consistent with my quotes there.

And that is what's set as the div's text. textContent set on jsDiv, the access object sets its text to an empty string and nothing shows up. Beautiful, okay, now, our handleclick function is finished executing. It's popped off the call stack, let's do a little clear up at our execution context, or close up.

We know that our callback queue is already empty, and we're getting the hang of this now, aren't we? There it is, and now more user action comes. They clicked so they could start writing. And they start writing what? They start writing, typing, sorry. It's gotta be our friend y, there we are.

And that is going to show up in the input field, and it's gonna immediately show up on our DOM, in that value position. If we're saying that everything the user sees needs to depend on underlying data, [SOUND] it ain't pretty that there's data here, there's data here. By the way, the CSS model of the page also can have data that determines what shows up on the page.

In a sense, our HTML code was an initial population of data, only one time display of data, but it was. Again, it's like, how do we have four different places to store data that can then determine what the user sees? And at least three out of four of them are changeable.

Well, that's why we're gonna be really restrictive if we're actually gonna have JavaScript as our single source of data. To the point that I won't even see this as necessarily data so much as a submission. Because when that input is filled in, it's gonna trigger the handleInput function to be passed to the callback queue.

Where, Ian, can you help me out? We're like one minute and one millisecond. And handleInput cuz the user has typed their name, Y. handleInput has now been added to the callback queue, what's gonna happen in JavaScript?
>> Well, since it's in the callback queue, we're gonna see, I mean, with the event loop, we're gonna make sure that nothing is in the call stack.

>> Yeah.
>> Well, except for the global function. And then we're gonna execute, do we handle the input? Yes, cuz we typed Y.
>> Right, exactly.
>> We are going to assign our piece of data post.
>> Hold on, so hold on, we're gonna execute handleInput, so it's a new.

Okay, you can do this, Ian, it's a new what?
>> Okay, it's a new execution context.
>> Yes, beautiful.
>> [LAUGH]
>> Exactly, brand new execution context. Exactly, well done, exactly. Into it we go and you're right, the only thing we can do is update data.
>> Yes.

>> Tell me about it.
>> So we are going to take the piece of data called post.
>> Yep, well, the identifier for a piece of data called post, yep.
>> Yes.
>> Yeah.
>> And then we are going to assign it to the result of accessing the value property of jsInput, but jsInput is gonna be a-

>> Accessor object.
>> An accessor object that we got cuz we can't just get stuff from the DOM.
>> Yeah, because there's C++ objects. It's beautiful, Ian, it's wonderful.
>> So we're reading it from the DOM through that accessor object to get the value of the jsInput.
>> Yes.

>> Assign post to that value.
>> Yes, so we grab it, and actually, it's gonna turn into a JavaScript string that we end up assigning there. Note, I'm now changing from green, [COUGH] which was a user submission, I'm gonna call it, into saving it in white. It's a JavaScript string, there it is.

That's great and then we've changed data. It's all we did, and so Ian, what are we now going to call?
>> We're gonna call our function dataToView.
>> dataToView converter, brand new execution context. I call it a converter function, right, because it converts our data into our view.

Now, it might do it with a bunch of conditionals to determine exactly what to display, but its input is JavaScript data and its output is view. It's content the user sees into dataToView convert we go. And John, if you don't mind, over to you, we are going to evaluate?

>> jsInput.value set, etc., and we will check if post equals undefined. And because it's not equal to undefined, we will get post's value and set input's value to post's value.
>> In the DOM, exactly, and that is the string what?
>> Y.
>> Y, and look, people, I've changed it to white.

It is derived directly from our JavaScript data. That only would have shown us the green for a second. Then that's gonna, of course, mean that what the user sees, they think it's just what they typed. No, well, they're not to be trusted with that.
>> [LAUGH]
>> They have to trust us to refill it with actual data from JavaScript.

And then take it away, John.
>> And then we will call jsDiv's setter method textContent.
>> Yeah, they call it property, but I'm with you, method or prop, both work. But yeah, exactly.
>> textContent and we will set it to post.
>> Yeah, which is?
>> That equals to Y.

>> And that-
>> Will go to DOM and set.
>> Beautiful, the execution context closed, they're popped off the call stack. And look at that, people, we have a full user interface with a highly restrictive but honestly liberating mental, well, model, I don't say mental model. Design pattern of everything the user can possibly see is an output of JavaScript data.

We have one function that in any change to date, any change, any action from the user or inaction, the initial before the user takes any action. Any action, the user will only be allowed to affect change on JavaScript data, nowhere else. And then we have one function, you could even call a description.

They use these funny terms that sound very profound and obscure, but I get it, it's a description, it describes what's gonna show up. In fact, based on that data, we have a full description of the content, not of the actual boxes, that might come tomorrow, but a full description of the content that's gonna show on the page.

All within one function, it's beautiful. And well, I don't know, good job, everybody. So let's see what it says. Restrict every change to view to be via, 1, an update of our data, and 2, a run of a single dataToView convertor function. Not make different changes in every different condition, every different action by the user, but one function that pipes the change of data through to the entire dependent.

Or not dependent, we haven't made that restriction yet, but the output being the view that the user sees. Just one approach, but immensely popular, and it tees us up, we're gonna see for semivisual coding with what I call a visual DOM. Something along the lines of, I have everything in JavaScript now that I need if I wanted to actually map out exactly what's gonna show up on the C++ DOM.

Because the only things that are gonna show up here, well, not quite yet, right? Because right now, I've got inputs, and divs, and stuff like that. With a bit more movement in terms of defining what's gonna show up, here in JavaScript first, I could have in JavaScript a full description of what's gonna show up on the page based on every single piece of data.

Based on every change, I can see it first in JavaScript. That's because nothing shows up here that wasn't determined by the underlying data and conversion from that data through to the view. Not like one-off handlers that change the data, no data left on here from the user's action that then doesn't get, no.

Anything from the user is a submission to underlying data here. A pinpoint submission, as Machik rightly said, and then it's going to run the one way dataToView conversion. Well, if we know that, maybe we could even intercede that with a full layout of what that page is gonna look like.

So that within Java we have a full map of what the page is gonna end up looking like. Which given that we don't have that access to that full map with all its state, we can't just call to log that. We need to make getter calls to get all that information every single time.

It would be pretty nice to have a full map of it within JavaScript first. It could also potentially allow us hand in hand with that to optimize. You notice here we wiped all the data? For our purposes of reasoning, amazing, wiped and reloaded all the data. Do we really need to do that every single time, a thousand elements, we gotta really wipe all the data every time and re?

Could it be that if we could map out in JavaScript all the data as it's gonna be displayed and then have an algorithm, clever code, as it's gonna be pretty basic? Look back at the previous map of the entire contents that are gonna be displayed and see what actually changed and only make those changes.

That could be quite a powerful move for us.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now