O Angular é um framework de componentização de interfaces, similar ao React e Vue, que permite a arquitetura escalável de páginas web.
O Angular é um framework de componentização de interfaces, similar ao React e Vue, que permite a arquitetura escalável de páginas web.
Conceito fundamental do angular que permite o encapsulamento de seções de interface
@Component({ selector: `app-login`, templateUrl: './login.component.html', styleUrls: ['./login.component.scss'], providers: [], }) class LoginComponent { @Input() username?: string; @Output() submit = new EventEmitter<void>() // Two way binding @Input() password?: string; @Output() passwordChange = new EventEmitter<string>() onLogin() { this.submit.next(); } }
@Component({ selector: `app-login`, templateUrl: './login.component.html', styleUrls: ['./login.component.scss'], providers: [], }) class LoginComponent { @Input() username?: string; @Output() submit = new EventEmitter<void>() // Two way binding @Input() password?: string; @Output() passwordChange = new EventEmitter<string>() onLogin() { this.submit.next(); } }
As diretivas permitem ampliar a funcionalidade de seu elemento hospedeiro, permitindo alteração de suas propriedades a interceptação de eventos do DOM.
@Directive({ selector: `[appHighlight]` }) class HighlightDirective { @Input() color: string = "yellow"; constructor(private ref: ElementRef) {} @HostListener('mouseenter') onMouseEnter() { this.highlight(color); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.ref.nativeElement.style.backgroundColor = color; } }
@Directive({ selector: `[appHighlight]` }) class HighlightDirective { @Input() color: string = "yellow"; constructor(private ref: ElementRef) {} @HostListener('mouseenter') onMouseEnter() { this.highlight(color); } @HostListener('mouseleave') onMouseLeave() { this.highlight(''); } private highlight(color: string) { this.ref.nativeElement.style.backgroundColor = color; } }
@Pipe({ name: 'uppercase', standalone: true, }) export class UpperCasePipe implements PipeTransform { transform(value: string|null|undefined): string|null { if (value == null) return null; if (typeof value !== 'string') { throw invalidPipeArgumentError(value); } return value.toUpperCase(); } }
@Pipe({ name: 'uppercase', standalone: true, }) export class UpperCasePipe implements PipeTransform { transform(value: string|null|undefined): string|null { if (value == null) return null; if (typeof value !== 'string') { throw invalidPipeArgumentError(value); } return value.toUpperCase(); } }
<div> <p> {{ name | uppercase }}</p> </div>
<div> <p> {{ name | uppercase }}</p> </div>
As pipes podem receber parâmetros que são passados como argumentos para a função transform.
Os serviços dão suporte aos componentes, lidando com lógica de negócio, gerenciamento de estados e comunicação entre componentes.
@Injectable({}) class AuthService { constructor(private http: HttpClient) {} public isUserLoggedIn(): boolean { /* checa se o usuário está logado */ } public getAccessToken(): AccessToken { /* obtem a token de acesso do armazenamento */ } public async login(username: string, password: string) { return await this.http.post(/* login route */) .asPromise() } }
@Injectable({}) class AuthService { constructor(private http: HttpClient) {} public isUserLoggedIn(): boolean { /* checa se o usuário está logado */ } public getAccessToken(): AccessToken { /* obtem a token de acesso do armazenamento */ } public async login(username: string, password: string) { return await this.http.post(/* login route */) .asPromise() } }
Configura o container de injeção de depêndencias do Angular e permite a modularização do projeto por subdomínios de negócio.
@NgModule({ declarations: [ CartPageComponent, PaymentMethodComponent ], imports: [FormsModule, UiLibraryModule], exports: [PaymentMethodComponent], providers: [PaymentService], }) class CheckoutModule {}
@NgModule({ declarations: [ CartPageComponent, PaymentMethodComponent ], imports: [FormsModule, UiLibraryModule], exports: [PaymentMethodComponent], providers: [PaymentService], }) class CheckoutModule {}
Técnica de desenvolvimento de software que permite que aplicações sejam mais flexíveis, extensíveis e testáveis.
@NgModule({ provides: [ExampleService] }) class RootModule {}
@NgModule({ provides: [ExampleService] }) class RootModule {}
@Component({ provides: [ExampleService] }) class RootComponent {}
@Component({ provides: [ExampleService] }) class RootComponent {}
Em frameworks de interface com paradigma reativo, as interfaces são definidas em função de alterações (i.e. eventos) no estado do sistema.
const RootComponent = () => { const [isLoggedIn, _]= useState(false) if (isLoggerIn) { return <HomePage /> } else { return <AuthPage /> } }
const RootComponent = () => { const [isLoggedIn, _]= useState(false) if (isLoggerIn) { return <HomePage /> } else { return <AuthPage /> } }
Um observable é um emissor de valores ao longo do tempo, sem que seu consumidor possua influência sobre quando são emitidos.
Isto pode ser utilizado para representar diversos conceitos:
const obs = new Observable(sub => { let count = 1; let handle = setInterval(() => { sub.next(1); count++; }, 1000); return () => clearInterval(handle); }) const subs = obs.subscribe((count) => { console.log(count); // 1, 2, 3, 4 .... }) setTimeout(() => subs.unsubscribe(), 10000)
const obs = new Observable(sub => { let count = 1; let handle = setInterval(() => { sub.next(1); count++; }, 1000); return () => clearInterval(handle); }) const subs = obs.subscribe((count) => { console.log(count); // 1, 2, 3, 4 .... }) setTimeout(() => subs.unsubscribe(), 10000)
Possível utilizar referências no DOM para obter o status de validação do formulário
Adiciona automaticamente classes CSS aos componentes, para que possam ser estilizadas
// login-form.component.ts @Component({ templateUrls: ['./login-form.component.html'] }) class LoginFormComponent { model = { username: '', password: '', } }
// login-form.component.ts @Component({ templateUrls: ['./login-form.component.html'] }) class LoginFormComponent { model = { username: '', password: '', } }
<!-- login-form.component.ts --> <form> <input [(ngModel)]="model.username" required type="text" #username="ngModel"/> <div [hidden]="username.valid || username.pristine"> Username is required </div> <input [(ngModel)]="model.password" required type="text" #password="ngModel" /> <div [hidden]="password.valid || password.pristine"> Password is required </div> </form>
<!-- login-form.component.ts --> <form> <input [(ngModel)]="model.username" required type="text" #username="ngModel"/> <div [hidden]="username.valid || username.pristine"> Username is required </div> <input [(ngModel)]="model.password" required type="text" #password="ngModel" /> <div [hidden]="password.valid || password.pristine"> Password is required </div> </form>
Possui observables que emitem o valor do formulário quando há alguma alteração.
Utiliza-se de funções para implementar lógica de validação dos inputs.
const requiredValidator = (control: AbstractControl) => { if (control.value == null) { return { missingValue: 'Value is required' } } return null }
const requiredValidator = (control: AbstractControl) => { if (control.value == null) { return { missingValue: 'Value is required' } } return null }
@Component({ templateUrls: ['./login-form.component.html'] }) class LoginFormComponent { loginForm = new FormGroup({ username: new FormControl('', Validators.required), password: new FormControl('', Validators.required), }) }
@Component({ templateUrls: ['./login-form.component.html'] }) class LoginFormComponent { loginForm = new FormGroup({ username: new FormControl('', Validators.required), password: new FormControl('', Validators.required), }) }
<!-- login-form.component.html --> <form [formGroup]="loginForm"> <input formControlName="username" type="text" /> <div [hidden]="loginForm.username.valid || loginForm.username.pristine"> Username is required </div> <input formControlName="password" type="text" /> <div [hidden]="loginForm.password.valid || loginForm.password.pristine"> Password is required </div> </form>
<!-- login-form.component.html --> <form [formGroup]="loginForm"> <input formControlName="username" type="text" /> <div [hidden]="loginForm.username.valid || loginForm.username.pristine"> Username is required </div> <input formControlName="password" type="text" /> <div [hidden]="loginForm.password.valid || loginForm.password.pristine"> Password is required </div> </form>
A classe representa requisições HTTP como Observables.
É possível transformar os Observables em Promises, caso necessário.
class HttpClient { public get<T>(/* params */): Observable<T> public post<T>(/* params */): Observable<T> public put<T>(/* params */): Observable<T> public delete<T>(/* params */): Observable<T> public patch<T>(/* params */): Observable<T> public options<T>(/* params */): Observable<T> }
class HttpClient { public get<T>(/* params */): Observable<T> public post<T>(/* params */): Observable<T> public put<T>(/* params */): Observable<T> public delete<T>(/* params */): Observable<T> public patch<T>(/* params */): Observable<T> public options<T>(/* params */): Observable<T> }
Exemplo
@Component({ /* ... */ }) class ExampleComponent { constructor(private http: HttpClient) {} onSubmit() { this.http.post("http://example.com/api/auth/login") .subscribe({ next: () => console.log('Sucesso ao logar'), error: () => { console.log('Algo de errado aconteceu'); } }); } }
@Component({ /* ... */ }) class ExampleComponent { constructor(private http: HttpClient) {} onSubmit() { this.http.post("http://example.com/api/auth/login") .subscribe({ next: () => console.log('Sucesso ao logar'), error: () => { console.log('Algo de errado aconteceu'); } }); } }
O Angular utiliza um mapeamento de rotas para componentes de modo a fazer o roteamento de páginas da aplicação.
const ROUTES: Routes = [ { path: '', redirectTo: 'auth/login', pathMatch: 'full' }, { path: 'auth/login', component: LoginPageComponent }, { path: 'auth/register', component: RegisterPageComponent }, ] @NgModule({ imports: [RouterModule.forRoot(ROUTES)], exports: [RouterModule] }) class AppRoutingModule {}
const ROUTES: Routes = [ { path: '', redirectTo: 'auth/login', pathMatch: 'full' }, { path: 'auth/login', component: LoginPageComponent }, { path: 'auth/register', component: RegisterPageComponent }, ] @NgModule({ imports: [RouterModule.forRoot(ROUTES)], exports: [RouterModule] }) class AppRoutingModule {}
@NgModule({ imports: [AppRoutingModule] }) class AppModule {}
@NgModule({ imports: [AppRoutingModule] }) class AppModule {}
Possível agrupar os componentes em três grupos principais
Page components: componentes que representam páginas da aplicação
Container components: componentes que agrupam seções da página por funcionalidade
Presentational components: componentes que representam seções reutilizaveis da interface