Getting started with Standalone Components

1. Introduction

What you will build

In this codelab, you will build a wildlife photo gallery application using Angular v14. The completed application will display a set of photos and it will also feature a send message form to contact the photographer and a chat window to learn cool facts about the animals pictured in the photos.

You build everything in your application using Angular v14 and the new standalone components feature.

All references to Angular framework and Angular CLI reflect Angular v14. Standalone components are a preview feature of Angular v14, so you must create a brand new application using Angular v14. Standalone components provide a simplified way to build Angular applications. Standalone components, standalone directives, and stand alone pipes aim to streamline the authoring experience by reducing the need for NgModules. Standalone components are able to take full advantage of the existing ecosystem of Angular libraries.

This is the application you are building today.

Completed Application

What you will learn

  • How to use the Angular CLI to scaffold a new project
  • How to use Angular standalone components to streamline the development of Angular apps
  • How to create a standalone component; which is how to build the UI and add some business logic
  • How to bootstrap an application using a standalone component
  • How to lazy load a standalone component
  • How to embed a chat dialogue in a standalone component using Dialogflow Messenger
  • How to deploy an Angular application to Google Cloud App Engine using Google Cloud CLI (gcloud)

What you will need

  • A Gmail or Google Workspace account
  • Basic knowledge of the following subjects
    • HTML. How to create an element.
    • CSS and less. How to use a CSS selector and create a style definition file.
    • TypeScript or JavaScript. How to interact with the DOM structure.
    • git and GitHub. How to fork and clone a repository.
    • Command-line interface, such as bash or zsh. How to navigate directories and run commands.

2. Environment setup

Set up your local environment

To complete this codelab, you must install the following software on your local computer.

  • An active LTS or maintenance LTS version of Node.js. Used to install the Angular framework and Angular CLI.

    Node Version

    Supported by Angular

    14.15 or newer

    Supported

    16.10 or newer

    Supported

    18.1.0

    Not supported

    To verify the version of Node.js on your local computer, run the following node command from a command-line window.
    node -v
    
  • A code editor or IDE. Used to open and edit files.Visual Studio Code, or another code editor of your choice.

Install the Angular CLI

After you configure all of the dependencies, run the following npm command to install the Angular CLI from a command-line window.

npm install --global @angular/cli

To confirm that your configuration is correct, run the following Angular command from a command-line.

ng version

If the Angular command successfully completes, you should receive a message similar to the following screen capture.

Terminal output of angular version

Source code and images

You create the whole application from scratch and this step-by-step codelab assists you. Keep in mind that the GitHub repository contains the final code. If you get stuck, review the final code and the images displayed on the gallery page.

To download the source code.

  1. In your browser, navigate the following page.
    https://github.com/angular/codelabs/tree/standalone-components
    
  2. In a command-line window, fork and clone the repository.

In the next step, build your Photo Gallery application.

3. Create a new application

To create the initial starter application, complete the following actions.

Use the Angular CLI to create a new workspace. To learn more about the Angular CLI and the Angular framework, go to angular.io.

Create a new project

In a command-line window, complete the following actions.

  1. Enter the following Angular command to create a new Angular project named photo-gallery-app.
    ng new photo-gallery-app
    
  2. At each prompt, accept the default choice.The Angular framework installs the required packages and dependencies. The process may take a few minutes.

After the Angular CLI completes, you have a new Angular workspace and a simple ready-to-run application.

Your new application is structured like a standard Angular application. The NgModule in your new application is redundant for this codelab.

Remove the application module

To remove the application module, complete the following action.

  1. Navigate to the src/app directory in your new photo-gallery-app project directory.
  2. Delete the app.module.ts file.

After you delete the application module, you have no module in your application. Your application has only one component, which is the application component You must declare the component as standalone.

Declare your standalone component

In a code editor, complete the following actions.

  1. Navigate to the src/app directory in your new photo-gallery-app project directory.
  2. Open the app.component.ts file.
  3. Add the following parameter and value to your list of decorators.
    standalone: true
    
    The app.component.ts file should closely match the following code example.
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css'],
      standalone: true
    })
    export class AppComponent {
      title = 'photo-gallery-app';
    }
    
  4. Save the app.component.ts file.

Compile your new standalone application

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory
  2. Enter the following Angular command to compile your new application.
    ng serve
    

Your application should fail to compile. Do not worry, you just need to fix a couple of more things.

Use the bootstrapApplication API

