Wednesday, 5 December 2018

Passing data between the nested component in Angular

Background

In the last post, we saw how we can create nested components in Angular -
We also saw a few other angular things - links creating a new App, using Angular CLI, understanding project structure etc. All the links are in the related links section at the bottom. In this post, I will show you how to pass data from parent component to child component and listen for data to be passed from child to parent. 

I am going to continue using previous code example that we have built so far. So if you need additional guidance before we start with this code, look up the previous post that talks about building nested components

Passing data between the nested component in Angular

At this point, you should have a parent component called NewEmployeeComponent and a child component called SubempComponent. Child component just has a static HTML saying that subcomponent works. And it gets rendered as part of the parent component. All of this works and we saw it in the last post. If you do have a question till here I would recommend to go back and read my previous post -
Now let's add some input and output properties in the child component. Your child component code should look like below -

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
  selector: 'app-subemp',
  templateUrl: './subemp.component.html',
  styleUrls: ['./subemp.component.css']
})
export class SubempComponent implements OnInit {


  @Input()
  department:string;


  @Input()
  designation:string;


  @Output()
  joined:EventEmitter<string>;


  constructor() {
    this.joined = new EventEmitter();
  }


  ngOnInit() {
    console.log("SubempComponent initialized");
  }


  onButtonClick = function(event) {
    console.log("Button clicked. Emitting now!")
    this.joined.emit("Joined department " + this.department + " with designation " + this.designation);
  }


}

Notice here that department and designation are two parameters which are input and are of type string. So we would expect the parent component to send it to this child component. Next, we have an output parameter called joined which is an EventEmitter. Parent component which creates this child component can catch and handle this output and we will see how in a moment. Finally, we have a function onButtonClick that actually emits a string saying that the button was clicked with the particular designation and department. We will now see when this function will get called. But essentially once this function is called we emit the string which the parent component can intercept and handle.

Now let's see child components HTML code -

<h1>This is sub components heading</h1>
<p>
  Yay! subemp works!
  Department : {{department}} <br/>
  Designation : {{designation}} <br/>


  <button (click)="onButtonClick($event)">Click to join!</button>
</p>


From the previous version of the code, I have just added lines to print department, designation and a button on click of which we call function onButtonClick which we just saw above. This function will, in turn, emit the event that will be caught and handled in the parent. We will now see changes in parent component and once done we will execute our code and see it in action.


Make changes to parent component typescript file so that it looks like below -

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-new-employee',
  templateUrl: './new-employee.component.html',
  styleUrls: ['./new-employee.component.css']
})
export class NewEmployeeComponent implements OnInit {

  name: string;
  age: number;

  constructor() { }

  ngOnInit() {
    this.name = "Aniket";
    this.age = 27;
  }

  childClickedButton = function(event) {
    console.log("Child component clicked. event : " + event);
  }

}



Notice that the only new change here is a new function called childClickedButton that we will use to catch and handle the output of child component we say above.

Now make changes to the parent's HTML file so that it looks like below -

<h1>Welcome to the Employee portal</h1>

<h3>Name : {{name}}</h3>

<h3>Age : {{age}}</h3>

<app-subemp

    [department]="'IT'"
    [designation]="'Software developer'"
    (joined)="childClickedButton($event)"
></app-subemp>

</pre>



We have changed some things in the way we add child component in the HTML file. This is how we send input to the child component and handle the output. It's called data binding. So we are essentially sending department and designation as inputs to the child component. We saw these as @input() variables in child component. Similarly, we are now catching joined which was a output and calling our user defined function childClickedButton function. So the string emitted by the child on the actual button clicked will be sent as the event to this function.

Now let's see this in action. Run the app with command -

  • ng serve -o
You should see the following screen -




Make sure you go to the correct URL path to render the components. Now you can click the "click to join" button in the parent and see the console logs. You should see the following -






You can see the button click event happened which emitted the event from the child. Parent captured it and printed another console log. That's how you can configure inputs and outputs for nested angular components and pass data.


