skip to content

Angular is so back

Devs are excited about Angular again. In this episode, Mark Techson from the core team will teach us how to build a web app using Angular v17.

Full Transcript

Click to toggle the visibility of the transcript

Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.

JASON: Are we live? We're live. Hello, everyone, and welcome to another episode of Learn with Jason. Super-excited to have you here. And today on the show we are bringing in one of my favorite people in the industry, Mark Techson. Mark, how are you doing?

MARK: Let's go. Listen, the streets don't know that you are the coolest thing happening right now. I'm being for real. You are so cool. Got to meet you. When did we meet? We met in person a couple times, when was the first time?

JASON: It was at a conference, but I don't remember which one.

MARK: At a conference, we hung out a party and spent way more time together, and man, I'm glad to be on the show, thank you for having me.

JASON: I'm so happy you're here. exciting. You and I have tried to work together, timing, project load, it just hasn't worked out. We got it this time, we made the connect. And today we are gonna talk about a lot of fun stuff. Before we do that, I want to talk about you. For those that aren't familiar with you and your work, do you want to give a background and what you do?

MARK: Yeah. This is how I describe myself, I'm Mark, a developer relations engineer and a motivational speaker. Get that more out there. That's part of my life, being a motivational speaker, inspiring people to live their best lives, in a particular age range, those 40 plus, it's really hard and we still have dreams. And I want to help people do that.

JASON: We're getting love for that in the chat. You do mornings with Mark. Which I absolutely adore. It's taken everything I have to not directly steal that format. Because it's so good.

MARK: Listen, Jason, you don't understand. When I saw Learn with Jason, damn it, I know him so I can't steal it. You don't understand. It's such a good idea. Even the format with the logo, is there a variation I can do? I get that feeling of being inspired by your peers. Damn it, this is so good. But I can't take this because it's their good thing.

JASON: So, no good. I'm getting asked to links for Mornings with Mark. Where's the best place -- do you have a collection somewhere?

MARK: Yeah, you can find them anywhere online. But find all of them on Instagram @marktechson, on YouTube, @marktechson, those are the best places to find the full collection of what I have been doing.

JASON: All right. Let me... I... wait. What?

MARK: And I'm gonna eat a Pop-Tart because I'm hungry.

JASON: Instagram.com, Mark Techson. Hold up, I'll show you and tell me what I'm doing wrong.

MARK: have I been hacked?

JASON: It says the page doesn't -- there's no at symbol. All right. There it is. Okay. Let me -- why am I not following you? I didn't know you were on Instagram.

MARK: It's okay. The betrayal begins already.

JASON: Right out of the gate. All right. Let me get this out of here for now. And okay. So, I mean, I've loved that stuff, the inspirational speaking you have been doing is amazing. I also love one of my favorite things about watching you online is your relationship with your son and how you always refer to him as the heir. And that is like one of my favorite -- one of my favorite --

MARK: Thank you so much.

JASON: So good, so good. So, let's talk a little bit about Angular, right? So, Angular is one of the things that you're focusing on professionally. It seems like there's a lot going on in the Angular world these days. Pretty exciting stuff. So, let's hear -- I mean, let's hear it. Let's start wherever you want to start. What's up with Angular?

MARK: So, the thing that I'm telling people nowadays, which I think rings true, is that Angular is back like we never left, right? When I say we're back, we've just taken some time, looked at a lot of evidence, listened to a lot of our community and we have been able to update the framework to meet developers where they are right now. Because so, thing Angular in general, like a big, big picture. Like we were some of the originals to a lot of the paradigms that are popular in frameworks that you know and love. Like you could find traces of Angular throughout just kind of popular frameworks. You could look at Vue, look at Svelte, look at a lot of these things and say, oh, yeah, these are things that Angular kind of pioneered. But we had this really interesting time period where we knew we had to make a significant core change to the framework before we can get to where we are now. And that core change took us a little while to do. And, you know, a lot of frameworks came up with a lot of great paradigms and great ideas since then. Now we have been able to learn from what our peers in the space are doing and then even innovate in some ways, which I hope we get to do, look at the features and we are actually innovating again. It feels so good, Jason. It feels so good to be back in a place to create things that help drive the web forward and not make it a holy war between Angular developers and -- look, here's some great ideas you have, here's what we have, let's push it all forward.

JASON: I love that. And I actually, I mean, this is one of the things that got me excited. Because I, you know, for better or worse, even had a lot of Angular content on the show. And a lot of that came from feeling Angular settled into a groove, it was down its thing. It was part of the JavaScript Community, but sort of held apart and that really feels like it's changed. The relationship that I've seen that angular has to the community feels very much like they're paying attention, they're pulling in good ideas, they're sharing good ideas. It feels like Angular is back in the game as part of the JavaScript Community, part of the frontend Community in a way that feels collaborative. And that's new and that's exciting. And I think that was kind of what got my ears to perk up. And obviously, you know, having folks like you, like Jessica Janiuk, so many good -- wait. Hold on. What just happened? I summoned her. JESSICA: Thank you so much for having me. Mark, why are you here? Isn't this my time to be on the show?

JASON: Jessica, I'm so sorry. I think you got your dates wrong.

MARK: Yeah, what's going on? Aren't you supposed to be on holiday or something, Jessica? JESSICA: I thought you were supposed to be on holiday. Wait, I think I know -- I think I know what happened here. You said "Mark this date on your calendar," and you meant Mark is on this date. That's --

JASON: Oh -- we let her on the show for 15 seconds...

MARK: 15 seconds. JESSICA: It's an easy mistake, if you think about it.

JASON: It is -- it is an easy mistake. JESSICA: Well, I guess while I'm here, do you mind if I ask a couple of questions since Mark is here?

JASON: Please, take it away. JESSICA: Mark, I have a couple questions. Curious, maybe you could answer these. There are several parts of Angular that have really interesting names, mark view dirty, performance mark, mark view for refresh. I was curious, how did you go about licensing your name for use in this open source project? And how do the royalties work? Do you get royalties?

MARK: You know, it's one of those things where getting my legal team involved early it a difference here, Jessica, and that was the differentiator. JESSICA: I see. I would love to learn more about that. Maybe I can find you afterwards and we'll --

MARK: Sure, I'll be signing autographs and all -- JESSICA: That's great.

MARK: We'll have a meet and greet. JESSICA: Your last name, Mark Techson, I'm curious, what nationality is that?

MARK: Is this from the Intel nation in a little region called x86. JESSICA: Ah, ah, yes.

MARK: That's kind of where it came from. JESSICA: And where in the world is that?

MARK: It's just in a place. It's right under the architecture islands. I don't know if you heard that have before? JESSICA: Like archipelago.

MARK: The Architecture Islands. There's a queen there, she came up with Thompson to Techson and married him. JESSICA: Wait, your last name isn't Techson?

MARK: I'm gonna be like Jaime Foxx. I will drop Thompson, y'all think I'm joking about this. Friends at home, look for Mark Techson at a stage near you. That is the name I'll be using hence forward. JESSICA: Okay, well, I've only got like five or six more questions. You work with a lot of people on the Angular team. And I'm just curious, who is your favorite person on the team?

MARK: There's this person that's been following me around geographically for a few years. We lived in the same neighborhood in California. Grew up in the same area. JESSICA: Yeah, yeah.

MARK: She's great. She has a lot of puns. I can't think of her name right now. But she's great. JESSICA: I think I know who you're talking about. Okay. Okay. That's interesting to hear. I'll have to share that with the rest of the team. I'm sure they'll be thrilled to know that you have a favorite person on the team. And I guess -- I guess I'll just kind of wrap it up with one more question: Can I have your autograph?

MARK: You can. I'm gonna do that. I'm gonna send you a piece of paper with my signature on it. JESSICA: Okay, great. I'm so excited. I'm such a big fan, Mark.

MARK: You got to pay shipping and handling, though. So, be prepared. JESSICA: I don't know if I can afford that. But we'll see. We'll work it out. I think I've probably interrupted this enough. Since I got my schedule mixed up. So, I'll just leave this with: It's good to see you both, as usual. And happy holidays to both of you and to your whole audience. I hope you have a wonderful new year. And I'll see you in a few weeks.

JASON: Yeah.

MARK: You take good care. JESSICA: You take, you know, the usual care.

JASON: Bye, Jessica.

MARK: Bye, Jessica. Shoutout to chaosmonster, shoutout to you. I know chaosmonster from other streams. Shoutout to you.

JASON: This was -- that was a lot of fun. I'm so glad that I switched over my streaming architecture recently which allows me to have like additional guests. I used to only be able to have like one guest at a time. And so, ask me four months ago, that this would have not been possible. But today? Unlimited guests.

MARK: Why did you let her trick you into coming on to the show? That's my question. Why would you allow that? You let her trick you.