To allow your application to run without an NgModule, you must use a standalone component as the root component using the bootstrapApplication API.

Remove references to the application module

In a code editor, complete the following actions.

  1. Navigate to the src directory in your new photo-gallery-app project directory
  2. Open the main.ts file.
  3. Remove the following import code, since you no longer have an application module.
    import { AppModule } from './app/app.module';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    
  4. Remove the following bootstrap code, since you no longer have an application module.
    platformBrowserDynamic().bootstrapModule(AppModule)
      .catch(err => console.error(err));
    
    The main.ts file should match the following code example.
    import { enableProdMode } from '@angular/core';
    import { environment } from './environments/environment';
    
    if (environment.production) {
      enableProdMode();
    }
    

Add the bootstrapApplication component

In a code editor, complete the following actions.

  1. Navigate to the src directory in your new photo-gallery-app project directory.
  2. Open the main.ts file.
  3. Import the bootstrapApplication component from the @angular/platform-browser service.
    import { bootstrapApplication } from '@angular/platform-browser';
    
  4. Add the following code to bootstrap your application.
    bootstrapApplication(AppComponent).catch(err => console.error(err));
    
  5. Import the component and the required libraries.
    import { AppComponent } from './app/app.component';
    
    The main.ts file should match the following code example.
    import { enableProdMode } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import { AppComponent } from './app/app.component';
    import { environment } from './environments/environment';
    
    if (environment.production) {
      enableProdMode();
    }
    
    bootstrapApplication(AppComponent).catch(err => console.error(err));
    

Add router and common modules

To use the Router and other common module features you have to directly import each module into the component.

In a code editor, complete the following actions.

  1. Navigate to the src/app directory in your new photo-gallery-app project directory.
  2. Open the app.component.ts file.
  3. Import the required modules into the component.
    import { CommonModule } from '@angular/common';
    import { RouterModule } from '@angular/router';
    
  4. Add the imports in the component.
    imports: [CommonModule, RouterModule],
    
    The app.component.ts file should match the following code example.
    import { Component } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { RouterModule } from '@angular/router';
    
    @Component({
      selector: 'app-root',
      imports: [CommonModule, RouterModule],
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css'],
      standalone: true
    })
    export class AppComponent {
      title = 'photo-gallery-app';
    }
    
  5. Save the app.component.ts file.

Compile and run your new standalone application

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Enter the following Angular command to compile and run the application and open a web server. You might need to close your IDE prior to running your application to remove any compilation errors.
    ng serve
    

Your development server should run on port 4200. All previous errors should be gone and compilation should be successful. Well done. You have successfully created an Angular application that runs without a module and with a standalone component.

  1. Next, you are going to beautify your application to display some photos.

4. Display the photos

Your new application is designed to be a photo gallery and should display some photos.

Components are the core building blocks for Angular apps. Components have 3 main aspects.

  • An HTML file for the template
  • A CSS file for the styles
  • A TypeScript file for the behavior of the app

Move the photos to your application

The pictures are provided in the application that you previously downloaded from GitHub.

  1. Navigate to the src/assets directory of the GitHub project.
  2. Copy and paste the files into the analogue directory in your photo-gallery-app project directory.

Create the HTML template

The app.component.html file is the HTML template file associated with the AppComponent component.

In a code editor, complete the following actions.

  1. Navigate to the src/app directory in your new photo-gallery-app project directory.
  2. Open the app.component.html file.
  3. Delete all the existing HTML.
  4. Copy and paste the HTML from the following code example.
    <article>
        <h1>Above and below the Ocean</h1>
            <h2>A taste of the Australia and Galapagos Wildlife, meet my friends!</h2>
            <section>
                <section class="row">
                    <div class="column">
                      <img src="/assets/49412593648_8cc3277a9c_c.jpg">
                      <img src="/assets/49413271167_22a504c3fa_w.jpg">
                      <img src="/assets/47099018614_5a68c0195a_w.jpg">
                    </div>
                    <div class="column">
                      <img src="/assets/41617221114_4d5473251c_w.jpg">
                      <img src="/assets/47734160411_f2b6ff8139_w.jpg"> 
                      <img src="/assets/46972303215_793d32957f_c.jpg">
                    </div>
                    <div class="column">
                      <img src="/assets/45811905264_be30a7ded6_w.jpg">
                      <img src="/assets/44718289960_e83c98af2b_w.jpg">
                      <img src="/assets/46025678804_fb8c47a786_w.jpg">
                    </div>
                  </section>
            </section>
    </article
    
  5. Save the app.component.html file.

