Allow the base toggle to be a tag (<toggle>) or attribute (<div toggle>). The <toggle> component has become less opinionated about the view, but has now taken on some responsibilities managing state. We’ll decouple the state management piece by moving it into the toggleProvider directive. The toggleProvider directive provides state for all the <toggle-off>, <toggle-on> and <toggle-button> components inside it.

For toggle component we made in previous post.

@Component({
selector: 'toggle',
template: '<ng-content></ng-content>',
})

As you can see, it use 'ng-content' inside template which means that it doesn't actually needs a template, we can consider ToggleComponent as a directive.

So we can modifiy ToggleComponet to ToggleDirective:

import { Directive, Input, Output, EventEmitter } from '@angular/core';

@Directive({
selector: 'toggle, [toggle]'
})
export class ToggleDirective {
@Input() on: boolean;
@Output() toggle: EventEmitter<boolean> = new EventEmitter(); setOnState(on: boolean) {
this.on = on;
this.toggle.emit(this.on);
}
}

So we can change the usage in app.component.html:

<div toggle (toggle)="onToggle($event)">
<toggle-on>On</toggle-on>
<toggle-off>Off</toggle-off>
<toggle-off>Off</toggle-off>
<other-component></other-component>
<toggle-button></toggle-button>
</div>

Then change all the dependencies injection for toggle-on/off/button component, the application should still works.

One problem for the current directive implementations is that each toggle directives are isolated:

Most of times, isolated directives are OK, but in some cases, if you want to share the state between two or more directives. You have to do some extra works.

Write ToggleProviderDirective for reference ToggleDirective.

state <-- ToggleDirective <-- ToggleProviderDirective

So ToggleDirective is managing the state, if we want to share the state, we create ToggleProviderDirective, it takes ToggleDirective as input, so that we can share one ToggleDirective thoughts multi directives.

import { Directive, Input, Output, Host, OnChanges, SimpleChanges, Optional } from '@angular/core';
import {ToggleDirective} from './toggle.directive'; @Directive({
exportAs: 'toggleProvider',
selector: 'toggle, [toggle], [toggleProvider]',
})
export class ToggleProviderDirective implements OnChanges { @Input() toggleProvider: ToggleDirective; toggle: ToggleDirective = this.toggleDirective; constructor(
// Reference the toggle directive on the same host element
@Host() @Optional() private toggleDirective: ToggleDirective
) { } ngOnChanges(changes: SimpleChanges) {
const {toggleProvider} = changes;
if (toggleProvider) {
this.toggle = this.toggleProvider || this.toggleDirective;
}
}
}

Also need to change the reference for toggle-on/off/button:

import { Component } from '@angular/core';

import { ToggleProviderDirective } from './toggle.toggleProvider.directive';

@Component({
selector: 'toggle-button',
template: '<switch [on]="toggleProvider.toggle.on" (click)="onClick()" ></switch>',
})
export class ToggleButtonComponent {
constructor(public toggleProvider: ToggleProviderDirective) {} onClick() {
this.toggleProvider.toggle.setOnState(!this.toggleProvider.toggle.on);
}
}

[Angular] Refactor Angular Component State Logic into Directives的更多相关文章

  1. Exploring the Angular 1.5 .component() method

    Angular 1.5 introduced the .component() helper method, which is much simpler than the.directive() de ...

  2. [Angular 2] Exposing component properties to the template

    Showing you how you can expose properties on your Controller to access them using #refs inside of yo ...

  3. [React] Update Component State in React With Ramda Lenses

    In this lesson, we'll refactor a React component to use Ramda lenses to update our component state. ...

  4. [Angular] Use Angular components in AngularJS applications with Angular Elements

    When migrating AngularJS (v1.x) applications to Angular you have different options. Using Angular El ...

  5. angular 2 angular quick start Could not find HammerJS

    Angular2 的material中 引用了 hammerjs,遇到Could not find HammerJS错误,正确的步骤如下: 需要在如下位置增加 对material 和 hammerjs ...

  6. ASP.NET Core 2.1 Web API + Identity Server 4 + Angular 6 + Angular Material 实战小项目视频

    视频简介 ASP.NET Core Web API + Angular 6的教学视频 我是后端开发人员, 前端的Angular部分讲的比较差一些, 可以直接看代码!!!! 这是一个小项目的实战视频, ...

  7. React 手稿 - Component state

    Component state 实例: import React, { PureComponent } from 'react'; export default class extends PureC ...

  8. [Angular] Expose Angular Component Logic Using State Reducers

    A component author has no way of knowing which state changes a consumer will want to override, but s ...

  9. Angular(二) - 组件Component

    1. 组件Component示例 2. Component常用的几个选项 3. Component全部的选项 3.1 继承自@Directive装饰器的选项 3.2 @Component自己特有的选项 ...

随机推荐

  1. django 数据库的一些操作

    1.数据过滤: 使用filter()方法 >>> Publisher.objects.filter(name='Apress') [<Publisher: Apress> ...

  2. Spring自动注入的几种方式

    ---恢复内容开始---   @Service("accountEmailService")public class AccountEmailServiceImpl impleme ...

  3. js检测对象是否是数组

    js检测对象是否是数组 可以通过instanceof 方法一. var arr=[] arr instanceof Array   //true var obj={} obj instanceof A ...

  4. L2-2 社交集群 (25 分)(一个写挫的并查集)

    题目: 思路: 就是一个并查集的裸题,不过在数据查找方面可能不好处理,暴力完全可以解决这个问题啊!! #include <bits/stdc++.h> #include <cstdi ...

  5. LeetCode(69) Sqrt(x)

    题目 Total Accepted: 67411 Total Submissions: 286086 Difficulty: Medium Implement int sqrt(int x). Com ...

  6. python基础——2(基本数据类型及运算符)

    目录 为何数据要区分类型? 一.数字类型 1.整型int 2.浮点型float 二.字符串str 三.列表类型list 四.字典类型 五.布尔类型 运算符的介绍 一.算术运算符 二.比较运算符 三.赋 ...

  7. Vue如何在webpack设置代理解决跨域问题

            在开发过程中我们请求数据有时候调用的是第三方接口,此时便会遇到一个问题:跨域限制.对于跨域问题的解释就不详细叙述了,要了解的请自行百度.一般跨域问题控制台会报这个错:         ...

  8. idea 设置系列 各种乱码

    http://blog.csdn.net/u013361445/article/details/51113692 把idea设置的好,才能用的好.

  9. JSP表达式语言(EL)

    JSP表达式语言(EL)使得访问存储在JavaBean中的数据变得非常简单.JSP  EL既可以用来创建算术表达式也可以用来创建逻辑表达式.在JSP  EL表达式内可以使用整数型.浮点型.字符串.常量 ...

  10. AI学习笔记(02)

    AI学习笔记   第一个黑箭头是用于挑选物体和移 动物体.在绘图是选中一个物体,就可以将它自由的移动.和其他的绘图软件相同当你选 中物体的时候物体周围就会出现八个方形的控制点,你可以通过这些控制点对物 ...