JASON: You know, I was at a conference with Jessica recently and I was the emcee. And she was one of the speakers.

MARK: Yeah.

JASON: And they had like a moderated Q&A. You could submit a question and I got a list of questions while I was on stage. And she came up with the most horrific pun-based questions for every single speaker. And honestly, it's -- you know, being sincere for a second, I actually think Jessica is one of my favorite people in tech because she -- like she stuck through the whole conference, she was there, paying attention, she came up with puns. It's so nice to see somebody who is truly engaged. And again, this points to what we were talking about before she came in. The -- the change that I've seen on the Angular front where we've got people who are -- they're like in it. Like you are in the community, Jessica is in the community. That's really impressive. And really kind of like gives me -- it gives me a lot of energy. Makes me kind of want to pay attention to what's going on. So, from -- with that whole tangent aside... let's talk a little bit about some of the specifics.

MARK: Yeah.

JASON: So, you know, Angular has gone through this sort of transformation. It's coming back to be real collaborative with the community again. What are some of the things that you're seeing? Like what are you excited about?

MARK: Oh, I think there are two big things on the horizon for Angular that we'll -- that just continue to make developer experiences special for our developer community. And the first thing is defer, right? Defer which is this idea that you could lazy load a part of your template and your component. Like that -- that just feels like magic. And every time someone asks about the feature, I think defer is magic and something we're see. It's almost like an island like in other frameworks, I think Astra had island architecture. Except this is declarative at the component level. With any component, this part of the component, do not load this. Right? It's a couple lines of code. Not like the older kind of patterns we have been known for. Nobody is in the dark about Angular being complicated at times. We know that. The way we implemented this thing, anybody, even a junior developer, can implement the default behavior for defer. And I mean, junior developer, experience, not indication of skill. But think about lady loading in general, that's a task that's traditionally a little bit more advanced, requires more effort. Nope. Wrap it in a defer block and it's done.

JASON: Cool.

MARK: It just works. It's so good. The big talk we have been doing is about signals. We already landed signals in Angular with version 17. Excuse me, production-ready signals in Angular, which is huge for us. And I think what's gonna happen next that's special is when our reactivity system in general is based on signals. Right? We migrate our community at, you know, one part at a time. Which is something I think Angular is kind of unique about. Where instead of like making people branch off and, well, you're stuck on Angular 16 and Angular 17 uses signal. Nope. Angular 17 has support for signals and you can migrate whether you're ready. And when you're ready, we're gonna give you the tools to migrate? Right? We also write migration scripts. Like Ruby on Rails is -- new project.

JASON: Right.

MARK: Run the scripts to upgrade. We do a similar-style thing where you can get tools from us -- first party -- from us, that migrate your code to new things that we release. We try to do that whenever we can.

JASON: Yeah. That sort of thing is I think one of the things that I think is like a super power of Angular is that Angular thinks long-term in a way that I haven't seen a lot of other JavaScript ecosystem tools think. Like one of the thing -- and I won't name names. The goal is not to despair here. The point to draw attention to the fact that an Angular codebase is intended to live for years.

MARK: Right.

JASON: And you can tell in the way that the API stays stable. In the way that I've heard people on your core team talking about things that they would love to change, but they won't because it would break the community, right?

MARK: That's right, that's right.

JASON: And so, there are these really interesting things about long-term support. The migration tools that mean that when you choose Angular, you don't to think about, well, the next major version we have to dedicate 6 months to overhauling our codebase to be on the thing. You run the migration tool and it's pretty confidently going to be on the new version without you having to make any code changes, right?

MARK: Right.

JASON: That's an attention to detail that's thinking about teams and maintenance in long-term. That's also one of the reasons that I think whenever I see people using Angular, it is almost always on huge applications. Like big enterprise teams with lots and lots of requirements. And it's because of that sort of attention to detail. I think that shows through.

MARK: And the enterprise thing is such an interesting parallel. I think we live in an age where people can spin up -- when you and I started development years ago, spinning up an application and deploying it someplace was a big deal. It wasn't as turn key at now, go to Netlify or hosting, not even that, you can go to GitHub pages and get your application.

JASON: Right.

MARK: That's how far we have become. But what's forgotten in the application is the goal of every application is scale. Like that is the goal of every application. So, when people say "Enterprise," you know, I see it kind of thrown around in like a negative light. Oh, that's only for enterprise. You would be so lucky if your project became an enterprise-scale project. That's what we all want. Nobody builds something, I only want to handle 30 users a month. You want 500,000 users a month, you want thousands and thousands of requests. You want that enterprise scale. Unless you're building a project app for like, you know, bake sale in your neighborhood.

JASON: Right.

MARK: Fine, that makes sense. Maybe you don't want to use something that's built with scale in mind. But if you think about scale being the goal of most applications, most businesses, Angular uniquely positions itself in that place. Where like whether you're ready, we'll give you a lot of tools to start. And then as you grow with the goal of being at scale, we're gonna be there and give you tools along the journey, which I think is unique to Angular in a lot of ways.

JASON: I -- yeah. I couldn't agree more. Sorry, I'm getting distracted by the Twitch side chat because it's getting out of hand over here. I have -- back here in the corner I have this rabbit.

MARK: Oh!

JASON: It's a rabbit with the mustache and the monocle. I put it in the background, thinking this will add some visual interest to my set. Didn't thinking it was derail the chat.

MARK: It's its own thing, and if you move it, Jason sold out. He moved the rabbit. Rabbit is gone.

JASON: So --

MARK: Yeah.

JASON: You just ran through an absolute laundry list. I'm gonna have Jessica who we saw a few minutes ago, she's gonna be on, on January 11th. And dig into defer. That's a feature she sort of led, right?

MARK: Yes.

JASON: She's gonna be digging into defer and a few other tricks and treats in the Angular set. So, make sure you mark that on your calendar. You can add a reminder on YouTube and -- let's see, YouTube, LinkedIn, wherever you're watching from, you can add a reminder for the next one. Quick reminder, like and subscribe and share this video with people. It helps get more people to see it, which means I get to make more of them and we get to keep having these ridiculous conversations about rabbits.

MARK: Jason, can I tell you a trick about YouTube livestreaming? You can get a point -- you can get a URL to the next live video on YouTube for your channel.

JASON: Is that true?

MARK: Yes! Yes.

JASON: Oh!

MARK: I set up Angular, GOO-G-live, always goes to the next video.

JASON: Cool. I love that. That's a very good idea I will be looking into.

MARK: I will DM you later how to do it. It's available to everybody. I love that. You can mention all the platforms that you can find yourself. And you can just have a link to the next live video. Whatever it is.

JASON: That's super-handy.

MARK: It will point to it.

JASON: That's a pain point, I have to remember to switch the URLs out. I apologize, you need to Jessica that on your calendar. And we got a very relevant question from the chat, Jason Torres wants to know, what's on the feet today?

MARK: Black Cat 13s.

JASON: I don't know what those are, but I bet they're dope.

MARK: No, good question. Jason asked what's on the feet today? My whole thing is Go Chainz and Jordans when I'm presenting. People don't know why I do that. Can I take a minute?

JASON: Please.

MARK: Here's where Go Chainz and Jordans, and I would go to schools, Polo and button up shirt and slacks. And I couldn't get these high school kids to look in my direction. They wouldn't pay attention. One day, I was out on my normal day and I was like, oh, crap, I got to make sure I get to the school. I will not have time to go home and change. And I had on a pair of Jordans that day. I heard them in the class, look at his shoes. Look at his shoes. That's the secret? That's the secret to get your attention? And then I was like, okay. I'm gonna make this about, you know, always wearing Jordans to let them know that you could have any type of career you want. Like, of course, if I was a lawyer, maybe got to wear a suit. Like in tech, you didn't have to fall into the mold of what people look like. And I was like, you know what? I'm gonna start wearing Go Chainz. And then wore one small Go Chain. I wore a small one, and someone was like, they hired Tupac to do Angular videos. Oh, you want to see Tupac? Cutting up and acting out? I'm gonna show you. Since then, I couldn't go on stage without fresh Js and Go Chainz to show you can be smart, talented, and be authentic to whatever is authentic to you. This is part of the culture I grew up in and I felt like I had to hide for so long when I first got into tech. And I didn't want to do that anymore.

JASON: Yeah, I think -- that's such a -- that's a great reminder. Because the other thing that I would note is that your approach makes you unique and notable, right? Like you're not another suit. You're not another like collared shirt. You're out there being yourself. Teaching people in the way that you want to teach people and this helps me remember, oh, yeah. And like if you're trying to describe somebody. It's hard to say, well, you know, the tech guy with the hoodie. Yeah, okay. Which one? But if you say the guy wearing the gold chain and Jordans? How many are wearing gold chain -- not many. And that's -- if you can find the things that make you comfortable getting up and being yourself and that allows you to bring more of yourself to the screen or to the stage or to the conference room, it just -- I don't know. It makes me feel like I'm more in my skin instead of putting on my work skin, you know?

