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. easyui- comobo 详细讲解

    具体代码实现 @{    ViewBag.Title = "人员查找";    ViewBag.LeftWidth = "200px";    ViewBag. ...

  2. BZOJ 1845 Simpson积分

    思路: Simpson积分直接上  限制一下递归深度+精度就好了 (难以理解为什么这么多人写扫描线) //By SiriusRen #include <bits/stdc++.h> usi ...

  3. 【Leetcode】92. Reverse Linked List II && 206. Reverse Linked List

    The task is reversing a list in range m to n(92) or a whole list(206). All in one : U need three poi ...

  4. easyui datagrid 高度布局自适应

    最近在把以前写的一个项目改成用easyui做前端.过程中遇到了不少问题.其中一个就是datagrid不能很好的布局.想了好多办法都有局限.最后想到会不会是布局(easyui-layout)的问题,经过 ...

  5. 关于java.util.properties的随笔

    public class Propertiesextends Hashtable<Object,Object> Properties 类表示了一个持久的属性集.Properties 可保存 ...

  6. 使用XUL开发跨平台桌面应用

    先上图: 现在使用html,css,js开发桌面的优势越来越明显了,硬件性能的不断提升,人力成本越发昂贵,用户对界面要求越来越高,全球化下企业间的竞争越发激烈. 桌面软件50%+的工作量都在界面开发这 ...

  7. Android项目实战_手机安全卫士home界面

    # 安全卫士主页面# ###1.GridView控件 1.与ListView的使用方式差不多,也要使用数据适配器,通过设置android:numColumns控制显示几列 2.通过指定android: ...

  8. cms判断写法

    cms比较容易写出循环的网页内容,对于有些循环的网页内容有不同css设定,这样在写cms时需要对循环做出条件判断:{if 判断条件}输出内容{else}输出内容{/if}.通过判断可以实现图片轮播效果 ...

  9. python中struct.pack()函数和struct.unpack()函数

    python中的struct主要是用来处理C结构数据的,读入时先转换为Python的字符串类型,然后再转换为Python的结构化类型,比如元组(tuple)啥的~.一般输入的渠道来源于文件或者网络的二 ...

  10. 学习随笔-Java WebService

    webService 可以将应用程序转换成网络应用程序.是简单的可共同操作的消息收发框架. 基本的webService平台是 XML 和 HTTP. HTTP 是最常用的互联网协议: XML 是 we ...