Angular 13 Fundamentals Component Driven Architecture
Transcript from the "Component Driven Architecture" Lesson
>> Let's talk about component driven architecture. The idea in and of itself is not super, I think we don't have to do too many leaps of logic, that we simply divide our application into small encapsulated pieces of software that can be reused in many different contexts. So Angular, fortunately, strongly encourages this by making it easy and in a lot of ways necessary to build out every feature of an app as a component.
[00:00:35] And so we can think of Angular components as these kind of self encapsulated building blocks that contain their own templates, styles and logic. So you can pick them up and you can move them elsewhere. Also not in the slide, but I will point this out, is not only does it contain logic, but more importantly is that you can write them in a way that they do not contain logic.
[00:00:57] And that's even better. So if we look at the anatomy of a component and how that component work together, we can see that obviously we have property bindings and event bindings. And the question that I have is, what if we could define custom properties and events to bind to?
[00:01:23] So, hm, do you think that's possible? Well, I've tricked everybody because it is, you walked right into that trap, oldest trick in the book. So we can create custom data binding on our events and our properties in the form of @inputs and @outputs. And so I've prepared a little slideshow to illustrate this point.
[00:01:53] When you have a parent and a child component, where is the surface area? Where do they intersect, On the template? So if you want to put a component on the page of an application, how do you do that? Well, you add it to a template, so that it can then be instantiated and become part of the application.
[00:02:22] So in this case, we have a parent class and a child class and they share a template. And so this is the relationship, we're separating the overlap and from within the child component, we have a template and a child class and this is standard event property binding. So from here, if I want to take a property from the child class and I wanna render in the template, I just use property binding.
[00:02:57] If I want to capture an event from the template, then I will add that or I'll capture that into the child class. Now, on the other hand, from the parent component, if I want to put something into the child, I do that via @input. And if I want to capture something that's happening from the child into the parent, that is an @output.
[00:03:26] So I think thankfully, the English language has not completely broken down, in that we're putting data in, we're getting data out. And so this is, at a high level, this is what this looks, is we're passing data into our class via an @input and we're getting it out via an @output and I realized that these are backwards.
[00:03:53] I'm not gonna fix this, but I will update this a bit later. So an @input allows data to flow from a parent component to a child component. And we use the @input decorator and then we bind to it in the parent template. So in this case, we have a component that has an @input of greeting and we are going to render that using string interpolation in the template.
[00:04:23] And then in the parent component, we are able to pass that in, whatever greeting that may be, into the child component via property bindings as an @input. Now an @output, how this works is because using event binding, we're binding to a native DOM event. Well, we can use the EventEmitter, so it essentially is an instance of the EventEmitter that we expose the EventEmitter so that when we want to trigger it, we can call EventEmitter.emit.
[00:05:00] And so what we're doing is we're basically dispatching or emitting an action from the child into the parent as an @output. So in this case, you can see here that we have an @output of greeter and it is an instance of EventEmitter. And when we want to emit that, then we do this.greeter.emit, and we pass the value in that we want to surface or bubble up to our parent, and then we're able to bind to this just like a normal event.
[00:05:37] And you notice that it's greet and then $event for the payload. And what this does, so we've kind of focused in, but I wanna zoom out just a bit. That why this is important is because we are now able to establish an agreement between a parent component and a child component or between a component and anything that wants to use it.
[00:06:08] So this is in a sense a component contract. So this is where, essentially, it's an agreement between the supplier and the consumer. And our inputs and our outputs work as essentially the API interface for that component. Also, it works really well as kind of a visual cue about how to interface and interact with a component.
[00:06:38] So one thing that I'm not going to get into much but I'm going to just offer a small comment on is that when we look at Angular and, by extension, React and modern web frameworks, it is allowed us, given us the opportunity to turn our HTML into a DSL.
[00:07:03] Meaning we can create markup that adopts all of the semantics of our particular business domain. And so, what this means is that you can have a non-technical stakeholder look at some markup, and they can say, well, I know what an items list is, or I know what a contracts list or whatever it is, they can look.
[00:07:29] And because you're adopting semantics that are familiar to that domain, non-technical stakeholders can look at even markup or code. And it's very easy for them to kind of make sense of what's happening. By even defining the specific inputs or properties that you can use to hydrate that component, as well as the things that that component can do, i.e., the events or the outputs, is that.
[00:07:59] Imagine you had an application for law and you had a client and it's like they were able to omit a litigate event. Well, that doesn't mean much to me but in the context of maybe a law firm, when that event is omitted, that means something, it's very meaningful to them.
[00:08:22] So it's important to at least register that by using inputs and outputs and component driven architecture. Is just a natural byproduct, we are able to establish a domain-specific language for our application which I think is, it's really, really powerful. And I will say this, that a lot of times there's pushback from engineers about getting non-technical stakeholders involved at the code level.
[00:09:00] So for instance, I really like Cucumber when I'm doing automated end-to-end testing because I can establish or define my specs in a natural language that is very similar to how you would speak something. As a user, when I log in, I should be on this page. And so, this allows for product owners and stakeholders to look at these Cucumber specs and they serve this kind of documentation or acceptance criteria for how that works.
[00:09:38] Same thing with these components. The pushback is that, well, nobody would ever do this or I'd never seen it. And I think for me the question that I immediately go to is, well, how would they have seen it? That we historically do not create opportunities for non-technical stakeholders to interact with engineering in kind of a meaningful way.
[00:10:01] Is that we create kind of these secret handshakes that you got to come to the back door and knock a certain way to be led in. When I think, as engineers, we should endeavor to make the code that we write and the things that we do to be as approachable and as understandable as it can be to everybody within the organization, starting from our stakeholders, but ultimately to our end users.
[00:10:28] So I don't know where that came from, but I feel very strongly about it. So, now, what this allows us to do, queue container presentation components. I've been waiting all day to answer this question, or at least fulfill this request. This allows us to create nice, neat containers with clearly defined data flows from the parent to the child and back.
[00:10:57] So this is container and presentational components, aka, historically, it was smart and dumb, components apparently that, I think what happened is it really offended a lot of smart people and they didn't like that. So it said stop disparaging me when you're talking about smart components. I'm totally kidding, that's hilarious to me, I'll laugh about it when I'm off camera.
[00:11:23] But container components are your kind of large components that they are responsible for, I would say, collecting the data to make available to its child or presentational components. And presentational components, on the other hand, are small very specific components that are defined by their bindings. And so you can think of that all data goes in as inputs, every change comes out is an output.
[00:11:56] And you want to create as few container components as possible and as many presentational components as possible or appropriate. And so, this is a presentational component. We'll kind of build this out in a moment. But you can see here, there's not a lot happening. It's just data bindings.
[00:12:25] On the other hand, this is what a container component looks like. So this is more responsible for one interfacing with an external service to get the data or to establish the query side of the command query cycle. As well as issue commands or execute or call methods on services to handle the business logic outside of the component.
[00:12:52] So, what this means is state flows down. So you have a container component that's saying get all the data and then it's taking bits and pieces of the data, some of the data, and saying, here, you get this component or this data, and component, you get this data.
[00:13:13] And it's consuming just enough to render the templates, but then it's also responsible for segmenting it out so that the individual presentational components are getting the data that they need as well as they have the ability to surface the appropriate events for that component. So, state flows down, and events flow up.
[00:13:39] So, within a presentation component, it says hey, here's this event, route it, do something with it. And then in the container component, it's saying, hey, process this event. And here is the kicker of the whole thing. So remember, state flows down, events flow up. You basically understand redux.
[00:14:05] So double WAT. And this is true, because remember I said at a mezzo or medium level, component driven architecture is a representation of a pattern that exists across various scopes within the application, kind of structure itself from a micro interaction to a macro concern.