MARK: That's right, that's right.

JASON: And as odd at that feels at first, that tends to get better results. People respond to real people.

MARK: Just being yourself. Angie Jones, one of my favorite humans in the universe, be you, they'll adapt, they'll adjust. I start to do that more and more. What's wild is I have seen more success being myself than trying to fit into what I thought people wanted me to be.

JASON: Jessica has asked me to ask you about hosting game shows.

MARK: Okay. So, we talked about this, Jason. But I want to quit tech in general and become a game show host. Like I want to do that for the rest of my life, to be honest with you. I do get some chances to do that. At ng-Conf two years ago. I got to host Family Feud. That's why she should I was like Steve Harvey. Internal tech conferences at Google and I did hosting. Talking with people, engaging with people, having a good time, telling jokes. Man, that's me at my purest form of what I dream of. And I love tech and I love teaching. But I do want to quit and just go to Hollywood and become a talk show host.

JASON: This is reason I like you so much. I'm trying to go the same way, but with producing stuff. So, my -- I'm -- I have a game show treatment written up -- and I've got you earmarked for it, anyway. I'm trying to get a company -- I need a tech company to understand how much more impactful it would be to do a game show than it would be to spend that three quarters of a million dollars to have another conference that you got to give away all the tickets to. If we make the Great British Bake-off for nerds, do you know what's gonna happen? It's gonna go absolutely off the rails, to the moon. It will be incredible. Tell your bosses you want to watch game shows and tell them to sponsor me and get Mark to host it.

MARK: You got me with the buy-in, do you know what's gonna happen? That in my heart let me know how much you believe in this idea. As soon as you said that, that's it right there. I started clapping. Because he believes me, I believe it. Let me know. If you want to do a pilot, I'll be there. You just make it happen, bro.

JASON: Absolutely

MARK: Set it up, I'll call my agent. Agent!

JASON: Is your agent the air?

MARK: Agent, dad needs to go to host a game show.

JASON: I love it. Now we've got the chat in over on Twitch is coming up with Tupac-themed Angular songs.

MARK: All eyes on the ng -- I like that.

JASON: From Tupac.

MARK: Thank you love -- �

JASON: Want to be a thug -- come on, get out of here with that.

MARK: The streets are with us, man. I love it. I love the energy.

JASON: This -- okay. How long have we been on the air? We're gonna get nothing done.

MARK: Okay. But you see how much fun we're having?

JASON: Yes.

MARK: This lets me know that you and I -- we have more -- there are other worlds than these, we have more things we can do in our future together.

JASON: Absolutely, absolutely. We talked about Jessica's episode. There's a link for that. I'm gonna throw that up just in case you want to continue on with whatever shenanigans we're doing. And then let's -- we're talking to Mark today.

MARK: Yeah.

JASON: This is Mark on Instagram. This is Mark on Twitter. And it's about to be Mark on Angular. So, here's a link to the new Angular site which is freaking gorgeous, by the way. Let's look at this for a second. Let's everybody, just take a deep breath and be ready to be amazed. Just watch it go. Oh, look at this side. It's so good.

MARK: That thing is clean. That thing is cle-e-ean.

JASON: And then it comes into editable code snippets to try stuff out. This is very clean. This is one of my favorite sites I have seen in a while for a framework. It's beautiful, fun to use.

MARK: And you got a sneak peek of that thing, and gave us great feedback. We took that. We took that evidence. We're evidence-driven. When we listen to the community, I took everything you said, wrote it up in a doc. Listen, listen, friends. We got some things that we didn't expect people to do, but they're doing. Oh, that makes sense. Let's make some improvements. So, this site is in beta. So, we're continuously improving it. There's Angular. io which is our regular site. This is the future site of Angular developers. You can learn here, you can learn in the browser, you can build projects in the browser. I mean, we're really cooking with this thing.

JASON: Love it, love it, love it. Oh, god. Jason and Markdown -- come on, now.

MARK: mm! The Jason and Markdown show! We got go. That's it, that's it, that's it. Jessica Janiuk is having a field day by saying these puns. I'm sure she's just losing it.

JASON: I hope you're having a wonderful day, Jessica. This is definitely the highlight of my week so far. It's so -- okay. I want to play with Angular. I have used Angular very lightly. Actually, I did a lot of Angular during Angular one, back in 2014, 2015.

MARK: Yeah.

JASON: I did a lot of projects then and sort of drifted away from it. I took a project, using React, and the next project, I think I was doing Eleventy or something. And I've just sort of spiraled off into now I do whatever it is I do. I don't use anything for longer than 15 minutes. But I'm excited to come back and see what's going on with Angular.

MARK: Let's do it.

JASON: So, if I wanted to give this a try, what do I do first?

MARK: First, let's choose your adventure. Do you want to do local or in-browser?

JASON: Let's do -- let's do local.

MARK: Let's do local. Get a terminal up, some access to the terminal. Install the Angular CLI, our tooling suite, okay? I'll give you the command for that.

JASON: All right, I'm ready.

MARK: All right, you want to do npm, I, and dash G for global. It's up to you. And then at -- the at sign -- Angular/cli.

JASON: Okay.

MARK: Boom. That gives you our tooling and scaffolding tool. You can see it's really robust, really powerful, gets you lots of stuff.

JASON: Okay. And the -- oh, wait.

MARK: You got to do the ng space version. No dash, dash.

JASON: No dash, dash.

MARK: I don't know why we did that. That's con newsing to even me.

JASON: Would I like to -- share pseudomas. I'll give you the data.

MARK: We want to make it better, I promise.

JASON: Angular 17, I'm on Node 20.

MARK: Perfect.

JASON: Excellent. I'm ready. I'm ready.

MARK: Look, got the fire on, the stove, start cooking, baby. Here's what you can do, make the first application with the scaffolding told, ng, that's short for Angular, new, and say whatever you want to call it. You give it a name.

JASON: All right. Let's call it... let's call it Angular-is-so-back.

MARK: So back.

JASON: All right.

MARK: All right. Choose your styles. Do you want to do CSS -- let me explain why this is important. We do not have our own subset of CSS. You can use whatever the browser supports. Write in these formats, CSS, less, or SaaS, or S-CSS. Whatever you're comfortable with, you use it, it works.

JASON: I'm gonna use CSS.

MARK: Now, this is if you want to do static site generation. This is about the server side story. For the first one, you don't have to enable this, you can do no for now.

JASON: Okay.

MARK: Done. Application is created.

JASON: Okay. We're doing the install like that.

MARK: That's a quick update of all the things it's gonna make for you. We could have reduced these files if you wanted to a smaller set of files. But this is what we send by default. Comes with other stuff. Here's what I want you to do in your VSCode editor. Because you want to have all the tools working in your favor, you want the Angular language service.

JASON: Nice. Look at it go.

MARK: Install that joker. Let me fell you what it's gonna give you. Angular Templates, you can write HTML, but also Angular code. The Angular language service gives you things like type information in your templates. Like in the HTML you could like click on a component and it will navigate to the right place. Give you some operations that you normally would not have in your HTML template. That will treat it as a regular HTML. This will give you superpowers.

JASON: Got it, got it. Cool, cool, cool. We got that, it is installed globally. We should be in good shape there. And then if I pop open the code editor here. Let me actually -- let me initialize this, so we can see what's going on over here. And this is our project.

MARK: That's your project. Feeling good, feeling great. You want stood a walk through of some of the highlight files.

JASON: Yeah.

MARK: At a high level. Some of the cool things no know about, Angular.json, you don't have to go in there. There is a lot of configuration, this is your project configuration. You can do a lot of things in Angular. One of the things that Angular by default supports is the monorepo, you can have multiple projects inside one workspace and you're noting to reinstall those dependencies, it will work. That's why there's so much configuration here. You can have that and you can configure other parts of your application. So, when it comes to at configuration, you can update this file. But hear me out. Because people will look at this and be like, this is a lot. You don't have to do much editing here. Our tools will usually update this for you.

JASON: And this is something that I've noticed is that Angular has a lot of -- like something like this I think I would typically refer to as a boilerplate file.

MARK: Sure.

JASON: But what I remember being painful about boilerplate is I had to sift through a lot of config docs and figure out what each thing was and how they fit together and with this, it's more like if I want to change something, I would say, ng, what is it generate is the command?

MARK: Sure, you could do generate.

JASON: That will put in a new thing and update this for me. This is something that Angular has done for a while. It's something that I think is really clever. It's also something that like other frameworks are picking up. Like if you look at way that Astra handles it. They've got config, but they update it from the CLI whenever they change it. So, you're rarely in the config yourself and I think that's really good.

