 Hey friends and welcome to Introduction to Angular at Google I.O. 2022. We're thrilled to have you here and I for one can't wait to get started with today's workshop, Introduction to Angular. Angular is a framework designed to support developers as they build scalable web applications. Whether it's scaling your product as user demand increases or scaling your team to meet growing technical needs, Angular will continue to be a fantastic solution. In this workshop we're going to build an Angular application from the ground up called Fairhouse. Fairhouse is an app that lists housing locations for individuals or families facing housing insecurity. Here's a preview of what we'll be building together today. Now here's what you'll need to get started. Node the Angular CLI and the starter project from GitHub. Since this workshop is based on the Introduction to Angular codelab, you can find the links in all of the details at this URL. Be sure to complete all of the setup instructions before continuing along with me. Now I'll be using VS Code and the Angular language service plugin for VS Code for the best development experience. With that done let's get into it. Alright friends I have my editor VS Code open with my project already loaded and a blank Chrome window. Let's confirm that the application starter code is working by starting up Angular's dev server. Here's how we do that. In the terminal window type the following command ng serve. In the browser navigate to localhost 4200 and it should display the text Fairhouse app is running. If that's the same content being displayed in your browser then we're off to a good start. If you are unable to get this message to display be sure that you have installed the dependencies with NPM and that you are in the right folder. These are two common mistakes. Ask me how I know. Alright this is excellent your app is up and running and we can move on to the next step working with components. I pre-built this app with the ng new command provided by the Angular CLI. The Angular CLI is a command line tool that provides features and utilities to help boost your productivity when building an Angular application. When creating a new application the Angular CLI scaffolds everything you need to get started. Source code, testing setup and configuration files. The source code for the app can be found in the source folder. There's a folder called app which represents our component. This is a great segue into one of the core concepts of Angular components. Components are the core building blocks for Angular applications. Think of components as a brick used for construction. When starting out a brick doesn't have much power but when combined with other bricks we can build incredible structures. The same goals for apps built with Angular. Each component has three main aspects. An HTML file for the template, a CSS style for the files and a TypeScript file for the behavior of the application. There are some other files in this directory that we'll come back to later but first we're going to update our UI. Open app.component.html in your editor and delete all the code in that file. We're going to replace it with a main tag then inside of the main tag we'll add a header. The header tag will contain our logo and the text Fairhouse. We'll also add an empty section tag as a sibling to the header tag. Save this code and let's check the browser. With our development server running the changes will be reflected in the browser when we save. Next we want to add a text field for search and a button to the UI. Now components have many benefits with one of those being the ability to organize the UI. We're going to create a component that will contain our text field the button for search and eventually the list of locations. To create this new component we'll use the Angular CLI. From the command line we'll type ng generate component housing list. Let's take a moment to explain the command we just used. ng is the Angular CLI, ng comes from the word Angular. Generate tells the CLI what type of action we want to perform. In our case we want to generate something. That something happens to be a component. We can generate other things like classes, routes, enums and more. Check out the documentation for ng generate to find out more. Finally we'll pass the name as the last argument to this command. We want to call our component housing list. I'm naming it that because we'll eventually put the filter list of options there. After hitting enter to execute the command the output of the command is displayed in the terminal letting us know what just happened. In our case multiple files were created for us. The TypeScript class, the HTML template and the CSS file. In the folder tree there's been an update to the source app folder. Now we have a housing list folder which contains all of those files we just covered. Next we need to add this new component to our UI. Back in app.component.html let's update the section tag and add our newly created component at housing list. If the refresh doesn't happen automatically check for errors in the terminal. Also check to make sure that the development server is still running. The updated UI now reads Fairhouse and housing list works. Let's update the housing list component with the code for the input field and the button. In housing list.component.html I'm going to remove the existing code here and add a label input and the button. Now before we go back to the browser let's update the styles for this component. I've already written them we just have to add them to the application. In housing list component.css copy the styles from the code lab and paste them into this file. We'll save the code here and the UI will be updated. Okay can you believe all this great progress that we're making here? This is fantastic. We have the input and the button but clicking on them doesn't do anything and we can fix that. On the web when we want to interact with controls like buttons we have to invoke the use of click handlers. Angular has support for click handlers built in as well. So first we'll handle the button. See what I did there? We'll make these changes in housing list.component.html. To add a click handler we'll need to add the event listener to the button first. In Angular the syntax is to surround the name of the event in parentheses and assign it a value. The parentheses let Angular know that the attribute click is meant to be an event. Let's take care of the value to the right hand side of the equal sign. Here we'll name the function that will be called when the button is clicked. Let's call it search housing locations. And don't forget to add the parentheses to the end of this function to call it. Once we save our code the browser will have an error letting us know about a compilation error. The search housing locations method doesn't exist in our TypeScript class for this component. Remember the TypeScript class contains the logic for our components. We have to implement search housing locations. Let's take care of it now. In housing list.component.ts we have the component decorator detailing what the tag name should be for this component, the location of the template for this component, and the location of the styles for this component. In the body of the class, we'll add the implementation for the function. I'm going to add a new line and add the function signature for search housing locations. Saving this code, the browser will update to reveal an app with no more compilation errors. Again, we're back at it with more great progress. I am so proud of you. Our next step is to somehow get the value of the input field and pass it in as an argument to the search housing locations method. We're going to use an angular feature called a template variable. This allows us to get a reference from the HTML element from the template and interact with it. In this case, we're going to get a reference to the input and then send the value as an argument to the method. In housing list.component.html, let's add an attribute called search with a hashtag as a prefix to the input. Next, we'll add an argument to the search housing locations method called search dot value. The search dot value is the reference to the input and the value property of the input. One cool thing about template variables is that they can be used throughout the template. In this case, I'm using it to send the value from the input into the function, but there are also more use cases to consider. In housing list.component.ts, we need to update the method signature for search housing locations to include a string parameter called search text. We'll add that in the parentheses of the function signature. We're using TypeScript and one of the big value ads of TypeScript is type checking. The type checking allows developers to write safer code at compile time. We want the type of the search text to be a string. We'll add a colon and the string type. Now, search text has to be a string. If it is anything else, we'll get an error. So this is what we want to ensure that the code is functioning as we'd hope. Let's add something to let us know that the code is working. That could be a test, but for now, we're going to use our age old friend console.log. I'm going to add console.log of search text to the body of the search housing locations method. Save all the code and in the browser, open up Chrome dev tools and navigate to the console tab. Enter a value in the input field. Any value will be fine. I'm going to enter Chicago and when I click enter, we find that the console now displays Chicago or whatever value you entered. All right, that was awesome. Can you believe all that great progress that we've made so far? You deserve something special again. Here's another high five from me to you. So far, we've created a new component. Use a template variable to get a reference to an element in our template and update our TypeScript class and template to include an event handler. We are making wonderful progress. Let's keep going. While this is very cool, we need to get some data involved. Our application should show a filtered list of housing locations based on the search criteria. So here's what we want to represent. Each location has a string property for name, city, state, photo, and number property for available units and two boolean properties, one for laundry and one for Wi-Fi. We could represent this as a plain Java object, but one of Angular's strength is the adoption of types and TypeScript. Using types helps us avoid errors during build time. So we're going to make a type for our housing location. In the terminal of the editor, we can use the Angular CLI to create the housing location type. To do this, we type ng generate interface housing location. We use interface to shape the data in TypeScript. This is the best practice versus creating classes. You can find out more in the official TypeScript documentation. In housinglocation.ts, we can add the type details for our interface. We'll give each property the appropriate type based on our design. In app.component.ts, we're going to create an array containing the data that represents our housing locations. First, we'll import the housing location interface from .slash housing location. Then in the body of app.component.class, let's add a property to the class called housing location list. The type of this property is an array of type housing location. We'll also add a few simple locations to start with. This is where shaping the data works in our favor. While we don't have to instantiate new instances of a class, we can still take advantage of the type information provided by the interface. The data in our objects has to be the same shape or match the properties defined on the interface. Now we need a way to share this data with other parts of our application, other components. Normally, this data will be stored in another class and then we can use it in multiple places. But here, we'll just make this happen by sending the data into housing list component via the Angular input feature. We can add the input decorator to a property and pass the value via the template. Let's implement this change to get more clarity on how this works. In housing list component.ts, we have to import input from angular slash core as well as housing location from one level up slash housing location. Next, we create a property called location list in the body of the component class. We're going to use input as a decorator for location list. To learn more about decorators, please check out the Angular documentation at angular.io. Now I want to create this right above the constructor. We're setting the type of this property to be an array where the elements are tight housing location. In app.component.html, let's update the app housing list element. We're going to include an attribute called location list in camel case and set the value equal to housing location list. The location list attribute has to be surrounded in square brackets so that Angular can dynamically bind the value of the location list property to a variable or expression. Otherwise, Angular will treat the value to the right hand side of the equals as a string. This is not the energy that we're looking for. Now, if you're getting any errors at this point, check out the following. Ensure that the input attribute name spelling matches the spelling in the property of the TypeScript class. Case matters here as well. Ensure that the property name on the right hand side of the equals is spelled correctly. Also, make sure that the input property is surrounded by square brackets. Let's confirm that we're sharing data from the app component to the housing list component. We're going to display all of the locations in the location list on the housing list component. We could hard code this, but since we have an array and we want to display each of the items, the best solution is some sort of looping mechanism. To do that, we'll make use of the Angular template feature called ng4. This allows us to repeat some of the HTML content in our templates. In housing list component that HTML, let's update the template to display the data in the browser. Beneath the input and the button controls, we're going to add an article element. Inside the article element, we'll add the ng4, but don't forget the asterisk. ng4 equals let location of location list. This code we're adding is called template syntax and is an Angular feature. You can learn more about template syntax in the Angular documentation. Here, location is like a local variable that we can use in our template within of the scope of the article element. So that means between the opening and closing tags of the article. Next, we'll display some values from the location. Remember, each location here is one of our housing list locations from the app component. Let's add a p element and the title that p element will be interpolated values from the location property. In Angular templates, we can use interpolation to display value via the curly bracket syntax. Let's do that now. As a child of the p tag, we add double curly brace location that name closing double curly brace. Save this so that the updates can also be made in the browser. Okay, great. The browser now has the content of the updated templates. The data is being shared from the app component to the housing list component, and we're iterating over each of those values to display them in the browser. Very cool. We've just covered some ways to share data between components. Use new template syntax and the ng for directive. We need to make some further updates to our housing list component. The filter function isn't exactly working because we haven't implemented that part of the functionality. Let's take that step now. What we want to happen is for the search results to only include locations that match our criteria when the user clicks the search button. In housing list.component.ts, we are going to make some changes. First, let's add a new property called results and set the value to be an array of type housing location. In the search housing locations method, let's update the code to filter the results based on the search text. Let's remove the console.log and assign the results property the value of the location list that's been filtered by location city. Let's remove the console.log and assign the results property the value of location list being filtered by location city. We'll make sure to compare the lowercase version of the search text and location city property. It's worth taking time to mention that when referencing properties of a class inside the methods that we have to use to this prefix. That's why we're using it with this.results and this.location list. We can improve our code just a bit. If the search text value is blank, we shouldn't try to filter. Let's add a guard at the top of our function. If search text is blank, return. Our method has been updated to handle the filter. Let's update the template as well. In housinglist.component.html, we just need to replace the location list with results in the ng4. Be sure to save all the code. And now let's check the browser. We can type a value into the search field and confirm that the search results match depending on how many locations are in a given city. Alright, this is working great so far. Excellent work. Before we move on, remember that this is the first iteration of our code. Right now we can search by location, but we can expand this code to search across the various fields if we wanted. Once we're done with this workshop, if you want to implement that functionality, that could be a great way to continue your angular journey. Alright, we just finished implementing the core functionality of our location search. There's just one more piece of the puzzle remaining, and then we'll be functionally complete from here. We just need to implement the details panel that should display after a user clicks on the search results. Let's get to it. In order to implement the details display functionality, we'll need to make it possible for users to click on a search result. The housinglist component knows which detail was clicked. And since we're going to display the details in the parent component, we need a way to share the data from the child component up to the parent component. Now we use the input decorator to share data from the parents of the child. To share from the child to the parent, we use the output decorator and the event emitter. Let's update the code to get this communication working in our application. In housing list component .ts, we need to import output and event emitter from angular core. Next, we'll create a property called selected location event and use the output decorator and assign the value to be a new event emitter of type housing location. Again, types are going to help us because we can have expectations of our code. When the selected location event is handled, the code can expect some data of type housing location. And that's opposed to something unpredictable. So what's next in this process? Well, we'll need to trigger the location selected event whenever user clicks on a location from the list. Let's add that code now. Underneath the search housing locations method, we'll add a new method called select housing location, and it'll take a housing location as a parameter. Then in the body of the method will emit a new event from the location selected event emitter. The value that will emit is the location that was selected by the user. Right. Let's link this to our template. In housing list component that HTML, let's update that article element once again. This time we're going to add a button element as a child with a label that reads view and add a click event to it. We're going to set the value of the click event to be select housing location and pass in the location variable from our ng4. This way, every one of these repeated items will be clickable and have a reference to the correct location. The housing locations each have a button that is now clickable and we know which location has been clicked. The final step is to hook this up in our parent component app component. Over an app.component that HTML, let's update the app housing list element. Right now it has an input so that we can send data to it from the parent component, but it now has an event that we can listen to in order to get values out of the component. So in our case, the event name is housing location selected, which is the same name as the event emitter that we created in the housing list.component.ts file. The names should match here. And since it is an event, we'll surround it with parentheses too. Now we should provide an event handler to deal with the event when it happens. We'll call that event handler update, select the location and pass it the special value of dollar sign event. The dollar sign event argument will be an object of type housing because that's what we set the event emitter's type parameter to be. Angular handles all of this part force. We just need to confirm that our templates are correct. We haven't implemented the update selected location function yet, so let's do that in app.component.ts. We'll need to make two changes here. First, we'll need to add a property called selected location of type housing location or undefined. Then we'll add the update selected location function, which takes a parameter of type housing location. We have to allow for the selected location to also include the undefined type because we may not have a selected location. Now one way to get around this is to set a default value. In the body of the function, we'll set the value of this dot selected location to be the parameter location. With this part complete, the last step is to update the template to display the selected location. In app.component.html, we'll update the template to add a sibling element to the app housing list component. We'll add an article element and inside that element, we'll display the details of our selected location. Let's display the photo, the name, the city, and the rest of the properties. Now we're going to use the optional chaining operator when we're treating these values because we don't know for sure that the values are defined since the selected location type is housing location or undefined. If it turns out to be undefined, then we don't want our application to crash. That's not a good experience for the user. And for laundry and wi-fi, we'll use a bit more template syntax here and add ternary expressions that will display a more human readable message. Has laundry does not have laundry and has wi-fi does not have wi-fi. Let's save the code and return to our browser. If we search for a location and click view, we can see the details. Wow, this app is looking awesome and we have some great functionality. But there's a slight problem though. When the page first loads, the UI has some unexpected details being displayed. Angular has some neat features that can help us solve this issue and improve the user experience. But we'll do that in the next step because right now I want to celebrate. Excellent work so far friends. We've really made some great progress on the application. We can share data from the child components to the parent components using the output decorator and the event emitter. We've also successfully allowed our users to enter a value, search using that value, then display the results and click the view to see more details. That's incredible work. I wish I could give you a double high five. Let's clean up our templates and then we'll be done building the Fairhouse application. The UI contains those artifacts because we're displaying them no matter what. What we need to do is conditionally display those details based on whether or not the user has selected a housing location. This is a perfect fit for the ngif feature provided by Angular. We'll use two Angular features to solve our issue. If we use the ngif directly on the article element, the UI will shift which may lead to a poor user experience. Let's wrap the details in an element that we can show or hide in the UI. Now we could use something like a div element but that would add unnecessary elements to our DOM. Angular has an element called ngcontainer that will not be rendered in the final output but we can add the ngif directive to it. Let's update the code in app.component.html. Next, add the ngif directive to the ngcontainer element. We have to include the abstract here and set the condition to be selected location. The contents of the ngcontainer element will only be displayed if selected location is truthy. Save this code and let's head to the browser and confirm that the functionality is what we expect. The page starts off with no search results and no panel. Perfect. We'll search for a location, then click the view button and there it is, our nice details panel. There's one final update we can make to our application. The search results in housinglist.component.html should display more details. In housinglist.component.html, update the code to feature a few more details for each location. Save this code and confirm in the browser that our beautiful application is fully functional with a complete UI. Wow, wow, wow, can you believe this? We just built a feature complete version of our web app. I'm so proud of you and I see that you did some great work here. We've just covered how to send events and data from the child components to the parent components, the output decorator and event emitter, how to conditioning display elements and templates with ngf, and how we can use optional chaining operator and ternary expressions in templates. We've created a beautiful functional application that is ready for you to extend and continue building. If you want to continue to build functionality, here are some ideas. The data is horror coded in the application. A great refactor is to add a service to contain the data. The details page is currently being displayed on the same page, but it would be cool to move the details to their own page and take advantage of Angular's router. One of the updates could be to host the data at a rest endpoint and use Angular's HTTP package to load the data at runtime. There's lots of opportunity for fun. Friends, thanks so much for spending time with me today building this Angular application. We've had so much fun and learned a lot. Remember, you can find this code in the Code Lab and on GitHub. You can continue your Angular journey by following us on Twitter and YouTube for fresh Angular content. Until the next time, go build great apps.