字幕列表 影片播放 列印英文字幕 WARD BELL: OK, well, I'm going to start. I'm Ward Bell, I'm VP of technology and a founder of IdeaBlade, a company in the Bay Area. And I'm here to talk about Angular and Breeze. Breeze is our product and Angular is a Google product, and they work really well together when you're building CRUD apps, which is Create, Retrieve, Update, Delete, something like that. Anyway, if you business apps are a very typical part of this. I come from the Microsoft arena. We build a lot of business apps there. And so building business apps is kind of what I know a lot about. I don't know how to build games, but I know how to build business apps. And because I don't know how to make games, I can't be Huggy Bear, because I can't do a lot of bling. So I have to do the thing that a lot of business developers get paid for, which is to build business applications. And you can call them Line Of Business applications, that's LOB, and CRUD apps. They kind of go together, because they're all about asking for data and saving data and stuff like that. And the typical category is ERPs, and I wish I could-- Enter source, Resource. You know how you know the acronyms, you don't know the words. CRM, Custom Resource Management, asset tracking, call centers. The kinds of apps in which users sit in front of them for long periods of time and they answer questions like, I've got to go find all the orders and I've got to fix them. Or I've got to book a premium three-week vacation or renew rail cars, or something like that. These are the typical tasks that people sit in front of them all day long. And really what the modality is that's pretty common across all of them, is that the user sits there are tries to find a target data set to work on like orders and something like that. And then the application pivots around that data set, looking at it from different angles as they process it. So they're not surfing all over the place. They just find what the customer is interested in and go at it. And so from a computing perspective, it's really a small set of data. But from their perspective, it's not so small, because it's about what fits in their head, fits in their attention span. So they usually just grab onto a chunk of data and then sit with it for a long time. Now because they work all day long doing that kind of thing, the most precious resource is the user. And so the whole idea is to say, let's move all the computing right there. Let's have client side computing, client centered computing. Another term for this might be SPA, Single Page Application. You could think of it as Ajax applications, HTML JavaScript app, whatever you want to call it. We call it SPA a lot where I come from. That's it. And Angular JS ought to be really good at it because of what you just saw. And it turns out it really is. And so what's happening is that a lot of people who are in the Microsoft space are seeing this Angular thing coming, and they're kind of interested in it. And one of the reasons-- well, there's a list of reasons about why they are. For one, it's comprehensive. So it does a whole lot of things. You don't have to buy a whole lot, or get a whole lot of libraries. It does screen. You can handle screen management, and dependency injection, and a whole bunch of other things that you can learn about. It's really elegant to work with, which is nice, because there are some other comprehensive ones that just seem like you write, and write, and write, and write, and write, and write, and write, and you can't figure out what their head was about. So it's nice and terse. Some people really like that it isn't sitting there listening for observable, so I don't have to have special purpose objects that raise notification events. And it has a lot of momentum. There's a lot of people working to make Angular better all the time. And it's getting a lot of traction. So lots of reasons. And there are people in the Microsoft space who are very well-known there who are writing about it, like my friend Scott Allen here. So anyway, you start to do it and you're the captain of your Angular luxury cruise liner. And really your job is to make sure everybody has a good time, and you don't end up on the rocks. That's really your only responsibility. Just keep it moving. Keep them happy. And so once you're doing it, you'll see that really if we think about that liner, there's the entertainment section up above, which is where you do the presentation. And that's where Angular is really super strong. And if you're doing the line of business stuff, there's all that data access stuff. And that's where Breeze is going to come in. So you could say we're going to help you build applications from A to B, except that doesn't sound right. Anyway, so remember it's fine to target data set and pivot around it. So it's a lot about data. And what do I mean by pivoting around it? Suppose I had an application that was for scheduling a code camp and there were sessions. Chances are you're going to have to pick your session or edit a session or do something like that. Well, the session keeps occurring from screen to screen to screen to screen. And you're really talking about the same session as you look at it from different angles and make different changes. So here we have this class by [? Scott Gould ?] appearing in four different screens. And when you finally look at one of the items that's in it, you'll find that the data that are behind it, it's not just one object. It's usually backed by a SQL relational database or something like that. So it has relationships to other things. So sessions have tracks that they're on, and time slots, and rooms, and speakers. And you have this sort of network of related objects. And that's part of the LOB space. So how are you going to deal with that if you're going to do it on the JavaScript side? So I'm going to propose to you that you're going to need to do queries. And some of them, because you're going to be on mobile devices, and some of them, because you're going to keep looking at them from one view to another, you'll need those queries to be both local and on the server. You'll want to be able to cache data. You'll want to be able to deal with those object graphs I was describing. You'll want to be able to do change tracking, because they're going to be making changes. And you're going to hold them. You're not going to just save them right away. You're not have a save button. And you're going to want to make those things that you're dealing with like sessions and stuff, you want them to have behavior. They're not just data bags. If you just read them in out of the database, they're data bags. But no, if you're going to use them, they're going to have behavior. So you could roll your own framework around this. This is really what ends up happening, whether you call it an official framework or not. And then your ship can run aground. Or you can use Breeze. And that's my commercial. It is open source. It's MIT licensed. It's on GitHub. Enjoy it. So back to this Angular thing. And Angular and Microsoft, and Google and Microsoft, cats and dogs living together, what's that? But yes, it does happen. And not only that, but there is now a in the box Visual Studio is the dot net IDE of choice. And right in the box now, you can get a Breeze Angular template that shows Angular working with Breeze inside of ID, the Visual Studio. As you can see, they're talking about it on a Microsoft address. Not on my site. Of course, I talk about it, too. So it's a two-page app. It's really simple, but it illustrates a lot of capabilities, both of Angular and of Breeze. And this is what it looks like when it runs. And we're going to do a demo of it. And then at the end, I'll show you more about what you can learn more. So-- oh my-- this is later in the day. No, no, and no. OK. Because we're going to build that app later. So if I were to spin up a new version of the Visual Studio IDE-- and there it comes-- and I wanted to create a new application, I can do these template kinds of things. And there in the web, ASP MVC, I can do that. And ooh, what's this? Yeah, there's the Angular SPA, right in there. So if I just keep on clicking, I'm going to end up with an application that looks like this. And just to save you the effort of watching this thing running away, to fill it all in, it will end up looking like this. And this is the a ASP.NETMVC4, if you know that world, which has a lot of stuff in it. But the net of it is that your client side application is right here in these JavaScript files and HTML files. And if I run it-- and I have to run the right thing, not that one. Get the right keys. It comes up. And I've highlighted some things, because I've been here before. So I have my to-do list, and my never-to-do list, and who knows what that one's going to be. And I could learn-- here you see I've learned-- no, I'd better learn it again. Learn Angular. Turn it off. By the way, every time I'm going anywhere in here, you'll see that it's saving. See? Save changes. And I could do a bunch of stuff like that. And if I say, oh no, see, there's the validation of all kinds. Yeah, that's not good either. And I can switch over here on the second page and see what I did. And really, the second page is only about logging what's going on. And you can see it saved all these modified things. So it has some idea of change tracking and error handling, and it's all reporting that. And you'll notice that it was initially going remote, but now it's going locally, whatever the heck that means. But that means that it could be kind of fast as I flip back and forth like this, because it's not making a trip to the server. And that's kind of what you want to do. OK? So you can spelunk that to your heart's content. But I'm not going to do that anymore, because we're going to take a trip through Angular and Breeze from what I hope is zero. And I'm also not using Visual Studio anymore. From now on we're going to go with Sublime. So I'm going to create a new one here-- NGI create. And I am a really fast typist, as you can tell. Spare you all of that. But this is just a big version of what Brad was showing during the warm up. So there's an NG app and a controller. And there'll be some repeating, and who knows what, but we'll just save that for now. And we'll call that index.html. And trust me, we'll get to know it. Let's create another one. All right, I have to have a controller. You saw that I mentioned the controller. So I'll type really fast again. And there is my controller. And I'm going to just shift this over so I've got a module. I'm stuffing a value in here. But this is really my controller right here. And this is an example of dependency injection. I told you I would use everything in the Angular tool kit, and I will. And so I'm really injecting some stuff in here, and that's the way it is. But I'm going to expose a list of items and a logger and stuff like that. OK. Well, we'll call that app dot JS. All right, so that's kind of like the controller side and the view side. And one of my rules is you never do data access within a controller review model. The controller's job is to manage the view. It is not to go into the intricacies of accessing data. So I always create some kind of other class to wrap around it. That's just good practice. And we'll call that our data context for historical reasons. And, wow, I type fast again. And there it is. And once again, I'm using dependency injection for various reasons to get some stuff in. I won't go into it, because all this code will be made available to you. But let's sort of see what it does. I've got to call that data context dot JS. All right. And if I have done everything right, I will be able to go here. And there's my index HTML. And I guess it worked, because there it is. Unless it's looking at the wrong one. No, that's the right one. So how lucky is that? Worked the first time, thank you very much. We can go home. It's actually not showing very much. I wonder why that is. So let's see. Well, first of all, it's not showing anything, because our controller isn't going to get anything. It would be nice if it did. So let's have our controller-- I think it's going to do it-- starts with an N. NGA and then [INAUDIBLE]. OK. So this would be the kind of thing you would get the items when the controller was instantiated. And what it's going to do is remember, I always go outside. I'm not going to do any data access inside. So I'm going to ask the data context to go get me some items. And because this is the way it is, it's got be asynchronous, right? So this is the grand world of promises. If you don't know what a promise is, let me give you the intuition. I'm going away to go do something, I will give you a promise. When I come back, I'll tell you that I either succeeded or I failed. If I succeeded, I'm going to call your then callback. If I failed, I'm going to call your fail callback. And no matter what happens, I'm going to call this refresh view. Fin finish. So that's kind of the syntax for dealing with this data context. I don't know how it's going to do it, but it's going to give me a promise, and I'm going to react. And when I get it back, I'm going to dump the data into the items so that they'll bind. And if there's an error, I'm going to print it also into the screen. And no matter what happens, I'm going to call this thing called apply, which you do in asynchronous operations in Angular to tell it go refresh yourself. So we put that in. And my bet is that even though we did that, we didn't get anything new, because if we look at the data context, you'll see that the get items was returning nothing. A big nothing. So let's make it return something. We'll blow that away, NGD, and we'll call that get. And lo and behold, now we're going to do something. What are we doing? Well, I'm going to fake the data in here. So I'm going to return some results of two people named Igor Minar and Naomi Black. And one of the great things about promises is you can chain them. So I can do thens and fails before the caller gets his thens and fails. So what I'm going to do when I succeed is I'm going to say yahoo. And then I'm going to return something. And if I go wah, wah, wah, sad face because it failed, that's what I'm going to do. So we'll save that. And let's see if that makes any difference. It did, but I didn't see anything happen here. But at least I got two of something. OK, so I guess it's time to go learn about binding. And there it is, binds to something. Let's replace that with-- I'll bet it's the word bind. Yes. So for every item in items, I'm going to show the first name and a space and the last name. Hope it works. Hey, it does. Yahoo. That's binding, a most primitive kind. You've seen it before. OK, that's really nice. But we can't make an application that works entirely from data that we store in the JavaScript. So let's do it the Angular way. Let's use that HTTP thing, which is a kind of primitive way to do Ajax calls. And I'm going to do this whole service name thing. That'll give me a URL. And when I do the get, I'll get back an Angular promise. Now an Angular promise isn't quite like the promises I use in Breeze, which are QJS promises. But Q can convert them for me and it'll return a Q promise. So just ignore the man behind the curtain. And then you get the get succeeded and so forth. And if I do this and I run it again, I get an error message, which is really not what I expected. What line? You know, I did that last time. You can't do that twice, and thank you, audience. You've been most kind. Let's see if that works now. Hey, how about that? I actually just made a trip out to a server somewhere-- let's just do it again. And I got speakers from-- don't know if you can see that, but-- I went out to Sample Service Breeze JS which you can go to, too, because it's just there to serve up some data for you to play with. And that's what I got. And all I did was fish the first name and the last name out of it. So that's good. But look at this. They're in sort of like, whatever order they're sitting in the database. You're not going to get far building an application that way. And so you're off to the races building your listing ship because you'll be building your HHHH HDV handling, all your data access stuff. And that's what people start out by doing. But we're not going to do that, because we're going to do it the Breeze way. So welcome to Breeze, NGD speakers. All right. This time I'm using Breeze, I'm going to create a new instance of this thing called an entity query. It's a query object. And we're going to evolve this query object as we go. And we're going to get it from the speaker's resource. When we get this query, we're going to get it back. And we're going to execute it with something called a manager, which is your gateway to data and also a cache of entities. Everything else is the same, kind of. Just squint. And now if I run it again, it doesn't work. Now why is that? The reason is because I actually can configure Breeze to say, you know what, I don't like-- in server land, they're in Pascal case. First name with a big F, and so forth. But in JavaScript, you like to have lower case. So we do some mapping things on the way in, if you tell us to. And I told it to. And so I'll just change that like so. And maybe this time it'll work. Yes. Yahoo. See me do that? So clearly something's a little bit different about the objects that are coming back, what's happening to them. They're actually coming back over the wire as JSON. We take those objects, and we turn them into something called Breeze entities. And we'll see that as it evolves. But for the moment, they're just data bags like everything else. OK. So we still haven't really improved things, because it's still in random order. But we can start to do some interesting things, all client side. Like for example-- wrong place-- I'm going to evolve this query object that we had here. I'm going to say order by-- let's do it first name. See, this is why I don't type. First name, last name. And if this worked, you can see that they are, indeed, sorted. There's Erin, Collen, Dan, Dave. So we got the sort. Now where did that sort take place? It did not take place on the client. It took place on the server on the data tier. It did not take place here. Took place on the data tier. Very important. Well, we could just do it again. Where are you? It's still thinking. You'll see it later. OK. So we've got an order by. What else can we do here? Well, let's see. We probably want to be able to filter it. So let's say, I don't know, the last name. There's a whole vocabulary here. So it could be starts with B. Let's try that. See if that does anything for us. It does. All right? Well, I went too fast there. I'm composing this nifty URL with all that stuff in it. It's kind of an OData query, if you know OData syntax. So I did that. So that happened on the data tier. Let's see. What else could I do there? There was actually a fair amount of data that came back. So I could say I really want to slim it. Well that's almost the same as this syntax here. This is called a projection. See what that does for us. No visible difference there, except if we look at what came over, it's very skinny. First name, last name, first name, last name. None of the rest of the data that came over before is coming. So I can reshape the data on the client side. Or actually, what I do is I shape my instruction on the client side to reshape it, send that instruction to the server. The server on the data tier does the reshaping, and skinnies my data down. I'll get rid of that. OK. But here we are, well, the wrong one. I wanted to get rid of the selects. You can't just sit there plugging Bs in there and Cs and Ds. You got to get what the user wants to do. So let's put a search box in. And where should we put it? We'll put it right here. NGI search. There it is, search. Do a little binding to a thing called search text, which should be in our controller somewhere. And a bunch of other information, and then we'll also see it. So that's nice. Let's go add it to our scope. Our scope keeps getting bigger and bigger as we bind to things, learn to bind to things. All right. So now I said I was bound to a search text. I'm going to give it one. And I'm going to use this other Angular thing called watching. What I'm doing is I'm watching for changes in value. And when I get a change in value, I'm going to call it get items. Right, so every time we type anything in that search box, it's going to get detected, and it's going to get passed down to this get items. That's all well and good, but I'd better pass that information along, because it'll probably need the search text. So I'm going to pass the search text to the data context. That's good, but the data context doesn't know about it yet. So let's extend this query. Let's call it search. OK. So I've got a little reminder here so I don't mess up. Now my get items has got to get a search text parameter. That's going to be the text I'm searching for. And that's good. Got that reminder out of the way. So when the search text comes in, I'm going to evaluate it and trim it and all that other stuff. And if there's any search text left after I take off all the spaces, then I'll say I'm searching for that. But here's the real key. I'm building up the query. I've got to get rid of that [INAUDIBLE], because I'm no longer hard coding B. It starts out as a query. If there's search text, then I will add the filter clause on. If not, I'm just going to go get them all. Let's see if it works. Well, I got that. Let's try-- hey, how about that. And I'm kind of tellying you what I'm looking for there. OK. Now we're making some progress here. That's looking closer to an LOB app. As long as I'm searching for last name, why not just search for anything? I got a little bit of search text, why not search for anything? So let's see if we can do that. NGD [INAUDIBLE]. And it turns out we can. Otherwise I wouldn't be here. So what you can do is you can create predicates. And you can build things up-- and's and or's and all the kinds of strange conditions. You can build them up. Again, I'm creating the client side query. It's not running against the client. It's being sent to the server. So in this case, I'm looking to say if the first name or last name contains the search text. Did that help things any? Let's find out. What will I know? Well there's B and A. Let's see. There's a BA here and a BA there. Bango Esteban. So it's now working first and last name. Getting closer. Let me catch up with where we're going. The connection here is really great. And apparently my server's working really great, too. So it's going really fast out there. And this is not a realistic speed, certainly, of a mobile app. So I'm going to make this thing slow down by putting a delay of one second in there. And then I'm going to do what I was doing before and execute the query. So I'm just making life a little bit slower and more realistic. And now if we do this, we get an error message. And that's not good. What did I do? Anybody know? Just undo? I could do that. That would be really nice. Let's see if it still works. AUDIENCE: [INAUDIBLE] WARD BELL: What did I not get rid of? AUDIENCE: [INAUDIBLE] WARD BELL: Oh, here? So you're saying-- AUDIENCE: [INAUDIBLE] WARD BELL: Oooh, you bad boy. NGD slow. AUDIENCE: I think you need that bracket. WARD BELL: Think I need that bracket, huh? AUDIENCE: [INAUDIBLE] WARD BELL: We're going to try this once. And you guys fail. Me, I'm perfect. But no, you failed. I love JavaScript. All right, we're taking that back. Because we don't really need it to be slow, do we? No. I just need it to work. Whew, all right. We're going to pretend it's slow. The whole point of that was damn, just how do I make my application slower? I always want it to. Anyway, the point is if it were slow, we would have some advantage to writing things locally versus going remote, because we're going to be toggling back and forth between pages as I was talking about earlier. So let's see if I can make that work. And we want that to be at the user's option. So up here in the HTML, I am going to say no, stay local. All right, I'm going to put a little check box up there that binds to a stay local property. So when I check it, I'll stay local. Duh. And now it's going to bind to something. So NGA stay local. So there's my stay local variable. And I'm going to watch that guy, too. Because when he fires up, I'm going to go-- it's not the first time-- I'm going to go to the get items. So no matter what happens, I'm going to end up here. Except that I'm going to need to tell them whether to stay local or not. So I'm going to pass that along to my data context. Now I'm not actually doing it. I'm just telling the data context, hey, if you can go local, I'm telling you to do it. So I guess I better do that. And pray for me, now. Because that was a lot of code. I type really fast. OK. Well, I'll need to get that stay local thing in there, because I need to get that passed through. And I did that in both places, and that's nice. And the other part. So what am I doing? When the stay local comes in, I first of all, make a little text variable so I can log the fact about whether I stayed local or whether I went remote. If I'm staying local, notice the pattern here? I'm just embellishing the query object again. And I'm going to say use the little Breeze thing that tells me to query the cache. That's going to be the same query. Exact same query I would have used to go remote. But I'm going to apply it to the cache of entities I already have. Ignore the man behind the curtain there. Otherwise, I'm just going to go remote. Really what happened is I just decorated it with this little thing. And then I continued on as we did before. And since I'm not doing the delay anymore, because I couldn't make that work, we don't have to do that. OK. Let's see what we got. Let me replay this. And let's go to the network. And have I got XHR? OK. The first time through, I went through and I got all the speakers. And if I do this stuff right, it should be going to get them. And it did. Nice. AUDIENCE: [INAUDIBLE] WARD BELL: Yeah. AUDIENCE: [INAUDIBLE] WARD BELL: Well that's, of course, nothing. I haven't clicked the stay local yet. My problem was that I was really surprised to see it making network calls. I don't know why. So, duh. Let's clear that out. OK. So now I'm going to go local. Let's see what happens now. No, yes. Why is it going? AUDIENCE: [INAUDIBLE] WARD BELL: You know, that's the great thing about JavaScript. Search text. I sent the search text twice. Thank you. You guys were right all along. AUDIENCE: [INAUDIBLE] WARD BELL: All right, let's try it again. That time it went. If I go stay local, and now I go like this, yay. No more am I going remotely. See all this locally, locally, locally? So I can do this stuff to my heart's content, and I'm not making any network trips. And that's the point of that one. I talked about object graphs a little bit earlier. And sessions have speakers, and speakers have sessions. And there's this whole stuff that everything's connected. And right now, all I'm doing is getting one thing-- speakers, persons. And that's not realistic. Beware the single object demo. So I want to get the sessions that are associated with each of these speakers. But I could get them eagerly or I could get them dynamically as I need. But I'm going to get them eagerly by saying, well, let's see. I want to say expand. And I need to know the navigation path from speakers to sessions. And it's called speaker sessions. So that's what I'm going to do. And I'd like to be able to see that back here in the HTML view. So I think I'm going to replace all of this with NGI expand. How about that? Let's take a second and see what this is. Still the same UL. There's the first name, last name. But it's got an inner repeater-- an inner repeater-- that's going to get the session information from the related sessions. Pray for me. Error message. Did it again. What did I do? Did that. Well, that's sweet. Hey, it worked, sort of. Great. Maybe the console tells me. AUDIENCE: [INAUDIBLE] WARD BELL: Beg your pardon? AUDIENCE: [INAUDIBLE] WARD BELL: I'm doing something stupid. AUDIENCE: [INAUDIBLE] WARD BELL: You think I have a break point? Well, that would do it. You know, it's a good thing-- can I have you guys in my pocket? There you go. All right, and if I stay local-- presumably it stayed local. I've got to leave it there, duh. OK. BA, yes, thank you. So I'm staying local, and it's going really fast, and I'm getting all this stuff. So yes, it did work. You just have to know how to code. OK? You get the idea? Outer one, inner one, and Breeze, simply because of the expand, said every time I get a speaker, no matter how I'm searching for it, I want to get the speaker sessions right along with it. Of course, I could do that on the server. I could do it on the client. But I have a lot of options as I'm developing my client side app. What's my time? I've got how much more? 20 minutes. I've been going very fast. So that's nice. But I'm still dealing with essentially data bags. By the way, you guys can ask me a question, if you like. I'm still dealing with data bags. The stuff that's coming over is speakers-- first name, last name, just property stuff. We've seen the query thing. What can we do, though, now that we have the entities in cache? There's more things that you need to do. It's not just about querying. It's about change tracking and validation and stuff like that. So in order to introduce that topic, what I want to do is-- oh, by the way, you may have noticed that I never defined speaker. Did you notice that I never went through and described what a speaker was? I didn't say what its properties were? It just had them. That's a feature of Breeze. One of things it's doing is it's getting metadata to describe the model down from the server and it's using it, so that you don't have to code it. If you've seen other systems, you've probably seen where you have to describe the whole model in some kind of a DSL. You can do that also if you want, but you don't have to if everything's going well. So let me create a model class. Remember to save it model JS. And just so I don't forget, we want to make sure that we , load it. Load that script. So let me walk this for you a little bit. Well, it doesn't do much, right? It's the revealing module pattern. It has an initialize method. That's all it's got. And it's got something that it does at the beginning called extend. Here's the initialize. We'll look at that in a second. But first, I just wanted to show you that there's a a person constructor. So if I want to create a constructor, I can. I didn't have to before, but I can. And one reason I might is because I wanted to set some defaults. Like I'm a newbie, if I create a new person. And also, I'd like this person to have some behavior. And I can't send behavior down from the server. But I might like to have a full name property, and I might want to know if it's dirty, if there are changes being made to this person. And this is some Breezy stuff that actually gets that. So I've got that. Now I have to initialize it. And I'm going to go up to-- I'm back in the data context, my data access thing. And I'm going to get the model, because I'm using Angular dependency injection here. If I slow down, that may actually work. I won't make a mistake. So I've got the model. And now that I have the model, it had only one method on it, which was an initialize. And basically, I've just got to tell it about the metadata, which I'm going to get from manage. So really what I'm doing here is there's metadata store that describes the model-- all the relationships between all the objects and what they have and stuff like that. And what we've done is we've just evolved it with our own stuff. So you're not restricted to just the data bag coming down from the server. You can make rich objects that have behavior and additional properties and stuff. And all these can be serialized, too, if you want. OK. So we've got that. Let's kind of see how that works. So I'm going to go back to the HTML. And I want to see it. And so to do that, I'm going to use that full name thing-- NGI full name. Wow. Let's give ourselves some room here and see what this is really doing. LI, LI, LI, LI. It's a little easier if I make it smaller temporarily. Yep, it's looking good. OK. So forgive me, let's see if I can do it this way. So I'm going to get an input text box and bind it to the first name. I'm going to get another input text box, bind it to the last name. And I'm going to take that full name property that we wrote that we added to the person, I'm going to run that. See if it works. Oh, that's good. So I've got the input text box and the output text box, and I've got the full name property appearing here. So as I make changes, if I call him Bob-- oh, notice I must have some indication that it's in a dirty state. So I'm leveraging that as well. And I'm going to do stuff like that, which I know is illegal. Now if I had given this the ability to save, it would be interesting. But I haven't. The thing that's kind of cool here, though, is there's this dirty and all this stuff, but this is not part of the form. So I've just made this change here. And if I go look at-- completely, that changed the screen, right? I went off and got [INAUDIBLE] or something like that. And I go back, he's still there. So we're talking about a property, a characteristic of the entity, not of the screen. The screen isn't dirty, the speaker's dirty. Very important distinction. So let's put a break point in here and see what's really going on behind the scenes. And I'm going to put that where it does the get locally thing. Here. And let's do that. And now we're stopped. Give ourselves some room. And let's do a little spelunking of what we've got here. So we have a manager. We know about him. Yay? OK. And we can ask the manager, do you have changes? Tab. Not the Caps Lock. And indeed, we do. I didn't have to save. It's accumulating changes. It'll accumulate changes to anything, any of the entities it's tracking. It can be persons, can be sessions, can be rooms, can be anything. So let's take a look at the first one. And just a reality check. Yeah, there's Bob. Yes, he has a full name. So there's a way to find out. There's an entity aspect property on every entity. And that's your gateway into entity-ness. Normally we try not to pollute the object. It should have the features of a person on it. But every once in a while you want to get under the covers to see, how is Breeze thinking about this thing? And that's what the entity aspect lets you do. So I can ask about the entity state, because that's entity-ness. Yeah, that's right. It's modified. That's what I kind of expected. How about the original values? Oh yeah. So we know that has changed, and what's changed. And I said that it was a-- I gave it a really ridiculous name. I wonder if that's a problem. Let's see. Get validation. Because I could always mistype this. Yes, indeed, there is a validation error. The error message is there. So as you make changes to a property, it immediately validates them. You can disable that if you want. But that could be useful if you needed your form to immediately light up with an indication that this had an invalid first name. One thing's for sure, there are several other times. One of the times is save. So this thing will never even try to save. If I try to save this back to the server, it would refuse. It would refuse, because it failed to pass client side validation. Now of course, that's no substitute for server side validation, I just want to warn you. But it gives a better user experience to tell them that they screwed up on the client before you make that long trip to the server. And I can say, you know what? I don't like what's going on here. I want to roll it all back. And if I do that, and now I say let's continue-- and just so I don't have another break point, as you guys will take that out-- you will notice that Aaron is right back where he was. And of course, I took the break point out, because there was one more thing I wanted to show you. I think what I want to do, is although I could show you that, I want to stop, bring it on home, and then take your questions. So where can you find out more about this Breeze thing? Well, we have a lot of resources on our www.breeze.com site. For example, there's a live tutorial. So you can play with Angular and querying and all kinds of things there right on screen. We have lots of documentation that's sort of a guide. We have an API documentation, just like you would expect, for each of the components. We have a growing set of samples that we've written. We hope to have other people contributing them. And you can learn more about it at www.breezejs.com. And you can follow us on Twitter. And it's 7:33. I am ready for your questions. [APPLAUSE] WARD BELL: Thank you. AUDIENCE: So I noticed that you have all the dot net back end stuff. Do you have the requests that Breeze makes documented such that I could say implement a back end in Rails or Node your Java, or whatever else? WARD BELL: Yes. As a matter of fact, I've got it working against Node. I have a Node example that I would've loved to have trotted out, but I didn't. So that's a pure JavaScript side. We'll be doing a PHP version and a Java version. I don't personally know Rails, but I'm hoping to find somebody who will do that. Yes. Because our principle is that you can have any back end that you want. And if it doesn't, for example, provide metadata, no problem. You can create that on the client side. If it doesn't have the querying stuff, no problem. You can hit it just in any way you want. I make the claim, we're making the samples so that you can see it. But absolutely, we should work with any HTTP server back end. AUDIENCE: OK, cool. AUDIENCE: So does it mean that it works with the REST clients, too? WARD BELL: Would it work with the a REST client? Again, if it serves HTTP, yes. And there are a variety of ways you can do it. There's kind of a hard way the first time. But the whole way of interacting with the back end on the client is there's also a thing called a data service adapter, which allows you to also morph anything on the way in and the way out. We have an Ajax adapter, so you can pull that out and you can short circuit it for testing purposes. So yes, there's a variety of ways in which that could be made to happen. AUDIENCE: How does it handle the cyclic dependency between entities. So for example, parent has children and child has a parent. So usually in the data module, you would [INAUDIBLE]. So how does it come to the-- WARD BELL: How did it know which? I'm not-- AUDIENCE: How does it resolve the cyclic dependency? Basically, like say, for example, NHibernate you say, like parent has children. WARD BELL: Yeah. See, all of that would be on the server side. In other words, the whole language of whether it used NHibernate or any of the other ORMs or something like that, the key question is, how do I communicate those relationships across? And the only standard we know for representing data of this kind is OData. So it doesn't have to be an OData back end. But if your server can describe-- and NHibernate can or people who have front ends for it that can-- can describe it. Or if it actually is an OData back end, no problem. If it isn't and you can describe it with OData metadata, and we're providing components for you to do so, then it's good. You can just send the stuff from the server. If not, you can describe the metadata and all the relationships in JavaScript with the metadata store object. And actually, you could cache that and serve that. You could keep it locally. So you could make it very fast, if you wanted to. AUDIENCE: So does it maintain the cyclic dependencies? WARD BELL: Oh, yeah, you mean cyclic, like orders have? Customers have orders, order says what's my-- yeah, yeah. It breaks all of that. It breaks that chain. It knows all about that. Absolutely. I know what you mean, because you can get into serialization trouble. And virtually any real model has cycles in it. So yeah, yeah, yeah. AUDIENCE: [INAUDIBLE] WARD BELL: You're talking server side stuff now. And so it depends. The answer depends on the server. In this case, I'm using JSON.net and having it break the cycles. But also the way we represent the data, the way we configure it to represent the data, breaks cycles.
A2 初級 三月 - AngularJS MTV Meetup Livestream。使用Angular和Breeze的CRUD應用。 (March - AngularJS MTV Meetup Livestream: CRUD Apps with Angular and Breeze) 62 6 101 發佈於 2021 年 01 月 14 日 更多分享 分享 收藏 回報 影片單字