MARK: And this is a thing -- advanced users, oh, I go right in there and then I open it myself. But look at chaosmonster. I open it maybe once a quarter if at all. That's the experience. I'm opening this when I'm learning about Angular's internals. Open this. Okay. We're gonna do internationalization, let me try to understand some of the settings. Then I'll be in here. Usually I don't have to open it. Angular.json, that's the place to find out about the Angular configuration. Let me show you where the magic happens. Go to main.ts.

JASON: Here.

MARK: This is the bootstrap. If you're a React person, just to let you know, there's one point, render DOM, that one call in your index.js. Here's the main component that you're going to render in how to kick off your application. Well, here is our version of that bootstrap process on line 5. You have bootstrap application, which application are you bootstrapping center? At component and the configuration, the app config, we can go into that when we need to. But that's another place where you might specify some other configuration like routing, for example, or this idea of your providers. That's a little bit more advanced. A person just started, doesn't need to necessarily know about this. But oh, yeah, I configure routing for the application. Or add SSR later. It's one line to add to it.

JASON: Got it.

MARK: This is a more advanced file. But you come in here when you're ready to start more configuration of your application.

JASON: Makes sense.

MARK: Two files, start off with main ts appConfig. How do I know what's on the screen? Let's go to your terminal. Let's do an ng and then serve. We use Vite as a Dev server. And it comes set up for you. Right? So you don't have to do anything extra. Out of the box.

JASON: And this is, I think, another really cool thing is that Vite has sort of become the Rosetta Stone of local Dev if not for serving. With Angular adopting Vite, I don't know if there's anybody left that's not using it in the major framework players. That's really exciting because it opens the door for really exciting stuff as we have seen with Astro, for example, which you can use just about every framework inside of Astro. That's freaking cool. And I think we have an Astro Angular integration now if I remember correctly.

MARK: Let's go.

JASON: It is super-cool. Like huge props to the Vite team for making something that we can all universally agree on. How often does that happen? Where am I going here? I need to get to this one. So, let's put the code over here. And then I will open up -- okay.

MARK: Done. You got a fully deployable application. You could deploy this, right? With the configuration you have right now. It's deployable and it will run. Like in you deploy to Firebase, for example, which is a two command step. If you wanted to -- like high level -- you would do ng add to add Angular-specific packages. You could do ng add, Angular Fire, and ng deploy. Those are the two commands.

JASON: Nice.

MARK: If you had everything set up on your Firebase side.

JASON: Nice.

MARK: That's a demo I would normally show people. We want you to be productive from the start and make sure we're out of the way whenever we can be.

JASON: And that's great, I just realized before we go another step here, I want to do a quick shoutout to our captioning. Because I forgot to do that. So, we've got Amanda here with us from White Coat Captioning today taking down all these words. The ticker that's going at the bottom of the screen here has the link if you want to see the live captions. Still trying to figure out how to get live captions into Streamyard. If you know, let me know. Made possible through the support of Netlify and Vets Who Code. Thank you very much for kicking in to make this show more accessible. Those sponsorships end at the end of the year, if you have a company to help make this more accessible, let me know, I need the help. Now that I've done that, let's get back into this. We've got our Angular app running. And we are running locally. We've got our code up. And I'm ready to rock. What happens next?

MARK: App.component.ts. That's -- because, remember, in this file, we said app components is our bootstrap component. Who you saw on the screen is all defined inside this file. Let's break down how this works. Say in something like React, you have functions. But we use classes, right? So, to make this app component class something special, without anything, it's export appear component, one class called title. How do we make this special, we add the decorator component. That's where all it happening. turning from a regular class to a component class that can be rendered on to the screen. Some of the -- and the most important part -- you know, let's write some code. Let's go to where it says template URL, that's one of the properties. Let's take that from being an HTML file. Just go ahead and delete that, as-is. Yep. And put back ticks instead of single quotes.

JASON: Okay.

MARK: All right. And then change that template URL to just template. Because by default, our template was in a separate file.

JASON: I gotcha.

MARK: Put your Hello World up in there and save it.

JASON: Okay.

MARK: All HTML is valid here. So, you can do whatever you want. If you put that in H1, whatever you would do.

JASON: Yeah, we'll just throw this into a quick paragraph tag.

MARK: Love it. Save it. Go back to the browser. Bam. Updated.

JASON: Okay.

MARK: Zoom in like six times so the streets can know what we're doing.

JASON: Good call.

MARK: Okay. Excellent. Now there's an edit refresh loop in Angular. Where if you make a change when the Dev server is running, it will make the change.

JASON: I think I might be able to -- let's see if I pop these together. Show that happening in real-time there.

MARK: Oh, yeah, you're cooking right now. All your styles for this component. Let's talk about -- okay. I wanted to show you that so you can get an idea about how as we build out how we'll do that process, but let's talk a little bit about what the other properties are in the component. You've got the selector property, at dash root, it can be whatever you want it to be. That's how you reference it in your HTML and other components. It needs a name. In React, I used to teach React and also I know people are familiar with React. Right? In React, you use the actual class name as an element in your JSX. And Angular, because we're using raw -- or regular HTML here, we have a selector system. Right? You define your custom tag selector name.

JASON: Got it.

MARK: That's what you call it. Standalone equals true. This is one of our newer features. One of the things that we used to have is this module that handled all of our dependencies and stuff. We have dependency injection, which is another feature that Angular has that you can provide services and values across your application through a dependency injection system that you normally see on the backend. We support that on the frontend, which is a really nice feature.

JASON: Okay.

MARK: But we used to manage all that stuff with modules. To take Angular to the next level, modules have to be optional as a concept. And standalone means this component can literally be used by itself. It manages its own dependencies. And then you can bootstrap an application from this component which is what we actually did. So, if you saw it, that's literally what we did, bootstrapped the component. Go ahead, sorry.

JASON: You're only going to set standard on your root component?

MARK: All components.

JASON: Okay. Got it. All right. We get into our imports. And I see we have pulled in a common module and a router outlet. I have a guess. But not sure.

MARK: Okay. Let's talk about CommonModule. That's some of the features you want to use in your template. Some built-in things that we provide that are gonna be in the CommonModule or you can pull out individual things later.

JASON: Got it.

MARK: This is a default generated app. We're not using it, the routerOutlet, this is where when we have another page, put it, you know, wherever this RouterOutlet is.

JASON: Yeah, when you got a layout and it's got your header and footer shared and then the page content needs to go in the center, the routerOutlet is the page content between the header and footer.

MARK: Man, you're a Genius. That's true. That's how it's going to be. I'm going to grab my tablet to write down some notes on what we want to do with you. What can we build so we can get cook something because the features that I want to show you, but I want to show you in context of us building over the next like few minutes.

JASON: Yeah. So, my thought is that we probably want to show how we get data into an app.

MARK: Yep.

JASON: I want to show -- I want to figure out how we use like a component -- a reusable component, kind of get props and all that stuff in there.

MARK: Yeah.

JASON: How about -- we've got two options. We could use one of the APIs like the dog CEO API to get pictures of dogs and make something where you could like send off a query, get a breed of dogs, like, you know, get corgis, get pit bulls, whatever. And use those. Or I have on my site an API, Learn with Jason episodes. We can make a schedule lister thing. If we want search, we should use the dog API. Like if we want to configure what comes back.

MARK: Yeah, we're gonna do a few things here. Let's do a few things -- does that dog API give you resources down to like dog API/1, like ID level?

JASON: Yeah.

MARK: Okay, great.

JASON: You can get a -- let's see... whoops. By breed. And then I think you get an individual.

MARK: All right. Let's run.

JASON: Actually, now I'm not sure. By breed, get these. Actually, I don't know if you get individuals. I don't think you do.

MARK: Okay. So, let's do this. I got you, though. I'm not worried about that for now. Because I know what we want to do. Let's just make some card UIs with some dogs. And that'll give us a couple things. Because then we can show the reusable component first. And then we can go into just all the different parts. I got you.

JASON: Hold up. I think we got a -- I think we got a sneaker API.

MARK: I mean, if we in the streets with the sneakers...

JASON: I have to type this out because apparently you can't copy-paste out of... out of Streamyard which is fine, I guess.

MARK: You take a lot of Ls in this situation. I don't know why. They're kind of forcing you to take some Ls that you shouldn't have to take.

JASON: This is great. We've got the sneaker -- sneaker database and we -- oh, no! Do I need an API key? That's not gonna work if we have to get an API key. I don't think this is gonna work, unfortunately.

