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. 337 House Robber III 打家劫舍 III

    小偷又发现一个新的可行窃的地点. 这个地区只有一个入口,称为“根”. 除了根部之外,每栋房子有且只有一个父房子. 一番侦察之后,聪明的小偷意识到“这个地方的所有房屋形成了一棵二叉树”. 如果两个直接相 ...

  2. 关于学习C语言

    c语言作为一种计算机的语言,我们学习它,有助于我们更好的了解计算机,与计算机进行交流,因此,c语言的学习对我们尤其重要. 在这个星期里,我们专业的学生在专业老师的带领下进行了c语言程序实践学习.在这之 ...

  3. 研磨JavaScript系列(一):回归简单

    想要理解JavaScript,你得首先放下对象和类的概念,回到数据和代码的本原.编程世界只有数据和代码两种基本元素,而这两种元素又有着纠缠不清的关系.JavaScript就是把数据和代码都简化到最原始 ...

  4. 【转】Java 集合系列12之 TreeMap详细介绍(源码解析)和使用示例

    概要 这一章,我们对TreeMap进行学习.我们先对TreeMap有个整体认识,然后再学习它的源码,最后再通过实例来学会使用TreeMap.内容包括:第1部分 TreeMap介绍第2部分 TreeMa ...

  5. Android java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@412d7230

    近期遇到了如标题这种错误,再次记录解决方法.本文參考帖子: http://bbs.csdn.net/topics/390196217 出现此bug的原因是在内存回收上.里面用Bitamp的代码为: t ...

  6. 精美对UI设计界面赏析

    最美的UI设计界面赏析 . 喜欢就关注我吧

  7. VC窗口类的销毁-是否需要delete

    Windows窗口如果使用new的方法添加之后,在父窗口析构的时候,有些需要delete有些却不需要delete.这个的确有点坑,由于c++的实现,对于每个自己new的对象,我都会delete删除它, ...

  8. Python标准库sys

    1.命令行参数sys.argv 我们从Python语言之模块第一部分的例子开始,看看sys.argv中到底存了些什么内容. #Filename: using_sys.py import sys i=0 ...

  9. 12--c完数/最大公约数/最小公倍数/素数/回文数

    完数/最大公约数/最小公倍数/素数/回文数 2015-04-08 10:33 296人阅读 评论(0) 收藏 举报  分类: C/C++(60)  哈尔滨工业大学(8)  版权声明:本文为博主原创文章 ...

  10. js 不能用关键字 delete 做函数名

    把delete更改为mydelete正常.