Create the style definition file

In a code editor, complete the following actions.

  1. Navigate to the src directory in your new photo-gallery-app project directory.
  2. Open the styles.css file.
  3. Copy and paste the CSS from the following code example.
    article {
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;
      font-family: 'Raleway';
    }
    
    h1 {
      color: #4479BA;
      text-align: center;
      font-size: xx-large;
    }
    
    h2 {
      color: rgb(121, 111, 110);
      text-align: center;
    }
    
    .row {
      display: flex;
      flex-wrap: wrap;
      padding: 0 4px;
    }
    
    /*   Create four equal columns that sits next to each other */
    .column {
      flex: 25%;
      padding: 0 4px;
    }
    
    .column img {
      margin-top: 8px;
      vertical-align: middle;
      width: 100%;
    }
    
    .link_button {
      -webkit-border-radius: 4px;
      -moz-border-radius: 4px;
      border-radius: 4px;
      border: solid 1px #20538D;
      text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4);
      -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2);
      -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2);
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2);
      background: #4479BA;
      color: #FFF;
      padding: 8px 12px;
      text-decoration: none;
      margin-top: 50px;
      font-size: large;
    }
    
    @media screen and (max-width: 800px) {
      .column {
        flex: 50%;
        max-width: 50%;
      }
    }
    
    @media screen and (max-width: 600px) {
      .column {
        flex: 100%;
        max-width: 100%;
      }
    }
    
    
  4. Save the styles.css file

Update the index file

In a code editor, complete the following actions.

  1. Navigate to the src directory in your new photo-gallery-app project directory.
  2. Open the index.html file.
  3. Add the Raleway font to allow all pages to inherit it.
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway">
    
  4. Save the index.html file.
  5. Save the code and check your browser. With the development server running, the changes are reflected in the browser when you save.
  6. Next, you are going to create a new standalone component to send feedback and chat with Jimbo. Continue this codelab to find out more about Jimbo.

5. Add a new standalone component

As you have seen so far, standalone components provide a simplified way to build Angular applications by reducing the need for NgModules. In the following sections, you create a new standalone component that allows the user to send feedback and chat with a virtual agent.

Create a new standalone component

To create this new component, you use the Angular CLI again.

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Enter the following Angular command to create a new component named feedback-and-chat.
    ng generate component feedback-and-chat --standalone
    
    The following table describes the parts of the command.

    Part

    Details

    ng

    Defines all of the Angular CLI commands for the Angular framework

    generate component

    Creates the scaffolding for a new component

    feedback-and-chat

    The name of the component

    --standalone

    Tells the Angular framework to create a standalone component

Import the new standalone component

To use the new standalone component, you must first add it to the imports array in the app.components.ts file.

This is a standalone component, so you just import it as if it was a module.

In a code editor, complete the following actions.

  1. Navigate to the src/app directory in your new photo-gallery-app project directory.
  2. Open the app.component.ts file.
  3. Import the new standalone component.
    import { FeedbackAndChatComponent } from './feedback-and-chat/feedback-and-chat.component';
    
  4. Update the imports in the component.
    imports: [CommonModule, RouterModule, FeedbackAndChatComponent],
    
    The app.component.ts file should match the following code example.
    import { CommonModule } from '@angular/common';
    import { Component } from '@angular/core';
    import { RouterModule } from '@angular/router';
    import { FeedbackAndChatComponent } from './feedback-and-chat/feedback-and-chat.component';
    
    @Component({
      selector: 'app-root',
      imports: [CommonModule, RouterModule, FeedbackAndChatComponent],
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css'],
      standalone: true
    })
    export class AppComponent {
      title = 'photo-gallery-app';
    }
    
  5. Save the app.component.ts file.

Lazy load the component

Switch from an eager loading paradigm to a lazy loading paradigm, in which the code is not shipped to the client until you need it. Lazy loading is a great approach to reduce the time to load a page, improve performance, and improve the user experience. The router handles the lazy load, which is the same for an ngModule and a standalone component.

Update the HTML template associated with the application component

To lazy load the standalone component, add a button to the UI that only activates the component when a user selects it.

In a code editor, complete the following actions.

  1. Navigate to the src/app directory in your new photo-gallery-app project directory.
  2. Open the app.component.html file.
  3. Scroll to the end of the file and add the following code example before you close the article element.
    <a class="link_button" routerLink="feedback-and-chat">Find out more about these guys!</a>
    <router-outlet></router-outlet> 
    
  4. The app.component.html file should match the following code example.
    <article>
        <h1>Above and below the Ocean</h1>
        <h2>A taste of the Australia and Galapagos Wildlife, meet my friends!</h2>
        <section>
            <section class="row">
                <div class="column">
                    <img src="/assets/49412593648_8cc3277a9c_c.jpg">
                    <img src="/assets/49413271167_22a504c3fa_w.jpg">
                    <img src="/assets/47099018614_5a68c0195a_w.jpg">
                </div>
                <div class="column">
                    <img src="/assets/41617221114_4d5473251c_w.jpg">
                    <img src="/assets/47734160411_f2b6ff8139_w.jpg"> 
                    <img src="/assets/46972303215_793d32957f_c.jpg">
                </div>
                <div class="column">
                    <img src="/assets/45811905264_be30a7ded6_w.jpg">
                    <img src="/assets/44718289960_e83c98af2b_w.jpg">
                    <img src="/assets/46025678804_fb8c47a786_w.jpg">
                </div>
            </section>
        </section> 
        <a class="link_button" routerLink="feedback-and-chat">Find out more about these guys!</a>
        <router-outlet></router-outlet>
    </article>
    
  5. Save the app.component.html file.

Configure your routes

In a code editor, complete the following actions.

  1. Navigate to the src directory in your new photo-gallery-app project directory.
  2. Open the main.ts file
  3. Import the provideRouter method and Routes module. Angular v 14.2.0 has introduced a new provideRouter method which allows us to configure a set of routes for the application.
    import { provideRouter, Routes } from '@angular/router';
    
  4. Copy and paste the following code snippet between the imports and the if statement.
    const routes = [
      {
        path: 'feedback-and-chat',
        loadComponent: () => import('./app/feedback-and-chat/feedback-and-chat.component').then(c => c.FeedbackAndChatComponent),
      }
    ]
    
  5. Copy and paste the following code snippet and replace the bootstrapApplication method.
    bootstrapApplication(AppComponent, {
      providers: [
        provideRouter(routes)
      ]
    }).catch(err => console.error(err));
    
    The main.ts file should match the following code example.
    import { enableProdMode } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import { provideRouter, Routes } from '@angular/router';
    import { AppComponent } from './app/app.component';
    import { environment } from './environments/environment';
    
    const routes = [
      {
        path: 'feedback-and-chat',
        loadComponent: () => 
          import('./app/feedback-and-chat/feedback-and-chat.component').then(c => c.FeedbackAndChatComponent),
      }
    ]
    
    if (environment.production) {
      enableProdMode();
    }
    
    bootstrapApplication(AppComponent, {
      providers: [
        provideRouter(routes)
      ]
    }).catch(err => console.error(err));
    
  6. Save the main.ts file.

Compile and review with the Chrome Developer tools

Use the Chrome Developer tools to review how the Angular framework lazy loads the component.

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Enter the following Angular command to compile and run the application and open a web server.
    ng serve
    
    Your development server should run on port 4200.

In your browser, complete the following actions.

  1. Navigate to the following page.
    http://localhost:4200
    
  2. Open Chrome Developer tools and choose the Network tab.
  3. Refresh the page to display several files, but not the feedback-and-chat component.Your screen should match the following screen capture.App screenshot with chrome devtools panel open
  4. Select the Find out more about these guys! button to route to the standalone component.The log should indicate that the component is only loaded when you hit the full router. Scroll down to the end of the list to check the component has been loaded. Your screen should match the following screen capture.App screenshot with chrome devtools panel open demonstrating lazy loaded component

6. Add the UI for the form

The send feedback form has three input UI fields and a button at the bottom. The three input UI fields are full name, sender email address, and comments.

To support the UI, add a formControlName attribute in an input element that binds to each contactForm form control associated with each of the three input UI fields.

Add the form to the HTML template

Add a form to the UI to allow a user to send feedback.

In your code editor, complete the following actions.

  1. Navigate to the feedback-and-chat.component.html file.
  2. Remove the existing HTML.
  3. Copy and paste the HTML from the following code example.
    <article>    
        <h2>Send me a message or use the chat below to learn some cool facts of the animals in the photos</h2>
        <section class="container">
            <form ngNativeValidate [formGroup]="contactForm" (ngSubmit)="onSubmit()">
                <div class="row" *ngIf="showMsg">
                    <div class="row">
                        <p>
                            <strong>Thanks for your message!</strong>
                        </p>
                    </div>
                </div>
                <div class="row">
                    <div class="col-25">
                        <label for="name">Full Name</label>
                    </div>
                    <div class="col-75">
                        <input type="text" id="fname" placeholder="Your name.." formControlName="fullname" required>
                    </div>
                </div>
                <div class="row">
                    <div class="col-25">
                        <label for="lemail">Email</label>
                    </div>
                    <div class="col-75">
                        <input type="text" id="lemail" placeholder="Your email.." formControlName="email" required>
                    </div>
                </div>
                <div class="row">
                    <div class="col-25">
                        <label for="comments">Comments</label>
                    </div>
                    <div class="col-75">
                        <textarea id="subject" formControlName="comments" placeholder="Write something.." style="height:200px" required></textarea>
                    </div>
                </div>
                <div class="row">
                  <button type="submit" class="submit">Submit</button>
                </div>
            </form>
        </section>
    </article>
    
  4. Save the feedback-and-chat.component.html file.

Update the styles file for the form

In your code editor, complete the following actions.

  1. Navigate to the feedback-and-chat.component.css file.
  2. Copy and paste the CSS from the following code example.
    /*   Style inputs, select elements and textareas */
    input[type=text], select, textarea{
      width: 100%;
      padding: 12px;
      border: 1px solid #ccc;
      border-radius: 4px;
      box-sizing: border-box;
      resize: vertical;
    }
    
    /*   Style the label to display next to the inputs */
    label {
      padding: 12px 12px 12px 0;
      display: inline-block;
    }
    
    /*   Style the submit button */
    button {
      background-color: #4479BA;
      color: white;
      padding: 12px 20px;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      float: right;
      font-size: medium;
      font-family: 'Raleway';
    }
    
    /*   Style the container */
    .container {
      border-radius: 5px;
      background-color: #f2f2f2;
      padding: 20px;
      width: 100%;
    }
    
    /*   Floating column for labels: 25% width */
    .col-25 {
      float: left;
      width: 25%;
      margin-top: 6px;
    }
    
    /*   Floating column for inputs: 75% width */
    .col-75 {
      float: left;
      width: 75%;
      margin-top: 6px;
    }
    
    /*   Clear floats after the columns */
    .row:after {
      content: "";
      display: table;
      clear: both;
    }
    
    /*   Responsive layout - when the screen is less than 600px wide, make the two columns stack on top of each other instead of next to each other */
    @media screen and (max-width: 600px) {
      .col-25, .col-75, input[type=submit] {
        width: 100%;
        margin-top: 0;
      }
    }
    
  3. Save the feedback-and-chat.component.css file.

Compile the UI update for the form

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Enter the following Angular command to compile and run the application and open a web server.
    ng serve
    
    Your application should fail to compile. Do not worry, you need to bind the form.
  3. For now, review the following items.
    • You use the formGroup property binding to bind contactForm to the form element and the ngSubmit event binding
    • The FormGroup directive listens for the submit event emitted by the form element. Then, the FormGroup directive emits an ngSubmit event that you are able to bind to the onSubmit callback function.
    • In a later step, you implement the onSubmit callback function in the feedback-and-chat.component.ts file
  4. Next, you are going to bind the form.

7. Add event handling to the form

The UI for the send feedback form is complete, but it is missing the interaction. Handling user input with forms is the cornerstone of many common applications.

In a real scenario, you need to implement business logic to complete the following actions.

  1. Parse the user input from the rendered DOM structure associated with the component.
  2. Validate the user input, which includes a Captcha or a similar mechanism to avoid bots spamming.
  3. Send an email to a designated email address.
  4. Display a friendly message back to the user.

In this codelab, you only implement the following actions.

  1. Parse the user input from the rendered DOM structure associated with the component.
  2. Display a friendly message back to the user.

You should challenge your skills and implement all four of the actions.

Add the send message form model to the component

Create and add the send feedback form model in the component class. The form model determines the status of the form. The FormBuilder service provides convenient methods to create a UI control.

In your code editor, complete the following actions.

  1. Navigate to the feedback-and-chat.component.ts file.
  2. Import the FormBuilder service and the ReactiveModule module from the @angular/forms package. This service provides convenient methods for generating controls. In the next step we will be leveraging the inject function so we need to import that one too from @angular/core.
    import { Component, inject, OnInit } from '@angular/core';
    import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
    
  3. Import the ReactiveFormsModule module.
    imports: [CommonModule,ReactiveFormsModule],
    
  4. Remove the following constructor.
    constructor() { }
    
  5. Inject the FormBuilder service through the inject function just below the class signature.
    private formBuilder = inject(FormBuilder);
    
    Use the group method from the FormBuilder service to create a form model in order to gather the name, email address, and comments from a user.
  6. Create the new contactForm property and use the group method to set it to a form model.The form model contains the name, email, and comments fields.
    contactForm = this.formBuilder.group({
      fullname: '',
      email: '',
      comments: ''
    });
    
    Define an onSubmit method to handle the form.In a real scenario, the onSubmit method allows the user to submit a feedback message to the photographer using an email message that is sent to a designated email address.In this codelab, you display the user inputs, use the reset method to reset the form, and display a user-friendly success message.
  7. Add the new onSubmit method and set the showMsg variable to true after initializing it.
    showMsg: boolean = false;
    
    onSubmit(): void {
      console.log('Your feedback has been submitted', this.contactForm.value);
      this.showMsg = true;
      this.contactForm.reset();
    }
    
    The feedback-and-chat.component.ts file should match the following code example.
    import { Component, inject, OnInit } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
    
    @Component({
      selector: 'app-feedback-and-chat',
      standalone: true,
      imports: [CommonModule, ReactiveFormsModule],
      templateUrl: './feedback-and-chat.component.html',
      styleUrls: ['./feedback-and-chat.component.css']
    })
    export class FeedbackAndChatComponent {
    
      showMsg: boolean = false;
      private formBuilder = inject(FormBuilder);
    
      contactForm = this.formBuilder.group({
        fullname: '',
        email: '',
        comments: ''
      });
    
      ngOnInit(): void {
      }
    
      onSubmit(): void {
        console.log('Your feedback has been submitted', this.contactForm.value);
        this.showMsg = true;
        this.contactForm.reset();
      }
    }
    
  8. Save the feedback-and-chat.component.ts file.

Compile and display the send feedback form model

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Enter the following Angular command to compile and run the application and open a web server.
    ng serve
    
  3. Your development server should run on port 4200.

In your browser, complete the following actions.

  1. Navigate to the following page.
    http://localhost:4200
    
  2. Open Chrome Developer tools and choose the Console tab.
  3. Enter any values into Full Name, Email, and Comments text boxes.
  4. Select the Submit button.A success message should display on the page.
  5. Verify the values display in the Console tab.Your screen should match the following screen capture.Browser window with the console displaying json data entered into the formYou successfully implemented the code to add a send message form to the component UI and parse the user inputs.
  6. Next, you embed a chat dialogue to allow the application visitors to speak with Jimbo. Jimbo is a koala, from whom you learn some cool facts about wildlife.

8. Add a chat dialogue

Leverage experience with conversational interfaces, such as Dialogflow CX or similar platforms. A Dialogflow CX agent is a virtual agent that handles concurrent conversations with humans. It is a natural language understanding module that recognizes the nuances of human language and translates end-user text or audio during a conversation to structured data that apps and services are able to understand.

A sample virtual agent has been created for you to use already. What you need to do in this lab is to add a chat dialogue to the standalone component to let the application users interact with the bot. For this requirement, you will leverage Dialogflow Messenger, a pre-built integration that provides a customizable dialog window. When opened, the chat dialog appears in the lower right side of the screen and triggers the agent default welcome intent. The bot greets the user and initiates a conversation.

The following implementation shares fun facts about wildlife with the user. Other implementations for virtual agents may address complex use cases for customers (like a human call center agent). Many companies use a virtual agent as the primary channel of communication with the company website.

Add the Dialogflow Messenger to your component

Like the form, the chat dialog should only display when the standalone component is loaded.

In your code editor, complete the following actions.

  1. Navigate to the feedback-and-chat.component.ts file.
  2. Copy and paste the df-messenger element in the following code example anywhere into the page.
    <df-messenger agent-id="762af666-79f7-4527-86c5-9ca06f72c317"
                  chat-title="Chat with Jimbo!"
                  df-cx="true"
                  intent="messanger-welcome-event"
                  language-code="en"
                  location="us-central1"></df-messenger>
    
    Dialogflow generates the attributes for the df-messenger element when you select the Dialogflow Messenger integration.

    Attribute

    Details

    agent-id

    Prepopulated. Specifies the unique identifier of the Dialogflow agent.

    chat-title

    Prepopulated. Specifies the content to display at the top of the chat dialog. Initially prepopulated with the name of your agent, but you should customize it.

    df-cx

    Indicates that the interaction is with a CX agent. Set the value to true.

    intent

    Specifies the custom event used to trigger the first intent when the chat dialog is opened.

    language-code

    Specifies the default language code for the first intent.

    location

    Specifies the region where you deploy the agent.

  3. Save the feedback-and-chat.component.ts file.

Display the send feedback form model

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Enter the following Angular command to compile the application.
    ng serve
    
    Your application should fail to compile. The command-line should display the following error message.df-messenger error message
  3. Next, add a custom schema.

Add custom schema to the standalone component

The df-messanger element is not a known element. It is a custom Web Component. The error message from the Angular framework suggests you have to add a CUSTOM_ELEMENTS_SCHEMA to both the standalone components in order to suppress the message.

In your code editor, complete the following actions.

  1. Navigate to the feedback-and-chat.component.ts file.
  2. Import the CUSTOM_ELEMENTS_SCHEMA schema.
    import { Component, CUSTOM_ELEMENTS_SCHEMA, inject, OnInit } from '@angular/core';
    
  3. Add the CUSTOM_ELEMENTS_SCHEMA to the list of schemas.
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
    
    The feedback-and-chat.component.ts file should match the following code example.
    import { Component, CUSTOM_ELEMENTS_SCHEMA, inject, OnInit } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
    
    @Component({
      selector: 'app-feedback-and-chat',
      standalone: true,
      imports: [CommonModule,ReactiveFormsModule],
      templateUrl: './feedback-and-chat.component.html',
      styleUrls: ['./feedback-and-chat.component.css'],
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
    })
    
    ...
    
  4. The df-messanger web component requires a javascript that should be injected only when the feedback and chat component is loaded. For this purpose we are going to add the relevant code to the ngOnInit() method which will load the chat script needed to activate the element.
    ngOnInit() {
        // Load the chat script, which activates the `<df-messenger>` element.
        const script = document.createElement('script');
        script.async = true;
        script.src = 'https://www.gstatic.com/dialogflow-console/fast/messenger-cx/bootstrap.js?v=1';
        document.head.appendChild(script);
    }
    
  5. Save the feedback-and-chat.component.ts file.

Compile and display the updated chat dialog

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Enter the following Angular command to compile and run the application and open a web server.
    ng serve
    
    Your development server should run on port 4200.

In your browser, complete the following actions.

  1. Navigate to the following page.
    http://localhost:4200
    
    A chat icon should appear at the bottom of the page.
  2. Select the icon and interact with Jimbo.Jimbo provides cool animal facts.Application displaying chat window with messenger bot responding
  3. The application is fully functional.

9. Deploy the application to Google App Engine

The application is running locally on your machine. What you want to do as the next and last step of this codelab is deploy it to Google App Engine.

To learn more about the Google App Engine, see App Engine.

Set up your environment for Google App Engine

If you already meet all of the following conditions, skip the next steps and proceed to deploy the application.

  • Created a Cloud project with App Engine
  • Enabled the Cloud Build API
  • Installed the Google Cloud CLI

Complete the following actions.

  1. Sign into your Gmail or Google Workspace account. If you do not have one, create your Google Account.
  2. Enable billing in the Cloud Console to allow you to use Cloud resources and APIs. To learn more, see Create, modify, or close your self-serve Cloud Billing account.
  3. Create a Google Cloud project to hold your App Engine application resources and other Google Cloud resources. To learn more, see Creating and managing projects.
  4. Enable the Cloud Build API in the Cloud Console. To learn more, see Enable access to API.
  5. Install Google Cloud CLI and the gcloud command-line tool. To learn more, see Install the gcloud CLI.
  6. Initialize Google Cloud CLI and ensure gcloud is configured to use the Google Cloud project to which you want to deploy. To learn more, see Initializing the gcloud CLI.

Build your standalone application

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Enter the following Angular command to compile and create a production-ready version of the application.
    ng build
    

The production-ready version of the application is created in the dist subdirectory of your photo-gallery-app project directory.

10. Deploy your application using Express.js framework

The sample code in this codelab uses the Express.js framework to handle HTTP requests. You may use your preferred web framework.

Install Express.js framework

In a command-line window, complete the following action.

  1. Enter the following command to install the Express.js framework.
    npm install express --save
    

Configure your web server

In your code editor, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Create a new server.js file.
  3. Copy and paste the following code.
    const express = require("express");
    const path = require("path");
    
    // Running PORT is set automatically by App Engine
    const port = process.env.PORT || 3000;
    const app = express();
    
    const publicPath = path.join(__dirname, "/dist/photo-gallery-app");
    
    app.use(express.static(publicPath));
    
    app.get("*", (req, res) => {
      res.sendFile(path.join(__dirname + "/dist/photo-gallery-app/index.html"));
    });
    
    app.listen(port, () => {
      console.log(`Server is up on ${port}`);
    });
    
  4. Save the server.js file.

Attach your web server

In your code editor, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Open the package.json file.
  3. Modify the start command to run the node in the server.js file.
    "name": "photo-gallery-app",
      "version": "0.0.0",
      "scripts": {
        "ng": "ng",
        "start": "node server.js",
        "build": "ng build",
        "watch": "ng build --watch --configuration development",
        "test": "ng test"
      },
    
    The start attribute is the entry point for your application.
  4. Save the package.json file.

Configure App Engine

In your code editor, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Create a new app.yaml file.
  3. Copy and paste the following code.
    runtime: nodejs16
    service: default
    
    The information in the app.yaml file specifies the configuration for App Engine. You only need to specify the runtime and service.
  4. Save the app.yaml file.

Update the gcloud ignore list

To ensure that your node_modules directory is not uploaded, create a .gcloudignore file. Files listed in your .gcloudignore file are not uploaded.

In your code editor, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Create a new .gcloudignore file.
  3. Copy and paste the following code.
    # This file specifies files that are *not* uploaded to Google Cloud
    # using gcloud. It follows the same syntax as .gitignore, with the addition of
    # "#!include" directives (which insert the entries of the given .gitignore-style
    # file at that point).
    #
    # For more information, run:
    #   $ gcloud topic gcloudignore
    #
    .gcloudignore
    # If you would like to upload your .git directory, .gitignore file or files
    # from your .gitignore file, remove the corresponding line
    # below:
    .git
    .gitignore
    
    # Node.js dependencies:
    node_modules/
    
  4. Save the .gcloudignore file.

Initialize your application

Before deploying the application, initialize it with your project and choose an associated region.

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Enter the following command to initialize your application.
    gcloud app create --project=[YOUR_PROJECT_ID]
    
  3. At the prompt, choose the region where you want to locate your App Engine application.

Deploy your application

In a command-line window, complete the following actions.

  1. Navigate to your new photo-gallery-app project directory.
  2. Enter the following command to deploy your application.
    gcloud app deploy --project=[YOUR_PROJECT_ID]
    
  3. At the prompt, confirm the action.After the gcloud deployment command successfully completes, it displays a URL to access your application.
  4. Enter the following command to open a new tab in your browser.
    gcloud app browse
    
    Console output of gcloud app deploy and entering glcoud app browse

11. Congratulations

Congratulations. You created a sample photo gallery using Angular v14 and successfully deployed it on App Engine.

You experimented with the standalone component feature and lazy loading. You built a form-based send message feature to provide feedback and comments. You also successfully added a chat dialogue with a Dialogflow CX virtual agent using Dialogflow Messenger. Well done.

Next steps

Now that you have completed the basic application, improve it using the following ideas.

  • The form does not actually send feedback, refactor it to add the business logic to send an email.
  • In a real world scenario, you should validate the user input and include a Captcha or a similar mechanism to avoid bots spamming
  • Create a new agent and learn how to design conversational flows in Dialogflow CX

Continue to experiment with the Angular framework and have fun.

Clean up and delete your Cloud project

You may keep your Cloud project or alternatively delete it to stop billing for all the resources used in the project.

In your browser, complete the following actions.

  1. Sign into your Gmail or Google Workspace account.
  2. In the Google Cloud console.Select the IAM & Admin Settings button.
  3. On the IAM & Admin page.Select the Manage resources tab.
  4. On the Manage resources page.Navigate to the project that you want to delete and choose it.Select the Delete button to open a dialog window.
  5. On the dialog window.Enter the project ID.Select the Shut down button to delete the project.