Skip to content

Latest commit

 

History

History
338 lines (233 loc) · 12.7 KB

angular-02-components.md

File metadata and controls

338 lines (233 loc) · 12.7 KB

[Angular] 02 - Components In Angular

by youhengchan

Component

Component's Composition

  • Template (View, HTML)
  • Class (Code, TypeScript, Data, Methods)
  • Metadata (Information and Decorator)
    (The metadata tells angular if the class is an angular class or average class and is generated by using diffrent types of decorators)

Example (code from last section):

// app.component.ts
import { Component } from '@angular/core';

@Component({  // decorator
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  title = 'changed-name-app';
}

At the bottom, we have the class name -AppComponent. This class currently just have a property named title and got no methods. This class is decorated with docorator - Component. This decorator is a function defined by angular and attaced to the class right below it (AppComponent).

This decorator tells the angular the class AppComponent is not a plane class but a component.

The Component decorator contains both the metadata (here we have selector | templateUrl | styleUrls in the example) and the templates which represents the view.

Metadata Usage

selector : a custom HTML tag that can be used to represent specific component when you specifiy a selector in your HTML files. Angular will then render the components template in its place.
In this example project (angulartest),the selector is defined as selector: 'app-root', which means that the selector is app-root. Now move to the index.html file, we will find it is used as a tag :
[IMG1 for app.component.ts]
app.component.ts
[IMG2 for index.html]
index-html

From IMG2 (index.html), <app-root></app-root> is used as an HTML tag.So angular renders the add components template when it come across the <app-root> selector.

The template for this component is defined using the template URL:templateUrl: './app.component.html'.This template URL points to the HTML file that represents the view for this componet. Now see the content of app.component.html :

// app.component.html 
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * Delete the template below * * * * * * * * * * -->
<!-- * * * * * * * to get started with your project! * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->

<span>{{ title }} app is running!</span>    

// Many verbose lines were Omiited.

<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content above * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * End of Placeholder * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->



<router-outlet></router-outlet>

From the code above, we have : <span>{{ title }} app is running!</span> . The title in double curly braces and the title is nothing but the property in the class contained in the app.component.ts file:

// app.component.ts
export class AppComponent {
  title = 'changed-name-app';
}

So when we run the application, the HTML file - app.component.html gets replaced in the index.html file where we specify the selector(tag) - <app-root> in the index.html file. And the HTML file will then get rendered in the broswer. And finally, We can have the styles that only attached to this component and we specify the stylesheet in the app.component.css file and use the style Urls : styleUrls: ['./app.component.css'] to annouce the path to it.

Create A New Component And Use It

Component Generation

To create a new component, just use the Angular CLI with command : ng g c components/name.
The ng g c tells angular to generate a new component, and the components/name just set the path of the new component to be stored.

For example, After having typed ng g c components/test in the Angular CLI, and then we will get the following output from the terminal :

CREATE src/app/components/test/test.component.html (19 bytes)
CREATE src/app/components/test/test.component.spec.ts (614 bytes)
CREATE src/app/components/test/test.component.ts (261 bytes)
CREATE src/app/components/test/test.component.css (0 bytes)
UPDATE src/app/app.module.ts (803 bytes)

First thing that we notice is that 4 new files : test.component.html | test.component.spec.ts | test.component.ts | test.component.css were created.
And one file app.module.ts were updated.

new-compoenent-test-added

Hint : test.component.spec.ts is created for testing. But we don't need it right now, So just delete it.

delete-testing-file

Now dive into these newly created files :
test.component.css :
Empty file

test.component.html :

<p>test works!</p>

test.component.ts :

// test.component.ts
import { Component, OnInit } from '@angular/core';

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

  constructor() { }

  ngOnInit() {
  }

}

app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

// Automatically created by Angular CLI
import { NewsComponent } from './components/news/news.component';
import { News1Component } from './components/news1/news1.component';
import { TestComponent } from './components/test/test.component';

@NgModule({
  declarations: [
AppComponent,
NewsComponent,  // Add by Angular CLI
News1Component, TestComponent  // Added by Angular CLI
  ],
  imports: [
BrowserModule,
AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})

export class AppModule { }  

In the last section, we have talked about the metadata of the decorator NgModule, and now put it more specificly : declerations contains all the components used by the application. We can also find that the angular will automatically import the newly created components and add them into the declaration array. Which means that just with a single command : ng g c path/name , then you will instantly be able to use newly generated component name in your angular application.

Put New Components Into Use

To use a component, Just include the HTML tag that represents the selector of it. To find the selector's name, just look in the test.component.ts :

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css']
})

From the metadata of the Component decorator, we can get the selector name - app-test, then just use it in the any view controller (html files), like root view controller - app.component.html, or global view controller - index.html. But do not use it in the view of test Component created just now - test.component.html becacuse remember that our goal to use the selector is to include the content of the test.component.html into the target file.

First, test it in the root component - app.component.ts :
add-tags-in-app-component-html
Effect look just like what we expect :
test-works-root-component

And then test it in the global html file - index.html:
add-tags-in-index-html
Effects : Nothing changed

So, we should use our component in the root component - app.component.html.

Three Ways To Specify Selectors

The following modification to selector is always within the file test.component.ts.

  • selector : 'app-test'
    Usage : Use it as a tag . Example Code : (In the file app.component.html, the same below)

    <app-test></app-test>

(We have tested this one above)

  • selector : '.app-test'
    Usage : Use it as a class.
    Example Code :

    <div class = 'app-test'></div>

  • selector : [app-test]
    Usage : Use it in the tag without specifing class = app-test and use it as an attribute to the tag. Example Code :

    <div app-test></div>

The other two methods : use as class and enclose the selector within aquare brackets were all tested and work fine.

Write HTML And Typescript In The Same File

To avoid switching between the html files and ts file, Angular provide us a way to write HTML code in the ts file. And we just need to modify the content of the metadata of the Component Decorator :

// Original app.component.ts file
import { Component, OnInit } from '@angular/core';

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

  constructor() { }

  ngOnInit() {
  }

}



// Modified app.component.ts file  
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-test',
  template : '<div> template within ts file </div>',
  styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

We also simplify the root modules' html file :

// app.component.html
<span>{{ title }} app is running!</span>
<app-test></app-test>
<router-outlet></router-outlet>

Effect :

template

And then we can use ES6 features - Template literals(use backticks - ``) to make break lines easy :

// app.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-test',
  template: `<div> 
  break <br\>
line <br\>
 is <br\>
  easy. <br\> 
 </div>`,
  styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

} 

Effect :
template-literals

Have CSS File Also Inline .ts FILE

Just replace styleUrls with styles and then you can write CSS in the .ts file(test.component.ts).

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

@Component({
  selector: 'app-test',
  template: `<div> 
  break <br\>
line <br\>
 is <br\>
  easy. <br\> 
 </div>`,
  styles : [`
  div {
color : purple;
background-color : yellow;
  }
  
`]
})
export class TestComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

Effect :
multi-embeded-css

Hint : We can still use backticks `` to specify multiple lines of CSS.

Conclusion

  • Components are building blocks of an angular application.
  • A component contains a class, a decorator and the template which represents the view.
  • Any component has to be imported and added to the module in the declarations array and then can be used by typing the selector of the registered componets in the HTML either as a custum tag or as a class or as an attribute of the label.
  • The HTML and CSS can either be in a seperate file or be inline in the .ts file.
  • We can use backticks (``) to specify multiple lines of HTML and CSS.
  • The component class contains data that can be displayed in the view and finally it is possible nest components within other components and also reuse them when required.