Related Links


  • Angular Hello World example
  • Understanding angular application folder structure
  • Routing and navigation in Angular
  • Tuesday, 27 November 2018

    Building nested components in Angular

    Background

    So far in learning Angular, we have seen following posts -
    1. Angular Hello World example
    2. Understanding angular application folder structure
    3. Routing and navigation in Angular
    This post is the continuation of the same series. If you are directly landing on this post please do take a look at above posts to understand the basics. This post assumes you have an Angular project set up with a component and it's navigation.

    In this post, we will try to add a new component that will be used in our existing component.


    Building nested components in Angular

    In the last post, we created a new component new-employee and set up navigation for it. Following is the final output from it.



    In this post, we will create a new component and add it inside our new-employee component. So let's create a new component. To do that execute the following command -

    • ng g c employee/subemp
    This is shorthand for -
    • ng generate component employee/subemp
    Your output should look like -


    athakur@athakur-Inspiron-7560:~/Documents/per_code/angulardemo$ ng g c employee/subemp
    CREATE src/app/employee/subemp/subemp.component.css (0 bytes)
    CREATE src/app/employee/subemp/subemp.component.html (25 bytes)
    CREATE src/app/employee/subemp/subemp.component.spec.ts (628 bytes)
    CREATE src/app/employee/subemp/subemp.component.ts (269 bytes)
    UPDATE src/app/app.module.ts (597 bytes)
    

    Notice the new files created and the root module updated with import and declaration of the new component. This is exactly the same steps we did for our earlier component. If you recall in the last post we generated the new-employee component similar way -
    • ng generate component employee/new-employee 
    The directory structure should look like below now -




    Now let's start adding code. First, go to subemp.component.ts and add/edit code so that it looks like below -

    import { Component, OnInit, Input } from '@angular/core';
    @Component({
      selector: 'app-subemp',
      templateUrl: './subemp.component.html',
      styleUrls: ['./subemp.component.css']
    })
    export class SubempComponent implements OnInit {
      constructor() { }
      ngOnInit() {
        console.log("SubempComponent initialized");
      }
    }
    


    This is a very basic boilerplate code.  Notice that this components HTML is in file './subemp.component.html' and similarly, CSS is in './subemp.component.css'. Also, note that this components selector is called 'app-subemp'. So that's the tag we will use in the parent's HTML template file.

    Let's make changes to the child's HTML template now. Go to './subemp.component.html'  and add following code.

    <h1>This is sub components heading</h1>
    <p>
      Yay! subemp works!
    </p>
    
    

    There are no changes needed in the CSS file. But if you are defining custom CSS then you can add it in 
    './subemp.component.html'. Now finally let's add the child component in the parent component. So go to parent components HTML file - new-employee.component.html and make sure it looks like below -


    <h1>Welcome to the Employee portal</h1>
    <h3>Name : {{name}}</h3>
    <h3>Age : {{age}}</h3>
    <app-subemp></app-subemp>
    


    The only new thing that we have added here is an <app-subemp></app-subemp> tag that we say was the selector of the child component. Now finally run -
    • ng serve -o
    to build and run your angular app and you should see below output in the browser.




    You can see how the sub-component renders inside the parent component.

    Also, note that we added this route in the last post. So we are just navigating to this route and seeing the changes.

    If you are wondering how it figures out the app-subemp tag then you can look at the app.module.ts file which is the angular root module file. Here we have imported this new component and added in the declaration section. This automatically happens when you use angular cli to generate a new component like we did above with command -

    • ng generate component <component_name>
    In the subsequent posts, we will see some more angular topics so stay tuned.



    Related Links

    Sunday, 25 November 2018

    Routing and navigation in Angular

    Background

    This post is in continuation of previous two posts on Angular -
    In this post, we will see how we can set up routing and navigation in Angular. If you are new to Angular please read the Hello World go through the posts above first. This post assumes you have a base project already setup as we did in the last post.

    Our current angular project looks something like below -




    Routing and navigation in Angular

    Before we start adding routing and navigation let's add a new component first and then we would add routing to that component. To generate a new component we can use the following command -
    • ng generate component <component-name>
    In our case, we will create a new component called new-employee and we will put it under a directory called employee. So use the following command -
    • ng generate component employee/new-employee 



    You can see it creates/updates following files -
    • CREATE src/app/employee/new-employee/new-employee.component.css (0 bytes)
    • CREATE src/app/employee/new-employee/new-employee.component.html (31 bytes)
    • CREATE src/app/employee/new-employee/new-employee.component.spec.ts (664 bytes)
    • CREATE src/app/employee/new-employee/new-employee.component.ts (292 bytes)
    • UPDATE src/app/app.module.ts 

    Let's try to understand what each file is -
    • new-employee.component.ts : Components typescript file
    • new-employee.component.html : Components HTML file
    • new-employee.component.css:  Components CSS file
    • new-employee.component.spec.ts : File corresponding to the test for the component
    • src/app/app.module.ts : New Component is added to imports and declaration in the main module file.
    Now that we have generated our new component let's add some HTML for it. Notice it is similar to the root component in terms of file and structure. Root component is used to render the main page and all the remaining component can be rendered/navigated through the main component. Root component is always added in the bootstrap property of the main angular module. In our case it is AppComponent. Our code and directory structure should look like below -


    Now let's add some code to our new component. First, we will add some variables that we can dynamically set and bind in our HTML file. So go in the components typescript file (new-employee.component.ts) and add name and age as variables. In the ngOnInit method, initialize these to the values you want. So the typescript file looks like below -


    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-new-employee',
      templateUrl: './new-employee.component.html',
      styleUrls: ['./new-employee.component.css']
    })
    
    export class NewEmployeeComponent implements OnInit {
    
      name: string;
      age: number;
      constructor() { }
      ngOnInit() {
        this.name = "Aniket";
        this.age = 27;
      }
    }
    

    Now let's write the corresponding HTML file (new-employee.component.html). Remove any existing code that might be present there and add below code -

    <h1>Welcome to the Employee portal</h1>
    
    
    <h3>Name : {{name}}</h3>
    <h3>Age : {{age}}</h3>
    

    Notice how we are binding name and age variables from our typescript file. You can possibly change this values on events and the changes should immediately reflect in the rendered page.


    Now that we have our components HTML and typescript file ready let's do our navigation setup. Note you can also add your custom CSS in new-employee.component.css. To add navigation we will make changes in app-routing.module.ts file.

    If you remember our first tutorial we when we created our angular app we said setup routing to yes. This should create an app-routing.module.ts file for you. This should already have the boilerplate code for routing like importing router modules and exporting the module itself so that it can be imported into our main module. Make changes to this file so that it looks like below -

    import { NgModule } from '@angular/core';
    import { Routes, RouterModule } from '@angular/router';
    import {NewEmployeeComponent} from './employee/new-employee/new-employee.component'
    
    const routes: Routes = [
      { path: 'newemployee', component: NewEmployeeComponent }
    ];
    
    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule]
    })
    
    export class AppRoutingModule { }
    


    Here we have imported our new component. That's line -
    • import {NewEmployeeComponent} from './employee/new-employee/new-employee.component'
    Then we have added a route for this component in the empty array the boilerplate code had. This essentially says if anyone tried to access the "/newemployee" path then use the NewEmployeeComponent and render it to the router outlet. We will come to router outlets in a moment. 

    So that's the two changes we have done. Now go back to app.module.ts and verify that 
    1. NewEmployeeComponent is imported and added to the declaration section.  
    2. AppRoutingModule is imported and added to the imports section
    Once you have verified this, we have one last thing to do - add router outlet. Before I proceed let me summarize the angular bootstrap process that happens. We know our configuration is in the angular.json file which points to our main file main.ts that essentially bootstraps our main module app.component.ts. The main module will try to load the root component app.component.ts that has selector app-root by default. This selector is used in our main index.html page which us again configurable from angular.json. You can also notice that default index.html file has the tag   <app-root></app-root> in the body which is where our root component renders. You would also see that AppComponent which is our root component is listed in the bootstrap property in the main module. 


    As you must have already been wondering there is no routing support added so far. And that is correct. We need to tell angular where the component should render. And for this, we use a special tag called -
    • <router-outlet></router-outlet>
    So let's add this in our root component HTML file. So go to app.component.html and make changes so that it looks like below -


    <div class="hello-world">
      <h1>Hello World!</h1>
    
      <p>----------</p>
      <h1>Routed modules go below</h1>
      <p>----------</p>
      <router-outlet></router-outlet>
      <p>----------</p>
    </div>
    


    Notice that <router-outlet></router-outlet> tag I have added. This is where our new component would get rendered. Now go to the app in the command line and execute -
    • ng serve -o
    You should see below the screen when you navigate to -

    • http://localhost:4200/newemployee

    You can see how our new component got rendered inside our root component. Root component generally has the layout design and based on users navigation we can render the custom component. We will continue to see more angular concepts in upcoming posts. So stay tuned!




    Related Links

    Sunday, 18 November 2018

    Understanding angular application folder structure

    Background

    In the last post, we saw how to write a simple "Hello World!" application -
    In this post, I will try to explain the directory structure and importance of various files and folders in the angular project that we generated.


    NOTE: This is for angular 7. Folder structure and file names might be different in previous versions of angular.

     Understanding the angular application folder structure

     If you see the previous post the directory structure generated was as follows -


    We go try to see all the files and folders in the above picture and see what each does.

    e2e

    e2e stands for end to end. This consists of your end to end integration tests. these tests are run as if it is a real user testing but are actually simulated one. This includes opening a browser, navigating to the page, clicking on UI elements etc.


    This uses a package called protractor. You can find more details about protractor in https://www.protractortest.org/#/.

    node_modules

    If you are familiar with node environment this requires no special introduction. Angular app is essentially a node package. You can see there is a file called package.json in the root folder of your generated application. It defines dependencies of your node package. So that when you run "npm install" these dependencies are installed. These dependencies go under a folder called "node_modules" which is in the same folder as package.json. 


    src/app

    This folder is the source folder of your angular application. It contains all the source code that you write for your angular app to render. This will have files corresponding to your module, components, templates, css/saas files etc. The angular app will have at least one module and component.

    src/assets

     As the name suggests this folder should store all your static assets like images, icons etc.

    src/enviroments

    This folder contains the configuration for environments you define. By default, it would have 2 environments -
    1. environment.prod.ts : For production environment
    2. environment.ts  : For development environment

    favicon.ico

    This is the icon that gets showed when your browser loads your page.


    index.html

    This is the main HTML file that loads. You can see it has tag -
    • <app-root></app-root>
    This tag corresponds to the selector of bootstrap component(app.component.ts) that is defined in your root module(app.module.ts).


    main.ts

    This is our main type script file. Here we can bootstrap our module as -

    platformBrowserDynamic().bootstrapModule(AppModule)
      .catch(err => console.error(err));
     
    

    polyfills.ts

    This type script file contains scripts that are needed by angular since the javascript feature may not be available in the browser. So basically it fills the gap to provide the features of JavaScript that are needed by Angular application and the features supported by your current browser.

    For example, IE may not support a File or a blob object. In this file, you can add your custom definitions.

    style.css

    This file contains your common styles that are global to the application. It could be a css or a saas file depending on what you choose during creation of your angular application.

    karma.conf.js

    This file is used to store the setting of Karma. Karma is used for unit tests while protractor that we saw above is used for end to end tests. For details see https://karma-runner.github.io/latest/index.html

    NOTE: Karma is a great tool for unit testing, and Protractor is intended for end to end or integration testing. This means that small tests for the logic of your individual controllers, directives, and services should be run using Karma. Big tests in which you have a running instance of your entire application should be run using Protractor. Protractor is intended to run tests from a user's point of view - if your test could be written down as instructions for a human interacting with your application, it should be an end to end test written with Protractor.

    test.ts

    This file is required for doing the testing setup.  This file is required by karma.conf.js and loads recursively all the .spec and framework files.


    angular.json

    This is the main file from which angular configuration is loaded. If you see this file it will have reference to all files - mian.ts, indes.html etc. All configuration needed for your angular application to build and run resides here.


    NOTE: In previous versions of angular this file was called angular-cli.json.


    package.json

    As mentioned in node_modules section, package.json is a descriptor file for any node project. It defines project name, it's dependencies etc.

    tsconfig.json

    This has configurations related to your typescript compiler. Your typescript compiler will look at these settings and converts type script to javascript that the browser understands.

    tslint.json

    This file has the liniting configuration. Rules that developers must follow to maintain the codebase in a standard way.

    .gitignore

    This is a file that git understands and whatever you add inside this file will be ignored by git for version control.




    Related Links

    Angular Hello World example

    Background

    In some of the earlier post, we saw Angular JS which is the older version of angular. 

    Current LTS version of angular is angular 6 (at the time of this writing). We will however be using angular 7 which is the active angular release.  In this post I will show you how to write a simple angular Hello World app. In the subsequent posts we will try to understand all files in the angular app and their purpose, angular routing, data binding etc.


    Angular CLI

    For generating angular app and it's components we are going to use Angular CLI (command line interface). You can see the wiki here. You need to have npm (node package manager) installed for this. If not please refer to my earlier posts on NodeJS(Links in the related section at the bottom).

    To install Angular CLI execute following command -
    • npm install -g @angular/cli 
     NOTE: You may have to run it with sudo of you are seeing permission issues. Once installed you can verify the installation by typing

    • ng --version



     Once angular CLI is installed you are all set to create your 1st angular app.



    Angular Hello World example

    Now let's create a new angular app, to begin with. To create a new angular application execute following command -

    • ng new angulardemo
     It if of format
    • "ng new projectname"

     You will now be asked for choices like would you like to add routing to the application. Would you be using CSS, SASS etc? For now, select Yes for routing and CSS as an option. We will see this later. For our current demo, these are not really essential.




     Once done you can go into the project directory and run.
    • ng serve -o
     This should build your app and open it in your browser.




     This is what the default application looks like. Now it's time to make some changes of our own. To do that open your application in your favorite IDE. I prefer using Visual Studio code. If you ae using this you can just open your project by going into the project directory and running -
    • code .
    The directory structure looks like below -



     As you can see there are bunch of files here but not to worry. We will see each in time. In this post, we will see how we can make changes and deploy our own code.


    The entry point is a file called angular.json. This file has all the configuration information used for building and developing your angular app. Look at the following part-


              "options": {
                "outputPath": "dist/angulardemo",
                "index": "src/index.html",
                "main": "src/main.ts",
                "polyfills": "src/polyfills.ts",
                "tsConfig": "src/tsconfig.app.json",
                "assets": [
                  "src/favicon.ico",
                  "src/assets"
                ],
                "styles": [
                  "src/styles.css"
                ],
                "scripts": []
              }
    

    You can see the important files we would have to check. You can see the index file is "src/index.html", the corresponding type file is "src/main.ts". Similarly, the CSS file is "src/styles.css". There are other files but not to worry about it as of now. We will just worry about these files for now.

    Now let's go to our index.html and here you can see the following tag -
    • <app-root></app-root>
    Now let's try to understand what would get rendered in this tag.  As I mentioned before the main file in "main.html" and corresponding typescript file is "main.ts". If you go to main.ts you will see -

    import { AppModule } from './app/app.module';
    platformBrowserDynamic().bootstrapModule(AppModule)
      .catch(err => console.error(err));
    


    This basically instructs to bootstrap a module called AppModule which is located at './app/app.module'. So go to this file. And you will see the following content in it -


    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    
    import { AppRoutingModule } from './app-routing.module';
    import { AppComponent } from './app.component';
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        AppRoutingModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    
    export class AppModule { }
    


    This is the main module of your Angular app. A module can have multiple components. An angular can have multiple modules as well. You can see in the above example it imports 2 modules BrowserModule, AppRoutingModule. You can see where it is imported from. The important part to see here is the bootstrap part because that is the component that actually gets rendered on loading an angular app. So lets go to ./app.component file.


    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    
    export class AppComponent {
      title = 'angulardemo';
    }
    


    Here you can see AppComponent is a component. Also, you can see it's selector is "app-root" which we saw in index.html. You can also see the HTML file and CSS file this component is using to render itself. So let's go its HTML file './app.component.html'. You can see this has some HTML code that got rendered when we ran "ng serve" command above.

    Time to make some changes. Remove this code completely and replace it with following code.


    <div class="hello-world">
      <h1>Hello World!</h1>
    </div>
    


    Notice we have added a class for the div called "hello-world". Let's add this class to our CSS file - './app.component.css'

     .hello-world {
        font-style: italic;
    }
    


    That's it. If you already have "ng serve -o" command running your changes should get reflected immediately in the browser. If you killed the command, run it again and you should see the changes reflecting in the browser.



    You can see in above picture that "Hello world!" comes in h1 tag and in italics()as our class defined it.





    Related Links

    t> UA-39527780-1 back to top