Binding Between Views and Models
Check out a free preview of the full Asynchronous Programming in JavaScript (with Rx.js Observables) course
The "Binding Between Views and Models" Lesson is part of the full, Asynchronous Programming in JavaScript (with Rx.js Observables) course featured in this preview video. Here's what you'd learn in this lesson:
Jafar puts his new Observable based on the Object.observe API to work by creating a two-way binding between the model data and the view. If the view is updated, the changes propagate to the model. If the model is updated, the changes are reflected in the view.
Transcript from the "Binding Between Views and Models" Lesson
[00:00:00]
>> [MUSIC]
[00:00:03]
>> Jafar Husain: So the thing we actually wanted to try out I believe. Fortunately JS Bin keeps losing the toolbar so I can't add it. But I think if we paste it into another screen it'll come right up. So let's keep our HTML toolbar open and let's try and do that server example we talked about earlier.
[00:00:18]
So we're listening for changes to a form. We're gonna have a form and that's gonna make changes to an object and then we're gonna listen to changes to the object and then make a change to the server. Does that makes sense? So I'm gonna add a,
>> Jafar Husain: Name and age tag.
[00:00:41]
>> Jafar Husain: And I'm gonna give them IDs.
>> Jafar Husain: Now clear the console. Let's grab a reference to our name and ID.
>> Jafar Husain: Right, now we need to listen for changes to name and age, and we wanna update it on a JavaScript object, a model, if you will, of a person.
[00:01:17]
And the advantage of doing this is that if we make all these changes to this model person, we might have six or seven different windows, in our view all bound to the same model. So in addition to a view, showing information about that person, you might have another pane on your view, showing the location of that person.
[00:01:37]
So in other words, the same model in an application can be viewed in many, many different ways. And so by using one object to sync up and to store the state of that object, we can have many, many different views listening for changes to that object. And you only have to change the object in one place.
[00:01:52]
And all of the views reflect the difference in that object because they're all listening using object.observe. Does that make sense? So I'm going to listen for changes to age.
>> Jafar Husain: Now remember, somebody was asking about change, the onChange event. This is the ideal case for the onChange event.
[00:02:19]
We don't wanna make this change after every key press. We only wanna make the change after somebody tabs away from the text box. Then, and only then, do we wanna update the person object. So I'm gonna create a person object which I'm just gonna keep in memory here.
[00:02:39]
>> Jafar Husain: And I'm going to take,
>> Jafar Husain: Just gonna listen for,
>> Jafar Husain: What I'll do is I will listen for changes to the person object and update the view. So if we ever change the person object directly, we're gonna update the text box and the age of that person.
[00:03:00]
So I'm gonna use object observations on the person.
>> Jafar Husain: And we are gonna change the text box of name if changes includes the property that the name has changed, right? That's one thing we could do. Well actually, before we do that, let's just do the simplest way, which is always update, always update with the current value.
[00:03:38]
This is less efficient, because maybe I've just changed the name on the model object. And every single time any change occurs in the model object we're gonna update all the fields on the DOM. This is the less efficient approach but it works.
>> Jafar Husain: Now look, it's already filling in stuff here.
[00:03:58]
>> Jafar Husain: Mm-hm, name.value. I'm not sure why the name isn't making it in there. Because it's waiting for the first change to do it, right? So if I go person., that should actually get the name if I initialized it with the name. So I'm not sure why our name property is not getting filled in.
[00:04:20]
Anybody have any idea out there on the web? We've defined name and we've pulled it in with getElementById just like age. And every single change and object observation is being picked up and written to the DOM, so I'm not sure why we're not getting the name property here.
[00:04:37]
>> Speaker 2: Is name a reserved word?
>> Speaker 3: [CROSSTALK] string value.
>> Jafar Husain: Sorry?
>> Speaker 3: Someone said age is a string value, I don't know if that matters.
>> Speaker 2: Is name a reserved word?
>> Jafar Husain: It shouldn't be.
>> Speaker 2: Or HTML?
>> Jafar Husain: In the HTML, yes, well not inside of a string.
[00:04:52]
I wouldn't expect so, but you know what? I think you're right, cuz that's the only possibility I can think of.
>> Speaker 4: When you're defining that person up there, you have Jim, and then age Tim? Or was that just cuz-
>> Speaker 5: He's Tim years old.
>> Jafar Husain: [LAUGH] Yeah, that's definitely a typo.
[00:05:11]
>> Jafar Husain: Okay, I'll change it everywhere to be firstName.
>> Jafar Husain: Did that work?
>> Speaker 4: Now it's working. Try re-running it.
>> Jafar Husain: Hey, okay, cool. So now we can listen for changes to a model and update our view, right? Another thing we can do, but now notice we also haven't gone the other way, right?
[00:05:46]
We're not going both ways, which would be kind of nice. If you change a text box, we'd ideally like to update the model, right? But here, we might be able to have many, many different views of the same information, right? And then only one place in the application where we change that model and then we update all of the views.
[00:06:04]
Does that make sense? So we can have this person object in memory and many, many different views of it and we change the person object in only one location then update it everywhere. But another thing we might wanna do, so we haven't gone the other way yet, we haven't set it up so that if you change a text box you then change the object.
[00:06:19]
The nice thing is we're never getting into an infinite loop, right, where I change the text box and then I change a property to the same thing it already is and then it calls an object observe. Because the reason why we're not getting that infinite loop is that for one thing object observe won't fire, if the property has the exact same name.
[00:06:32]
So then we don't have to worry about that. So let's see if we can go the other way around now and practice using MVC framework to do this. But this is exactly what an MVC framework will do under the hood if it uses object.observe, right? So it'll listen for name.
[00:06:47]
Now I'm going to convert,
>> Jafar Husain: The firstName change and forEach and I don't even care what I get. I'm just gonna sync up the person.firstName with value.
>> Jafar Husain: And I'm gonna do the exact same thing with,
>> Jafar Husain: person.age and let's be good and do parseInt on that.
>> Jafar Husain: Okay so now, we should be syncing up changes both ways.
[00:07:42]
So I'm not sure quite how to figure that out, but I think if we log when we get an object.observations then we'll know if that's worked successfully. So we'll console.log changes, and now we're only gonna get a log when we've actually changed the person object. So if I change this form we should update the person object if everything's working correctly and we should get an object.observations call back.
[00:08:05]
We should get this changes printed out to the console. So I'll run. We've already got one cuz I've changed one in here right, explicitly. But now let's see if we change this to,
>> Jafar Husain: I'm gonna hide our HTML pane cuz we don't need it anymore. Strange to clear the console.
[00:08:35]
>> Jafar Husain: No, not yet.
>> Speaker 4: We need to tab away, right?
>> Jafar Husain: Good call. Yes, I do. But that was not the source of the problem. So we should be listening to change on, age. I forgot to put age instead of firstName there, so let's see if that solves the problem.
[00:08:59]
>> Jafar Husain: Yep.
>> Jafar Husain: Okay, so now every single time we change the form we're changing our model object, right? And hopefully vice versa as well, let's see. So I'm gonna use the set time out and I'm gonna change our person name to John and I'm gonna do it after five seconds.
[00:09:23]
So we're gonna patiently await here, and hopefully if we do this we should see the text box name change. We didn't see it change but we did see a console log happen. So that's a little bit odd. Something definitely happened, but we didn't update the form. So let's run it again.
[00:09:39]
So we got a console log. Then after five seconds, we should see another console log. Great, but we're not updating the name. So why is that? Well, let's go back to our observations where we're forEaching over observations.
>> Speaker 3: Does it have to be firstName, person.firstName?
>> Jafar Husain: Yes it does, thank you.
[00:10:05]
Collaborative coding, I love it. So run it and we wait, time elapses and bam. So now we've got code syncing both ways from our view to our model, but also from our model back out to our view. And that's great because if any of the views change the model, they only have to change it in one place, this one model object, and then you might have n different views of the same model.
[00:10:29]
And all the changes are gonna get propagated back to those views.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops