[Angular] Why should we using Protal
Protal from Angular CDK, is a way to create dynammic component.
Consider an example of Page toolbar.

This toolbar should show differently content when route changed.
For example, when we changed the router to 'Contacts page':

There should be a Mat-icon (Plus icon) showing on the toolbar.
Tradional Approach:
Listening on the route changes and using *ngIf or *ngSwitch to switching template.
This approach works fine for small application, but for large application, switching logic becomes harder to control.
Also 'app-page-actions component' should have no idea 'currently it is in Home page or it is in Contacts page'. In other words, those logic should not be hard code inside the component.
Portal Approach:
To make portal works, it reuqests a host container and a component or a template.
The host container is the placeholder DOM element, this is the place <app-page-acitions> should be rendered into.
<!-- shell.component.html-->
<div fxFlex="50px" id="page-actions-container">
<!-- content will be placed dynamically via Cdk Portal -->
</div>
(full code see the bottom)
App-page-actions itself can be just a placeholder which implements content projection:
<ng-template cdk-portal>
<ng-content></ng-content>
</ng-template>
So now its upto each page to tell App-page-actions, whether there is any action or what action to be rendered. For example, the contacts page could be:
<app-page-actions>
<button type="button" class="toolbar-btn" mat-icon-button (click)="onSave()">
<mat-icon>add</mat-icon>
</button>
</app-page-actions>
To connnect portal host and portal component or template:
import {
Component,
OnInit,
AfterViewInit,
ComponentFactoryResolver,
Injector,
ViewContainerRef,
ApplicationRef,
ViewChild,
OnDestroy
} from '@angular/core';
import {
DomPortalHost,
TemplatePortal,
PortalHost,
CdkPortal
} from '@angular/cdk/portal';
@Component({
selector: 'app-page-actions',
template: `
<ng-template cdk-portal>
<ng-content></ng-content>
</ng-template>
`,
styles: []
})
export class PageActionsComponent implements OnInit, AfterViewInit, OnDestroy {
private portalHost: PortalHost;
@ViewChild(CdkPortal) portal;
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
private appRef: ApplicationRef
) {}
ngOnInit() {}
// We have to wait until DOM is created, so that we can access the DOM element
ngAfterViewInit(): void {
// Create a portalHost from a DOM element
this.portalHost = new DomPortalHost(
document.querySelector('#page-actions-container'), // get the placeholder element by Id
this.componentFactoryResolver, // you have to do this
this.appRef, // you have to do this
this.injector // you have to do this :(
);
// Attach portal to host
this.portalHost.attach(this.portal);
}
// Always remember to clean up the dynamic component
ngOnDestroy(): void {
this.portalHost.detach();
}
}
That's all.
Well, how to do is not so important, but rather why we should do it.
To summry, portal is good for
1. Better component articulture.
We know that, app-page-actions should have no idea which page current is. It should only receive the component from content projection and display it. This can be done in Content projection.
2. We have a placeholder where the app-page-actions should be rendered for different pages.
This helps Angular to understand our applications better. (better for AOT)
--------------------------
Layout:
<!-- shell.component.html-->
<mat-sidenav-container class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport="true" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
[mode]="(isHandset$ | async) ? 'over' : 'side'" [opened]="!(isHandset$ | async)">
<mat-toolbar color="primary">Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item routerLink="/home">Home</a>
<a mat-list-item routerLink="/contacts">Contacts</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()" *ngIf="isHandset$ | async">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>Application Title</span> <div fxFlex fxFill></div>
<div fxFlex="50px" id="page-actions-container">
<!-- content will be placed dynamically via Cdk Portal -->
</div>
</mat-toolbar> <div class="app-container">
<ng-content></ng-content>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
[Angular] Why should we using Protal的更多相关文章
- Angular杂谈系列1-如何在Angular2中使用jQuery及其插件
jQuery,让我们对dom的操作更加便捷.由于其易用性和可扩展性,jQuer也迅速风靡全球,各种插件也是目不暇接. 我相信很多人并不能直接远离jQuery去做前端,因为它太好用了,我们以前做的东西大 ...
- Angular企业级开发(5)-项目框架搭建
1.AngularJS Seed项目目录结构 AngularJS官方网站提供了一个angular-phonecat项目,另外一个就是Angular-Seed项目.所以大多数团队会基于Angular-S ...
- TypeScript: Angular 2 的秘密武器(译)
本文整理自Dan Wahlin在ng-conf上的talk.原视频地址: https://www.youtube.com/watch?v=e3djIqAGqZo 开场白 开场白主要分为三部分: 感谢了 ...
- angular实现统一的消息服务
后台API返回的消息怎么显示更优雅,怎么处理才更简洁?看看这个效果怎么样? 自定义指令和服务实现 自定义指令和服务实现消息自动显示在页面的顶部,3秒之后消失 1. 显示消息 这种显示消息的方式是不是有 ...
- div实现自适应高度的textarea,实现angular双向绑定
相信不少同学模拟过腾讯的QQ做一个聊天应用,至少我是其中一个. 过程中我遇到的一个问题就是QQ输入框,自适应高度,最高高度为3row. 如果你也像我一样打算使用textarea,那么很抱歉,你一开始就 ...
- Angular企业级开发-AngularJS1.x学习路径
博客目录 有链接的表明已经完成了,其他的正在建设中. 1.AngularJS简介 2.搭建Angular开发环境 3.Angular MVC实现 4.[Angular项目目录结构] 5.[SPA介绍] ...
- Angular企业级开发(4)-ngResource和REST介绍
一.RESTful介绍 RESTful维基百科 REST(表征性状态传输,Representational State Transfer)是Roy Fielding博士在2000年他的博士论文中提出来 ...
- Angular企业级开发(3)-Angular MVC实现
1.MVC介绍 Model-View-Controller 在20世纪80年代为程序语言Smalltalk发明的一种软件架构.MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并 ...
- Angular企业级开发(2)-搭建Angular开发环境
1.集成开发环境 个人或团队开发AngularJS项目时,有很多JavaScript编辑器可以选择.使用优秀的集成开发环境(Integrated Development Environment)能节省 ...
随机推荐
- C# 工厂单例
public class BusinessFactory { private static BusinessFactory instance = null; pri ...
- 免费开源ERP成功案例分享:化学之家通过Odoo实现工业互联网转型
本文来自<开源智造Odoo客户成功案例采访实录>的精选内容章节.请勿转载.欢迎您反馈阅读意见. 客户地区:江苏常州 客户名称:化学之家(中外合资) 所属行业:化工制造(工业) 实施模块:销 ...
- curl 采集的时候遇到301怎么办
采集的时候遇到301,采集数据有错误 $ch = curl_init($url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt( ...
- day02_12/12/2016_bean的实例化之普通工厂方式
- 将class类对象转化成json的数据格式
直接上代码: JSONObject的的使用需要导入json-lib-2.4-jdk15.jar包,下载地址:http://mvnrepository.com/artifact/net.sf.json- ...
- SAS学习笔记之《SAS编程与数据挖掘商业案例》(4)DATA步循环与控制、常用全程语句、输出控制
SAS学习笔记之<SAS编程与数据挖掘商业案例>(4)DATA步循环与控制.常用全程语句.输出控制 1. 各种循环与控制 DO组 创建一个执行语句块 DO循环 根据下标变量重复执行DO和E ...
- JS高级——Function原型链
基本概念 1.函数可以通过Function new出来,那么Function可以被称作构造函数,被new出来的函数可以被称为一个对象 2.Function既然是构造函数,那么肯定也有原型,它的原型是一 ...
- js 判断 微信浏览器
<script type="text/javascript"> window.onload = function() { isWeixinBrowser(); } // ...
- 微信小程序获取二维码并把logo替换为自己的头像
$avatarUrl = 'http://cms-bucket.nosdn.127.net/2018/05/28/a1a44ffdc2d24f928c1860d4fbf54703.jpeg?image ...
- DECLARE_DYNAMIC
DECLARE_DYNAMIC(class_name) DECLARE_DYNCREATE 包含了DECLARE_DYNAMIC的功能,并且可以在运行过程中动态创建对象.如果需要动态创建类对象,需要使 ...