MARK: mm... it's all right. That's all right. Let's just run it with the dog API for now. And get some things going. The first thing we're gonna need, because what I'm thinking about is we'll just list up the dogs, you know? We'll list them and we can get so many different features if we do it this way. Let's do it like this -- let's -- first -- let's make a dog card, right? A component for a dog card. Go back to your commandline, all right? And you can leave your Dev server running, you can open a new tab. Yeah, yeah, that looks good. Do not laugh at me. My mother used to tell me, do not laugh at him it will only make things worse. Don't laugh at him.

JASON: Do not encourage these shenanigans.

MARK: Do not encourage that boy, he will lose control of himself. Ng, generate, G is for generate. But your autocomplete is working, right?

JASON: It's working and it's wonderful.

MARK: All right, let's go. All right. So, generate, and we're gonna say component. That's what we want next. And then just name the component. But I'm gonna tell you before you hit enter what to do. You can do dog -- you can do dash card if you want. Do some good stuff for you. And space, dash, dash st. Yeah, try that. Oh, wait. Maybe do... only one dash. See if that is doing it right. All right. Cool. The st flag was just to remove some of the boilerplate that we generate whenever we make a new component.

JASON: Oh, nice and simple, yeah.

MARK: Without all the extra stuff.

JASON: Okay.

MARK: So, let's jump into that dog card component.

JASON: Oh. And here it is, nice and clean. Real simple.

MARK: Real simple. Exactly right. You can start from here. Everything is ready for you. This component is ready to be used in our other component right now. So, if you copy the name of the class, right at the bottom. Yep. And then go back to your app component, we're gonna import it. So, just go into your imports array. You can do that too, you can say imports array.

JASON: Just go straight in?

MARK: You can. I'll show you what I mean. It'll help you out. Resolve that error by importing, command space, I think you can do.

JASON: Nice and easy.

MARK: We're only working on where you need to import once and then it will do it. We're working on it. Everybody just relax. We're working on it.

JASON: Okay.

MARK: So, go to your template code right online 10. Because this is HTML, we're gonna reference our new dog component just to get it on the screen so we know that things are working.

JASON: Okay.

MARK: Add a new line at the end of this line. But within the text. Yep. And then you're gonna do angle bracket and then you start typing app --

JASON: App-dog-card, oh, it does it like that.

MARK: You can do self--closing too. Instead of doing the full -- yeah. Do self-close. Now look at our app code. That lets you know that you have an app dar component. You're right in there.

JASON: What's app dog? Come on.

MARK: Oh, I know. The pain is hurting me. Because that was good -- that was very clever, actually. I don't know, what's happening with you? So -- oh, come on, man. Look, we're unsubscribing because Mark and Jason cannot -- they just cannot get themselves together. If we look at that dog CEO API, what kind of data can we get for an individual dog?

JASON: We can get -- if we -- we can do a list of all the breeds. And we can get -- if we go by breed, it gives us images. If we go...

MARK: Okay, let's see here.

JASON: I got an idea. You were talking about potentially doing, I think, if I'm reading your mind correctly.

MARK: Yes.

JASON: You were talking about doing a list on the front page and click into one to get like a --

MARK: Yep.

JASON: -- okay. What we can do is get our list of breeds and use the breeds to click into. And then we can -- so, we'll be able to show one image here and then when we get into each breed, we can show like maybe the first ten off of the list here.

MARK: Sure. I'm totally fine with that. Is there a breed photo? No, there's not a breed photo, is there?

JASON: But we can get there. So, if we go to "By breed," we can do the slug and then add images and just grab the first one.

MARK: I see... I see. Okay. So, let's get the breed API. So, this is something that I normally would not jump to when I was showing somebody to do Angular. But your audience is pretty advanced. They kind of know how to write applications. We'll jump a little bit. But what I was going to do first was pick out the data points that we display in the dog card, right? Fill those in, then show you how to pass in data to customize that. And then from there, tie in the data at the end. The live data at the end.

JASON: Okay. Yeah, yeah, yeah.

MARK: So, that's the way I normally would do this. So, we can go straight to the data and then work from the data first.

JASON: Let's get wild. Let's do it. The way that I would expect this to work, we would want to set up a loop to generate one dog card for each breed.

MARK: That's right. Do you want to get like spicy and have the experts roast us? Let's just make something work. We can always refactor.

JASON: Oh, yeah. Let's -- if we can offend all of the crusty Angular programmers in one line of code, we should do it every time.

MARK: They're gonna roast us -- you should not do this. This should be in a service. This should be in a service. But... let's get roasted. I like that, Vinny, I like that energy. Brandon.

JASON: We got an endorsement from Brandon, does Brandon count as one of the crusty Angular developers?

MARK: But I would put Brandon's name with the picante, Brandon comes with the hot takes.

JASON: I remember Brandon coming in with spicy takes in the Angular community not too long ago.

MARK: And he's a friend of the community even though he's roasting us. I respect that hustle. Let's jump into this. Ideally, in your constructer for a class, this is computer science and not Angular. In your constructer for a class, you do not want to do anything that takes a long time, in creating instances, it's slow their way. What we do in Angular usually to handle this, we do this thing, ng on it, which is the life cycle method. First thing, go to line 14.

JASON: Line 14.

MARK: And at end before the opening bracket, do implements, all right and then on init. It told you.

JASON: Oh.

MARK: Now your class needs to implement that ng on init. If you resolve the error, it will tell you what to do -- missing the fixture -- ngOnInit. We're not going get super-roasted. Let's get that out there have. and do a regular good old fetch.

JASON: Can I make this async?

MARK: You can make it async, yeah, that's fine.

JASON: Okay. I'm going to await fetch. And we'll hit this dog CEO breed list API. I'm gonna make sure that's not wrapping for whatever reason. I got to turn off the autocomplete on whatever this thing it. Although I guess that's useful. So, we'll get the data and then once I have the data, I need to do something with it.

MARK: Store it someplace. Let's make a property under title. Let's make one called "Dog list."

JASON: Okay.

MARK: The type for this list -- okay. You got to be careful here. That's gonna be type never because it's TypeScript. So, you won't be able to add anything to that. You don't want to do that. Yeah, I've done that so many things and couldn't figure out what to fix. Let's give it a type.

JASON: Let's give it a type. And the type I'm gonna give it is -- we'll just go with string.

MARK: A string array, fine. It's something. It's now no longer type never. Which you can add to it. So, that's a pain point in TypeScript. That's not Angular-based. It's TypeScript thing. It's doing the right thing. I just don't like to. Okay.

JASON: Okay. Ready.

MARK: Now we have our data, we just need to adapt the data from data to dog list, whatever that looks like. You can do for each or whatever. I don't know the right thing you're gonna get.

JASON: Yeah. Let me do this. I'm gonna do map.

MARK: Oh, wait. There's a message property first. You probably got to go over the dot message.

JASON: Yeah, we get to the dot message and then I need to get the keys. So, actually, maybe I can just do like an object.keys. Get the data message.

MARK: Yeah, yeah, yeah.

JASON: I think and that would be it, right?

MARK: That should give us an array of arrays.

JASON: Well, I think it should just give us an array of the names, right?

MARK: All right, but the named properties will be array, right.

JASON: Yeah.

MARK: But we just want the names for now. That's totally right. Let's run it.

JASON: What are we -- what are you unhappy about? Leave me alone.

MARK: It's saying you're not returning something?

JASON: We made it async, it's a promise.

MARK: You're not returning anything, that's weird to me.

JASON: Well, because we made it async, it's always returning a promise.

MARK: Oh, the function is returning a promise. By default, that is correct.

JASON: Yeah. I always -- this is like -- this is where the -- like TypeScript strips away all the magic of async await and you have to remember that it's all just promises. And under that, it's all -- I'm talking about doing an episode soon on just how broken -- not broken -- how sneakily complicated promises are in -- in JavaScript in general. Stay tuned for that.

MARK: Loves observables, he agrees with you. That async programming in JavaScript sucks! All right. Let's keep cooking. So, now we have our dog list. Let's go into our template there. I'm pointing at the screen. Even though people are home, I'm actually pointing at the screen.

JASON: You know what? I know what you're pointing out.

MARK: All right. Let's wrap this with a For Loop. You're gonna use this new syntax we just released a few weeks ago.

JASON: Okay.

MARK: At, the at symbol.

JASON: Let me break this up a little bit so I can see.

MARK: Go for it.

JASON: At --

MARK: For.

JASON: For.

MARK: Open parentheses. And then say dog of dog list.

JASON: Do I need the this in here?

MARK: Nope. It knows. It just knows. And then you end up putting your curly braces. That's right. That was very intuitive. You did not know that, but you knew what to do.

JASON: I've got my guess. Okay. So, then here I want --

MARK: Fix one thing here.

JASON: All right. Show me what I'm doing wrong.

MARK: In your for, you got to give it some type of expression. You know how you have keys and maps for React?

JASON: Yes.

MARK: You got to give a key so it knows how to do row swapping. We have a thing called a track. Put a semicolon -- sorry, colon -- after dog list online 12. And then you're gonna do track: Dog. Nope. No colon after track. And then you should have a semicolon after dog list. I might have said the wrong one.

JASON: Semicolon after dog list.

MARK: Everything is cooking. All right. You go back to the code, what you wrote doesn't make any sense for the line 13, but we'll fix that later.

JASON: This is just me doing nonsense here.

MARK: It does not make any sense. But we'll fix it. All right.

JASON: Okay.

MARK: We're cooking. Go back to the browser. Make sure we should have a bunch of dog works. Okay. Dog works.

JASON: Look at it go.

MARK: That was pretty smooth. Okay. Do this for me. Command click at dog-card.

JASON: Command click...

MARK: Online.

JASON: Oh, command click. I'm like trying to do it in the browser.

MARK: No, bro. We don't have predictive debugging that you want. We don't have that yet, bro. But we're working on it. You know how with the templates, you get superpowers?

JASON: Right.

MARK: That made that really easy for you. Here's what you need to do now. Say this dog-card accepts a prop called dog or something. You can call the dog. We call them inputs, not props. We call them inputs.

JASON: So, like here -- there it is, okay.

MARK: But don't do that, though.

JASON: Don't do that. Get it out of here.

MARK: That's dope that it works that way. But that's not how we normally do it.

JASON: Okay.

MARK: That's not how we normally do it. Interesting that you wanted to do that. I'm going to take note on that. You wanted to do that. That's so interesting to me. At input, capital I.

JASON: Capital I, Input. Oh, and it's doing this for me.

MARK: Yep. Okay. All done. All right.

JASON: Okay.

MARK: So now our input is called dog, because what's what you called it. It's a type string. So, whatever gets passed in there, has to be a type string. Now, let's get roasted a little bit. Put an exclamation point after the dog.

JASON: After the dog.

MARK: Yes, the non-null assertion.

JASON: That's right, TypeScript, you're not the boss of me, I will do whatever I want.

MARK: I will do what I want to do. The dog is gonna be there. Don't you worry about it, TypeScript! Oh, man.

JASON: Okay. All right.

MARK: I'm gonna get fired. It's all good. Let's go back to our component, app dog component. Dot ts. Back in there. Now here's what you're gonna do. Do square bracket there and then dog --

JASON: Did you see it?

MARK: No.

JASON: That's cool.

MARK: Jason what about did I tell you about the way we care about our developers. I'll tell you, our tool is topnotch. People sleep on Angular's tooling.

JASON: This is good.

MARK: It figured it out. Let's go back to the dog component.

JASON: Back to the dog component.

MARK: And fill in whatever properties we want. Right now the dog is just a string. Oh. You don't know how to do this yet.

JASON: I don't.

MARK: How do you display dynamic values in Angular? We do double curly braces. I promise you, this is my representation of double curly brays.

JASON: Double curly boys.

MARK: Double curly boys. We're cooking. That's it.

JASON: Look at it go!

MARK: Cook! Cook! In the kitchen, whipping, whipping, whipping. We did it. All right. Now we know what we can do. Now we know what we can do. If we wanted to get even fancier, we could take those keys and pass in -- like this page could have more -- we could set it up where we pass in, click on this, go to this page and display the summaries when we wanted to. We could do whatever we wanted to, right?

JASON: I opted to ignore the sub-breeds because that seemed more like a JavaScript looping problem than an Angular problem.

MARK: I appreciate that. That makes me happy, actually. We got the skills because we know what our breed is gonna be, right? The API is like forward slash API, forward slash breed, breed name, forward slash images to get some pictures.

JASON: Yes. So, if we go by breed, then we grab one of these and so, the way that that will work, we can just comment it out right now.

MARK: Yep.

JASON: Is we will go like that.

MARK: But you plan -- you a genius, I ain't lying. Streets at home, Jason a genius. He's right on it. He's right on it.

JASON: Will somebody clip on this so I can play it on loop when I feel bad about myself?

MARK: Man, you a genius. You know, David Goggins has a bunch of people saying mean things about him on repeat. I'm gonna do the opposite, I like David Goggins, I got to tell you something, you got to write the right code. You got your Cheetos next to your keyboard and you should be writing -- that's real. You should clip people talking nice about you and play those clips back to yourself. Right. exactly. Exactly. say it hard! Code hard!

JASON: This is so good.

MARK: People are gonna see this and be like, I'm not watching any of Mark's videos. Cut. Cut. All right. But we do want to display one of the images. So, if we went straight to -- so, to get that -- so, we got to get the array of data again. We got to repeat that same fetch. This is where we could do a quick refactor and probably save ourselves some effort.

JASON: Okay.

MARK: Because we got the basic stuff working. Friends at home, yes, we know we can do better, got the basic stuff working. Let's refactor. Go to the terminal. What I want you to do is make a service.

JASON: Okay.

MARK: Ng generate, service, if you want it, and that will also just work. And then call it dog, right? Okay. Cool. Now let's go become to appComponent. And let's pull off that request where we pull off the dog names -- I'm sorry, the breed names.

JASON: Pull this part out, okay. So, I'm getting this.

MARK: You keep that, probably. Probably take that, let's copy that.

JASON: Copied.

MARK: Let's go to the service we just created and make a function called get dog breed.

JASON: Inside here?

MARK: Yep. Yep. GetDogBreeds. And then make it async just like we need to. And we can return line 12 if we wanted to. Right? And just return --

JASON: We don't need to -- we don't have to await the return because it's already a promise, good. All right.

MARK: All right. Awesome. Make a function of GetPhotoByBreed.

JASON: I like that. GetPhotoByBreed, and put in breed, thank you, robo computer. Did you know -- oh, you knew.

MARK: It was almost right. Wait, did it get all of it right?

JASON: I think it got it right.

MARK: It's missing a curly boy right there.

JASON: Because it's a JavaScript template. Yeah, yeah.

MARK: What?

JASON: Good job, computer.

MARK: Let me tell you something quick on the side about this, I have been experimenting with these code times. I'm not so much worried about my job going away so much as I'm really enthusiastic about how much I will be able to get done.

JASON: Yes. On Tuesday we did a show about this. And I think having it do something like that just saved me 10, 15 seconds. And over the course a day, that's huge. I don't I could say write me a functional application and ship that code. But these little utilities and repeated pieces that I type a thousand times a day, that's nice to not have to do.

MARK: Right. That's good. Now let's go back to appComponent first. Save that file too.

JASON: Oh, yeah. Now it's saved. Back to appComponent.

MARK: Import the service -- this is great. Time for dependency injection. You don't want the service available to the component template, that's where the inserts go, you want this to be available to the component class. Here's what you. Go to line 1 on init. You're gonna put a little thing called comma and then do inject.

JASON: Okay.

MARK: No, not capital one, that's a trick. So, watch out familiar. You want the inject utility function. So, what about inject does is gives you an opportunity to use our dependency injection system in Angular. So, I can say use the inject function and what do I want? And then it will get an instance of it for me. If it's a singleton, it will get the right instance and not create a new one. It will do all the right stuff for you so you don't have to worry about it. So, this is one of the major powers.

JASON: Cool. Cool, cool, cool. Okay. And where does one put that?

MARK: Yeah, let's go down to the body of our app component class. Excellent question. Right under dog list, you want a dog service.

JASON: Inject.

MARK: Yep, capital D for dog service. Okay. You don't have to put the type there. Nope.

JASON: Don't have to put the type there.

MARK: Nope, nope. So, the left-hand side you want to assign that to a value someplace to you can actually reference it, right?

JASON: Okay.

MARK: You want to do like dog service, lower case D. Equals...

JASON: Oops. Like that.

MARK: Boom, done. Now it's injected. Now you have an instance of the dog service. Is it imported?

JASON: Did now.

MARK: Okay. There grow. Great. Love it. So, technically, we should be able to --

JASON: So, I should be able to delete this and say -- this dogService, getDogBreed. We need a light -- wait. We want to await. There we go. Light refactor because I named this wrong. Should be breeds.

MARK: Yeah, sure, sure, sure.

JASON: And then let's go back here and fix that. Okay.

MARK: Boom, cooking!

JASON: There's our list. And now theoretically, I should be able to do the same thing over here, right? Where I can say I need to do the on init. Wait. I need to get the OnInit.

MARK: Yep.

JASON: OnInit, implement OnInit. Oh, crap. What's the shortcut? Command, period. Whatever. Implement.

MARK: Yep.

JASON: All right. Is there like a standard for -- like do you put these at the top usually?

MARK: Yeah, I put all my properties at the top.

JASON: Okay. Cool, cool, cool. So, in here, we're gonna say we want to get the dog image is gonna be a string.

MARK: Yeah, sure.

JASON: Starts out like that.

MARK: Perfect.

JASON: And then in here we will say this dogImage equals await. So, we'll make this async. And gonna do.dogService. I need -- okay. So, it got close. Even with me getting this all wrong. Does it know? Ah, it didn't quite get there. That's fine, that's fine. I was asking a lot.

MARK: That's okay. But switch that to -- right, yeah, put your inject dogService.

JASON: There's our dogService

MARK: Right.

JASON: And then I need to make this into a thing. Like that. And then we will import it.

MARK: Uh-huh.

JASON: And now this is a promise void.

MARK: Uh-huh, uh-huh.

JASON: And now we've got functional code. So, theoretically speaking, I should now have access to this image. And I should be able to do something to the effect of -- let's say like image and we can set --

MARK: Yes.

JASON: -- a width of like 300.

MARK: Yep.

JASON: And I guess we can do all of that.

MARK: And this right -- that is right.

JASON: Whoa. Did that just work?

MARK: That works. That's right.

JASON: Sick. That's very cool. And then we'll set the alt to be the dog.

MARK: Sure, sure. I'm with that.

JASON: Okay.

MARK: Wait. There's a little bit of imagine take I don't want to get ignored here. Those square brackets around source and around alt, those are special and intentional. What they do is they say, "Treat this property like whatever is on the right-hand side of the equal sign -- treat that as a property of the class and not just a plain default string like you would a normal attribute." So, if you were to like put dog K, right, for the alt, tornado give you an error, right? Because it will be like, oh, there is no property called dog K.

JASON: Right.

MARK: But without the curly brackets, it wouldn't know any different. It's actually expecting something. Yeah.

JASON: Just to keep it from distorting. Okay. So, this should give us a little square.

MARK: And we should be good, yeah.

JASON: Is this just gonna work?

MARK: Yeah, it's gonna work, bro.

JASON: I screwed something up, what did I screw up? Console... new collection is not a function? Did I -- oh. I know what I did wrong. In this one, we're getting the whole list. But what I actually need...

MARK: Yes. Yes. It's the first one. It's that message of zero. Yeah.

JASON: Oh, wait, it is dot message, isn't it? Is that right? That doesn't seem like it's right. Let's see. What is this? Get out of here. So, we do the -- there we got the message and then -- so what about it should be right. Why don't you like this?

MARK: Doesn't exist on a promise any. Oh, because it thinks that... wait what about? It thinks images -- JSON --

JASON: Oh, wait.

MARK: Await, there grow.

JASON: There we go. Back here.

MARK: Okay. So, we should be in closer.

JASON: New collection is not a symbol. So, I'm doing -- app component.ts13, so I'm actually in the wrong --

MARK: But you're fixing things that we would have to fix no matter what.

JASON: Okay. So, I did something wrong here.

MARK: Okay. We got this.dogs -- the await, yes, that's right. DogService, I get. Dog...

JASON: Let's look at our service. Because it's probably in here.

MARK: Yeah, yeah. You're there. Oh, wait. Didn't we have some other logic someplace where we're getting the properties?

JASON: We did. So, we need -- let's see. List and then that is going to be return list.message.

MARK: But then we were getting the -- well, list.message is dot message.object keys or something?

JASON: Yes, that is right. We threw away a lot of code when I got all happy about this.

MARK: Okay. Now we're cooking.

JASON: Look at it go.

MARK: Now we're cooking. You see that? Now we're cooking.

JASON: Beautiful.

MARK: Boom, Shaka Laka.

JASON: Let me update -- no, wait, our dog component. Make these a little smaller because they're a little big right now. Let's go with 150. There we go. That's a little better. So, now we've got -- it looks like some of these are broken. We're gonna leave that up to that's an issue with the API that I'm not gonna deal with.

MARK: API problem. Oh, but we can deal with it. We can deal with it. You know how we can deal with those? Deal with it in a nice way.

JASON: Okay.

MARK: If you scroll down to where we get the image, won't we know if the image URL is broken?

JASON: Not unless we hit it to see if 404s. I don't think this is like they gave us an empty URL. I think this is more that they gave us a --

MARK: See, I thought it was an empty URL. See, that's what I think, is they gave us an empty one. The dog breeds we don't have a photo for.

JASON: Let's look president here. The source... yeah, I think it's -- I think they're giving us broken images.

MARK: Oh, okay. That's fine, then. If they gave us an empty one, we could have done something smart around that.

JASON: It's giving us an image. I think this is volunteer-submitted. If somebody put an image up and then put it in and disabled the server, somebody has to volunteer to edit this list. Probably it's something like that. But this is already pretty dang cool how far we have been able to get here.

MARK: And that's without that much effort, either. Like we haven't even done a ton of the features that you can do with Angular. So, let's just... let's keep cooking. What other information can we get to the API once we have a dog breed? Can we get anything else?

JASON: Not a on it, unfortunately. We can get a full list of -- if we go to a particular breed, we can get a full list of all the images of that breed. So, we can show a little gallery. But we don't have -- it doesn't give us like any other details as far as I can tell.

MARK: Oh, I see. I was hoping to find a way -- a reason to do routing because I would like to show just kind of like out routing works.

JASON: Do you think we could do it in 5 minutes?

MARK: Yes.

JASON: Here's what we can do. Let's have these link. We're gonna do the link a little bit dirty. But we'll do something like this. And that's not gonna work, obviously. But then we can set it up like this. We can set up this one as a span. And this one as a span. And this gives us like a linkable set of -- this will take us to a page. And on this page, we can get all the images for that particular breed. We can make that same call, instead of getting one, we can get the full list.

MARK: I'm fine with that. Let's make this work. Go to app.route.ts.

JASON: Okay.

MARK: Already set up for you. Okay. Go inside that routes array, and then what you're gonna do is make an object. Empty object, yep. And then do the path -- p-a-t-h -- the colon. And set the path. the path could be dog forward slash -- something like that -- yep. You better work, boy. Let's go. And then we need a component to go to -- when this happens, where should they go, right? We need to say, whatever you want to call it. Literally, whatever you want to call it.

JASON: Okay. Let's call this what would be like app breed component or something.

MARK: Sure, but no you want the component class there. Go to your terminal real quick. Right where you are, get that terminal and generate that breed component. Yep. Component. And then we say, what do you want to call it? Breed. Yep, okay. And then do dash ST. Yeah. Cooking. All right. Now let's go back, write it right where you are, take the quotes out and put the class name that you created. And start typing what you typed. Breed component.

JASON: Breed component-component.

MARK: You put component in the name.

JASON: I did something cute and I shouldn't have. Okay. I can open this. I can get rid of this. And I can fix this. Did I just break everything by doing that?

MARK: You didn't have to do that. That's fine. So, then -- nope, nope, take the class. Change the class like you did. Okay. Go up to the selector. Let's see what you got. That works, that works, that works.

JASON: Okay.

MARK: Now let's go back to the place we're using it and the routes and show -- yep, perfect. You're back! You're back! You're back like you never left.

JASON: All right.

MARK: That's done. Back to the app component. We need a place to display the thing that we're gonna show.

JASON: Okay.

MARK: Go to the bottom of the list for now. This is not beautiful, but it will be fine.

JASON: All right. I'm ready.

MARK: All right and then you just want to do router-outlet, yeah. Empty. Right. That's where it's gonna show up.

JASON: Okay.

MARK: Whatever we click on. And this is a really bad idea. All right. Go to the app dog cart. I'm just gonna make our lives a little bit easier.

JASON: AppDogCard here.

MARK: Yeah, let's take that image out for now. Or make it really small. Because it's gonna be too hard to scroll. So, make it like 50 for now.

JASON: 50 works.

MARK: Yeah, go back to the screen, make sure the screen is still working.

JASON: There we go.

MARK: It's fine.

JASON: what a mess. It's fine. It's beautiful.

MARK: Yeah, go to app component one more time. Do one more thing. Okay, put an HR between. Yep. That way we can know where our new images start. Go down, yep, put an HR. Cool. Okay. Cooking, cooking, cooking. Now we make this a route. What you want to do is in your -- where did you -- where did you run to? Oh. Dog component, right? This is where you put your links, right? Okay. Now in the imports array... capital R for router. Yep. Router link. Yeah. Cooking. All right. Now take that -- that href, you don't want that to be an href anymore.

JASON: Okay.

MARK: Let me change that, get the exact syntax. It's escaping me because of the pressure.

JASON: We started a timer, do this as fast as humanly possible.

MARK: We got to type the router link, it's the router link directive we got to use here. Square bracket, the word router link, equals -- I'm remembering. Okay. Equals and inside of there, let's put like a little array.

JASON: An array.

MARK: Because you have -- so, here's why you do an array here. It will make it in a second.

JASON: Is it in a quote?

