Origianl article

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的更多相关文章

  1. Angular杂谈系列1-如何在Angular2中使用jQuery及其插件

    jQuery,让我们对dom的操作更加便捷.由于其易用性和可扩展性,jQuer也迅速风靡全球,各种插件也是目不暇接. 我相信很多人并不能直接远离jQuery去做前端,因为它太好用了,我们以前做的东西大 ...

  2. Angular企业级开发(5)-项目框架搭建

    1.AngularJS Seed项目目录结构 AngularJS官方网站提供了一个angular-phonecat项目,另外一个就是Angular-Seed项目.所以大多数团队会基于Angular-S ...

  3. TypeScript: Angular 2 的秘密武器(译)

    本文整理自Dan Wahlin在ng-conf上的talk.原视频地址: https://www.youtube.com/watch?v=e3djIqAGqZo 开场白 开场白主要分为三部分: 感谢了 ...

  4. angular实现统一的消息服务

    后台API返回的消息怎么显示更优雅,怎么处理才更简洁?看看这个效果怎么样? 自定义指令和服务实现 自定义指令和服务实现消息自动显示在页面的顶部,3秒之后消失 1. 显示消息 这种显示消息的方式是不是有 ...

  5. div实现自适应高度的textarea,实现angular双向绑定

    相信不少同学模拟过腾讯的QQ做一个聊天应用,至少我是其中一个. 过程中我遇到的一个问题就是QQ输入框,自适应高度,最高高度为3row. 如果你也像我一样打算使用textarea,那么很抱歉,你一开始就 ...

  6. Angular企业级开发-AngularJS1.x学习路径

    博客目录 有链接的表明已经完成了,其他的正在建设中. 1.AngularJS简介 2.搭建Angular开发环境 3.Angular MVC实现 4.[Angular项目目录结构] 5.[SPA介绍] ...

  7. Angular企业级开发(4)-ngResource和REST介绍

    一.RESTful介绍 RESTful维基百科 REST(表征性状态传输,Representational State Transfer)是Roy Fielding博士在2000年他的博士论文中提出来 ...

  8. Angular企业级开发(3)-Angular MVC实现

    1.MVC介绍 Model-View-Controller 在20世纪80年代为程序语言Smalltalk发明的一种软件架构.MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并 ...

  9. Angular企业级开发(2)-搭建Angular开发环境

    1.集成开发环境 个人或团队开发AngularJS项目时,有很多JavaScript编辑器可以选择.使用优秀的集成开发环境(Integrated Development Environment)能节省 ...

随机推荐

  1. 【题解】动态逆序对 [CQOI2011] [P3157] [BZOJ3295] [P1393]

    [题解]动态逆序对 [CQOI2011] [P3157] [BZOJ3295] [P1393] 水一水QAQ 题目链接: \([P3157]\) \([BZOJ3295]\) [题目描述] 对于一个序 ...

  2. JavaScript入门二

    ******函数****** **函数定义** //普通函数定义 function f1() { console.log("Hello word!") } //带参数的函数 fun ...

  3. 【NOIP2016】DAY1 T2 天天爱跑步

    [NOIP2016]DAY1 T2 天天爱跑步 Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要玩家每天按时 ...

  4. PHP电影小爬虫(2)

    学习了别人的爬虫后自己改的一个,算是又回顾了一下php的使用 我们来利用simple_html_dom的采集数据实例,这是一个PHP的库,上手很容易.simple_html_dom 可以很好的帮助我们 ...

  5. 题解报告:hdu 1272 小希的迷宫

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1272 Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem ...

  6. 关于华为手机Log.d打印不出来log的问题

    http://blog.csdn.net/picasso_l/article/details/52489560     拨号,进入后台设置,进行操作.

  7. jquery 零碎笔记

    toggle使用 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...

  8. 在PHP中调用php_ssh实现远程登陆linux服务器并执行shell脚本。

    这个功能主要用于在web端利用程序对远程服务器进行操作,通过PHP_ssh执行shell脚本来实现. 首先要安装php_ssh2组件,linux中centos7下有ssh2源,直接安装.window下 ...

  9. element ui 日期控件范围时间限制记录、以及计算两个日期之间的天数

    日期的筛选经常会有最小的日期选择,例如:当前日期 :clearable="false" :picker-options="pickerOptions0" val ...

  10. Python os模块和time模块 day4

    一.os模块 print(os.listdir(r'/Users/smh/Desktop/整理'))#os.listdir() 列出某个目录下面的文件夹/文件 print(os.path.isfile ...