MARK: The whole thing is in a quote, whole thing is the array. The first thing in the array is the quote path. You put like a single quote around there. Nope, don't write the word path, sorry. I meant the part of the path. See that, and then yeah, quote that, comma. And now you're gonna specify the property. That's why it's an array.

JASON: Like that.

MARK: The first thing is the string path and them the property list -- see what I'm saying?

JASON: Yeah.

MARK: That was a little hard to explain. Now what have we done?

JASON: What did I blow up? We got circular dependency for router.

MARK: That feels bad.

JASON: How did I do a circular dependency?

MARK: I don't know. Let's see. Let's see... what did we type? So, you get router outlet there. So, that's right.

JASON: Yeah, yeah. And then we've got our dog-card. Is it because I pulled us router into a component that's already getting --

MARK: No, because you need it there otherwise you don't have access to router link. If it's something small, that will make sense. Go back to the at routes.ts. Okay. You were not in the breed component when you made that last change, you were in the dog component, right?

JASON: Right.

MARK: We should not be in here. Nothing should be in here. We should click and make this work. What did we type? Let me double check our syntax. What, what, what? Let's see. This is part that we can figure out -- router link, circular -- now I got to do what I would normally do. I got to Google what I did with the router here to make it messed up.

JASON: Let's see. That does what I want it to do. We get our missing dogs. The circular dependency is in here somewhere. In the router link in the template.

MARK: Okay. When you save that, does it give you any information?

JASON: It says... path cannot start with a slash?

MARK: Oh! Sure. Okay. Let's fix that. Go back to the route page. The route sites, yes.

JASON: Okay.

MARK: You can't do that. I didn't tell you. Sorry. We were going too fast. Okay. Save that. Okay.

JASON: Hey, there we go.

MARK: That's better. And all those reds are just broken pictures, right?

JASON: Yes. And down there --

MARK: And breed works, back in business, we got like 2 minutes left. Back in business, breed component. Let's do implements on the net real quick.

JASON: Okay. Implements onInit.

MARK: Cool. And then async, promise, void.

JASON: Promise void.

MARK: Async -- yep, boom and then we're gonna do -- then define a property called dog service. Sorry, I'm way away from my microphone. Because I was leaning --

JASON: That means when we're really cooking. I'm in, I'm in. We're doing this like this.

MARK: Yep.

JASON: Let me fix this. We're gonna import, fix this, we're gonna import and then we need to go into that service and we need to add one that is get all --

MARK: Get all breed, yep. All breed photos or whatever.

JASON: Get all photos by breed. And with this one, we're going to return the whole thing. Okay. Great. Then back over to the breed component and we can say -- so, we need -- let's see... photos.

MARK: Yep. Photos, sounds great.

JASON: And that's gonna be an array of you knew.

MARK: Who knew? You knew.

JASON: This dot photos is going to be await. This dog service get... almost. Get all photos. And we're gonna throw in the breed which means we need the input.

MARK: Okay. Yeah, you got to do something a little tricky here. Do input. You definitely want to do an input here. Okay. This is about the cook. This is about the cook. Okay. And then you need to do an input setter. Let me get you that syntax. This one's brands new where you can get the input directly from the -- you want to get the input directly from the route. All right?

JASON: Okay.

MARK: Let me just get you that syntax. I can't get this off hand, I'm not lying to you and then do a setter -- where is it? Where is it? Where is it? I know somebody in the commented, we don't know this? You can do input and then set as the property name?

JASON: Like this?

MARK: Outside of the brackets and outside of the curlies. So, input and then next word is "Set." And then you set -- let's see -- breed, that's fine. It's a function now. So, instead of a property, it's a function. So, yep. Looking good. And then inside the curly braces you want to do something like this.breed -- you could do this.breed name or something like that. We're gonna handle this in a second. Equals breed. Okay. And then you're gonna have -- wait. You need to go up a little bit. In the parentheses there. Okay. So, I got this. I don't want to mess this up here. Just do value. And we slow down and do string.

JASON: Okay.

MARK: Value is a string. Okay. Now you do value right there. Okay. Now pass breed name into your function.

JASON: Now pass breed name into... this function?

MARK: No, no, sorry. Into your dog service call. Yeah. Just do breedName. And then define a property called "Breed." Yeah. Okay. Perfect. Let me tell you what we did right here. We used a nice little trick, components, values through the input mechanism. We can also pull a value from the URL and bind it to that same input mechanism. So, that's just like a nice little convenience method that you can use to do this.

JASON: Got it. Okay. So, then we're gonna say image of photos.

MARK: Yep.

JASON: Track image.

MARK: You're cooking. You're cooking.

JASON: And is it just going to do this for me, that would be sick.

MARK: That looks right to me.

JASON: Did you just do my job for me?

MARK: Almost. But you're almost there. The right number of things.

JASON: Okay. So, we missed a piece. And the piece that we missed is that what? When we get all of our photos by the breed name, can we -- it's saying undefined. Which leads me to believe that something is missing in here. So, let's see... can I just like console log?

MARK: Yes, sure.

JASON: This photos. Let's do it. Let's get this open and see what comes back. We get... we get nothing. Does it log in here?

MARK: You didn't navigate to that page yet.

JASON: I didn't navigate to this page yet.

MARK: Now it should give you the...

JASON: Breed not found. Master breed does not exist -- uh-oh. Breed undefined. Okay. We're not getting the breed. We're missing something. So, the breed name is not...

MARK: Okay. So, yeah, go ahead. That's fine.

JASON: This.breedName. Oh, boy, oh, boy. Playing a dangerous game doing this right at the last minute. Where does this get?

MARK: Okay. So, do two things. First thing is, okay, so you got an error there, syntax error.

JASON: That I think got fixed.

MARK: Okay. Do something real quick. For your console, filter your output to not show errors for a second.

JASON: Filter it to not show errors.

MARK: The log level is the cog up there, point, I don't know if you can see this. But anyway, now you can just see what you are trying to output. So, we can get an idea.

JASON: Yeah. Okay. So, it's sending back breed does not exist because we're not getting the breed.

MARK: Okay.

JASON: So, let's... yeah. Our breed is undefined. So, something in here. We're missing --

MARK: Make sure that we got that cooking right . you got your setter, and breed name. Oh! Go to app.config. App.config.ts. Last part and we're done. We got this cooking. Add a comma after routes.

JASON: Here?

MARK: Yep. With... w-i-t-h -- with component input binding. There you go. Now we cookin'.

JASON: Do I need to import this?

MARK: It imported, but you got to execute it.

JASON: Oh, it's like a -- like one of these.

MARK: Yeah, now it will work. This is a new feature. We just added this. There we go.

JASON: There we go. Look at it. Look at all of these pekingese. And hit another one, corgis. What did I do wrong? Here's our corgis. Here they all are. And so, I think we missed something that's causing it to -- like the refresh -- because it is updating the page. But I got to refresh the whole page to get it. We're missing some kind of a refresh, but unfortunately we are out of time. But this is pretty dang cool that we were able to get all this going this quickly. I love, you know, it's -- there was a lot of intuitive stuff. The tooling here is doing a lot of work which is pretty dang impressive. So, Mark, for folks who want to see more, the first thing I'm gonna do is I'm going to recommend that everybody just sets their calendar, come back and tune in on the 11th when Jessica from the Angular team comes back and we're gonna do a little more. So, Mark, you're -- Jessica, your calendar is for that. And if somebody else wants to -- if they want to go further, like where do they go next? I'm going drop your links again.

MARK: Awesome, two places, check out the YouTube channel, if you like the way I teach and instruct, find out more on the YouTube channel. I have a course on Angular. YouTube.com/angular. You can get stuff there. If you want to learn more, I designed the tutorial in the browser that you run through. You can get more information there. And if you want to learn even more, our community -- I mean, our community is wild. There are amazing groups. There's Angular Nation, Angular Architects, there's people like Brandon, there's the Nx team, they have a lot of Angular content. There's so many people I couldn't even imagine to name everybody. There's a great book. There's books and everything out there. I want to give everybody -- and say there are lots of things to learn online. Go out and find it. If you have questions, tag me or tag an official Angular account and we're happy to help you. [Deep breath]

JASON: Wonderful. Wonderful, wonderful, wonderful. Take advantage of that, and hit up Mark and ask your questions and get directed to the other wonderful people contributing to this ecosystem. With that, one more shoutout to our sponsors, Netlify and Vets Who Code, kicking in to make the captioning done by Amanda who so graciously stayed a little bit late, thank you so much. From White Coat Captioning. Check out the schedule, it's absolute fire beginning into the new year. Y'all, it's going to be so much fun. This is our last episode of the year. So, please, have a happy holiday, have a happy new year, and we will see y'all next time. Thanks, y'all.

Learn With Jason is made possible by our sponsors: