angular2.X

Angular2 Material2 封装组件 —— 多选组件

2017-04-11  本文已影响2398人  LeeChingYin

环境:

Angular 4.0.0
Angular2 Material2 2.0.0-beta.3
node v7.4.0
npm 4.0.5

1.多选列表组件

1)定义组件

multiple.component.ts
import { Component, OnInit, HostListener, Input } from '@angular/core';


@Component({
    selector: 'multiple',
    templateUrl: 'multiple.component.html',
    styleUrls: ['_multiple.component.scss']
})

export class MultipleComponent implements OnInit {

    @Input() items: any = {};
    @Input() colsTitle: any;
    @Input() keyArray: any;
    @Input() assignFilterItem: string;

    constructor() {
    }

    public ngOnInit() {
        this.keyArray = this.keyArray.split(",");
        this.colsTitle = this.colsTitle.split(",");
    }

    // 设置全选状态
    private setSelectedAll = function() {
        // 全选
        let data = this.items;
        let count = 0;
        for (let i in data) {
            if (data[i].checked) {
                count++;
            }
        }

        if (count === data.length) {
            this.slideToggleModel = true;
        } else {
            this.slideToggleModel = false;
        }
    }

    // 选中,反选
    onToggle(item) {
        item.checked = !item.checked;

        this.setSelectedAll();
    }

    // 在已选项列表中取消选中
    cancleSelected(item) {
        item.checked = false;

        this.setSelectedAll();
    }

    // 全选
    selectAll(checked) {

        var data = this.items;

        if (checked) {
            for (var i in data) {
                data[i].checked = true;
            }
        } else {
            for (var i in data) {
                data[i].checked = false;
            }
        }
    }

}
multiple.component.html
<div class="clearfix">
    <div class="col-md-12">
        <md-input-container>
            <input mdInput placeholder="请键入筛选项..." value="" [(ngModel)]="searchText"></md-input-container>
    </div>

    <div class="col-md-12 multiple-data-list">
        <md-grid-list [cols]=colsTitle.length+1 rowHeight="35px">
            <md-grid-tile>
                <md-slide-toggle (change)="selectAll(slideToggleModel)" [(ngModel)]="slideToggleModel" [checked]="slideToggleModel">全选</md-slide-toggle>
            </md-grid-tile>
            <md-grid-tile class="text-center" *ngFor="let title of colsTitle">
                <h3>{{title}}</h3>
            </md-grid-tile>
            <div *ngFor="let item of items | searchTextFilter: [searchText, assignFilterItem]">
                <md-grid-tile>
                    <md-checkbox (change)="onToggle(item)" [checked]="item.checked"></md-checkbox>
                </md-grid-tile>
                <md-grid-tile *ngFor="let key of keyArray">{{item[key]}}</md-grid-tile>
            </div>
        </md-grid-list>
    </div>
    <div class="col-md-12">
        <h2 class="multiple-title">已选项</h2>
        <div class="multiple-selected">
            <div class="multiple-selected-item" *ngFor="let item of items">
                <md-chip *ngIf="item.checked" [selected]="item.checked"  class="chip-item" hover (click)="cancleSelected(item)">
                    <span class="chip-item-label">{{item[assignFilterItem]}}</span> <i class="icon-close-cyan selectedItem-close"></i>
                </md-chip>
            </div>
        </div>
    </div>
</div>

2)使用方法

在标签<multiple></multiple>设置相应属性

属性 描述
items 数据源
colsTitle string,列表的表头。eg. colsTitle="Title,Name"
keyArray string,列表的列项内容属性。eg. keyArray="title,name"
assignFilterItem <ol><li>string, searchText筛选的属性。<br />eg.数据源的属性为:title,name,number 假设输入searchText需要筛选的是Title,则assignFilterItem="title";</li><li>已选项展示的值,assignFilterItem="title", 即设置已选项展示的数据是title的值。</li></ol>

3)例子

multiple-example.component.html
<multiple [items]="listData" colsTitle="Title" keyArray="title" assignFilterItem="title"></multiple>
效果图:
多选列表Example

2.简单版多选列表组件

逻辑上,跟1.多选列表组件其实是类似的。就是使用上有区别。

1)定义组件

multipleSimple.component.ts
import { Component, OnInit, HostListener, Input } from '@angular/core';

@Component({
    selector: 'multipleSimple',
    templateUrl: 'multipleSimple.component.html',
    styleUrls: ['_multiple.component.scss']
})

export class MultipleSimpleComponent implements OnInit {

    public ngOnInit() { }

    @Input() items: any = {};
    @Input() assignFilterItem: string;
    slideToggleModel: boolean;

    // 设置全选状态
    private setSelectedAll = function() {
        // 全选
        let data = this.items;
        let count = 0;
        for (let i in data) {
            if (data[i].selected) {
                count++;
            }
        }

        if (count === data.length) {
            this.slideToggleModel = true;
        } else {
            this.slideToggleModel = false;
        }
    }

    // 选中,反选
    onToggle(item) {
        item.selected = !item.selected;

        this.setSelectedAll();
    }

    // 在已选项列表中取消选中
    cancleSelected(item) {
        item.selected = false;

        this.setSelectedAll();
    }
    
    // 全选
    selectAll(checked) {
        var data = this.items;

        if (checked) {
            for (var i in data) {
                data[i].selected = true;
            }
        } else {
            for (var i in data) {
                data[i].selected = false;
            }
        }
    }
}

multipleSimple.component.html
<div class="clearfix">
    <div class="col-md-12">
        <md-input-container>
            <input mdInput placeholder="请键入筛选项..." value="" [(ngModel)]="searchText"></md-input-container>
        <md-slide-toggle (change)="selectAll(slideToggleModel)" [(ngModel)]="slideToggleModel" [checked]="slideToggleModel">全选</md-slide-toggle>
    </div>

    <div class="col-md-2">
        <h3 class="multiple-title">请选择</h3>
        <md-list>
            <md-list-item *ngFor="let item of items | searchTextFilter: [searchText,assignFilterItem]">
                <md-chip-list>
                    <md-chip class="chip-item-unselect" [selected]="item.selected" (click)="onToggle(item)">{{item[assignFilterItem]}}</md-chip>
                </md-chip-list>
            </md-list-item>
        </md-list>
    </div>
    <div class="col-md-3">
        <h3 class="multiple-title">已选项</h3>
        <md-list>
            <span *ngFor="let item of items">
                <md-chip *ngIf="item.selected" [selected]="item.selected"  class="chip-item" hover (click)="cancleSelected(item)">
                    <span class="chip-item-label">{{item[assignFilterItem]}}</span> <i class="icon-close-cyan selectedItem-close"></i>
                </md-chip>
            </span>
        </md-list>
    </div>
</div>

2)使用方法

在标签<multipleSimple></multipleSimple>设置相应属性

属性 描述
items 数据源
assignFilterItem <ol><li>string, searchText筛选的属性。<br />eg.数据源的属性为:title,name,number 假设输入searchText需要筛选的是Title,则assignFilterItem="title";</li><li>列表的列项内容属性</li><li>已选项展示的值,assignFilterItem="title", 即设置已选项展示的数据是title的值。</li></ol>

3)例子

multiple-example.component.html
<multipleSimple [items]="datas" assignFilterItem="title"></multipleSimple>
效果图:
简单多选列表Example

3.多选Dialog

1)定义组件

multipleDialog.component.ts
import { Component, OnInit, Inject } from '@angular/core';
import { MdDialogRef } from '@angular/material';
import { MD_DIALOG_DATA } from '@angular/material';



@Component({
    selector: 'multiple-dialog',
    styleUrls: ['_multiple.component.scss'],
    templateUrl: 'multipleDialog.component.html'
})

export class MultipleDialogComponent implements OnInit {
    config: {};
    slideToggleModel: boolean;
    constructor(private mdDialogRef: MdDialogRef<MultipleDialogComponent>, @Inject(MD_DIALOG_DATA) data: any) {
        this.config = data;
        this.setSelectedAll();
    }

    // 设置全选状态
    private setSelectedAll = function() {
        // 全选
        let data = this.config.content;
        let count = 0;
        for (let i in data) {
            if (data[i].checked) {
                count++;
            }
        }

        if (count === data.length) {
            this.slideToggleModel = true;
        } else {
            this.slideToggleModel = false;
        }
    }
    public ngOnInit() {

    }

    // 选中,反选
    onToggle(item) {
        item.checked = !item.checked;

        this.setSelectedAll();
    }

    // 在已选项列表中取消选中
    cancleSelected(item) {
        item.checked = false;

        this.setSelectedAll();
    }

    // 全选
    selectAll(checked) {
        let data: any = this.config;
        let dataContent: any = data.content;
        console.log(dataContent);
        if (checked) {
            for (let i in dataContent) {
                dataContent[i].checked = true;
            }
        } else {
            for (let i in dataContent) {
                dataContent[i].checked = false;
            }
        }
    }
}
multipleDialog.component.html
<div md-dialog-title>
    <md-input-container>
        <input mdInput placeholder="请键入筛选项..." value="" [(ngModel)]="searchText"></md-input-container>
    <span class="icon-close-mid pull-right md-dialog-title-close" (click)="mdDialogRef.close()"></span>
</div>
<div md-dialog-content class="multiple-dialog-contentContainer">
    <div class="col-md-12 multiple-data-list">
        <md-grid-list [cols]=config.colsTitle.length+1 rowHeight="35px">
            <md-grid-tile>
                <md-slide-toggle (change)="selectAll(slideToggleModel)" [(ngModel)]="slideToggleModel" [checked]="slideToggleModel">全选</md-slide-toggle>
            </md-grid-tile>
            <md-grid-tile class="text-center" *ngFor="let title of config.colsTitle">{{title}}</md-grid-tile>
            <div *ngFor="let item of config.content | searchTextFilter: [searchText, config.assignFilterItem]">
                <md-grid-tile>
                    <md-checkbox (change)="onToggle(item)" [checked]="item.checked"></md-checkbox>
                </md-grid-tile>
                <md-grid-tile *ngFor="let key of config.keyArrayName">{{item[key]}}</md-grid-tile>
            </div>
        </md-grid-list>
    </div>
    <div class="col-md-12">
        <h2 class="multiple-title">已选项</h2>
        <div class="multiple-selected">
            <div class="multiple-selected-item" *ngFor="let item of config.content">
                <md-chip *ngIf="item.checked" [selected]="item.checked"  class="chip-item" hover (click)="cancleSelected(item)">
                    <span class="chip-item-label">{{item[config.assignFilterItem]}}</span> <i class="icon-close-cyan selectedItem-close"></i>
                </md-chip>
            </div>
        </div>
    </div>

</div>
<div md-dialog-actions class="multiple-dialog-actionsContainer">
    <md-slide-toggle (change)="selectAll(slideToggleModel)" [(ngModel)]="slideToggleModel" [checked]="slideToggleModel">全选</md-slide-toggle>
    <div class="multiple-dialog-operate">
        <button md-raised-button color="primary" (click)="mdDialogRef.close()">确定</button>
        <button md-raised-button md-dialog-close class="multiple-dialog-cancel">取消</button>
    </div>
</div>

2)把组件注入到服务

为了通用,把组件注入服务,方便在其他地方使用。这样的话,就不用在每次使用的时候重新定义组件。

multipleDialog.service.ts
import { Component, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
import { MdDialog, MdDialogRef, MdDialogConfig } from '@angular/material';
import { MultipleDialogComponent } from './multipleDialog.component';
import { Observable } from 'rxjs/Observable';


export class MultipleDialogService {
    constructor( @Inject(MdDialog) public _multipleDialog: MdDialog, @Inject(DOCUMENT) doc: any) {
        _multipleDialog.afterOpen.subscribe((ref: MdDialogRef<any>) => {
            if (!doc.body.classList.contains('no-scroll')) {
                doc.body.classList.add('no-scroll');
            }
        });
        _multipleDialog.afterAllClosed.subscribe(() => {
            doc.body.classList.remove('no-scroll');
        });


    }

    public setMultipleData(contentOrConfig: any, title?: string): Observable<any> {
        let config = new MdDialogConfig();
        config = {
            width: '700px'
        };
        if (contentOrConfig instanceof Object) {
            config.data = contentOrConfig;
        } else if ((typeof contentOrConfig) === 'string') {
            config.data = {
                content: contentOrConfig,
                title: title
            }
        }
        return this._multipleDialog.open(MultipleDialogComponent, config).afterClosed();
    }
}

3)使用方法

属性 描述
arg1 Array,列表的表头。eg. ['Title']
arg2 Array,列表的列项内容的属性。eg. ['title']
arg3 <ol><li>string, searchText筛选的属性。<br />eg.数据源的属性为:title,name,number 假设输入searchText需要筛选的是Title,则assignFilterItem="title";</li><li>已选项展示的值,即设置已选项展示的数据是title的值。</li></ol>

4)例子

multiple-example.component.html
<button md-raised-button (click)="openDialog(['Title'], ['title'],'title')">Open dialog</button>
multiple-example.component.ts
import { Component, OnInit, HostListener } from '@angular/core';
import { MultipleDialogService } from './multipleDialog.service';

@Component({
    selector: 'multipleExample',
    templateUrl: 'multiple-example.component.html',
    styleUrls: ['multiple-example.component.css'],
    providers: [MultipleDialogService]
})

export class MultipleExampleComponent implements OnInit {

    public constructor(public _multipleDialogService: MultipleDialogService) { }
    public ngOnInit() { }

    listData = [{ title: '森美', name: '1' }, { title: '小仪' }, { title: '西瓜' }, { title: '阿杰' }];

    // 多选框
    public openDialog(titleArray, keyArray, assignFilterItemName) {
        this._multipleDialogService.setMultipleData({ content: this.listData, colsTitle: titleArray, keyArrayName: keyArray, assignFilterItem: assignFilterItemName }).subscribe(res => {

            // 返回结果
            let selectedArr = [];
            let data: any = this.listData;
            for (let i in data) {
                if (data[i].checked) {
                    selectedArr.push(data[i]);
                }
            }

        });
    }
}
效果图:
多选Dialog Example

4.简单多选Dialog

逻辑上,跟3.多选Dialog组件其实是类似的。只是简单版

1)定义组件

multipleSimpleDialog..component.ts
import { Component, OnInit, Inject } from '@angular/core';
import { MdDialogRef } from '@angular/material';
import { MD_DIALOG_DATA } from '@angular/material';


@Component({
    selector: 'multiple-dialog',
    styleUrls: ['_multiple.component.scss'],
    templateUrl: 'multipleSimpleDialog.component.html'
})

export class MultipleSimpleDialogComponent implements OnInit {
    config: {};
    slideToggleModel: boolean;
    constructor(private mdDialogRef: MdDialogRef<MultipleSimpleDialogComponent>, @Inject(MD_DIALOG_DATA) data: any) {
        this.config = data;
        this.setSelectedAll();
    }

    // 设置全选状态
    private setSelectedAll = function() {
        // 全选
        let data = this.config.content;
        let count = 0;
        for (let i in data) {
            if (data[i].selected) {
                count++;
            }
        }

        if (count === data.length) {
            this.slideToggleModel = true;
        } else {
            this.slideToggleModel = false;
        }
    }
    public ngOnInit() {

    }

    // 选中,反选
    onToggle(item) {
        item.selected = !item.selected;

        this.setSelectedAll();
    }

    // 在已选项列表中取消选中
    cancleSelected(item) {
        item.selected = false;

        this.setSelectedAll();
    }

    // 全选
    selectAll(checked) {
        let data: any = this.config;
        let dataContent: any = data.content;

        if (checked) {
            for (let i in dataContent) {
                dataContent[i].selected = true;
            }
        } else {
            for (let i in dataContent) {
                dataContent[i].selected = false;
            }
        }
    }
}
multipleSimpleDialog.component.html
<div md-dialog-title>
    <md-input-container>
        <input mdInput placeholder="请键入筛选项..." value="" [(ngModel)]="searchText"></md-input-container>
    <span class="icon-close-mid pull-right md-dialog-title-close" (click)="mdDialogRef.close()"></span>
</div>
<div md-dialog-content class="multiple-dialog-contentContainer">
    <div class="col-md-6">
        <h3 class="multiple-title">请选择</h3>
        <md-list>
            <md-list-item *ngFor="let item of config.content | searchTextFilter: [searchText,config.assignFilterItem]">
                <md-chip-list>
                    <md-chip class="chip-item-unselect" [selected]="item.selected" (click)="onToggle(item)">{{item[config.assignFilterItem]}}</md-chip>
                </md-chip-list>
            </md-list-item>
        </md-list>
    </div>
    <div class="col-md-6">
        <h3 class="multiple-title">已选项</h3>
        <md-list>
            <span *ngFor="let item of config.content">
                <md-chip *ngIf="item.selected" [selected]="item.selected"  class="chip-item" hover (click)="cancleSelected(item)">
                    <span class="chip-item-label">{{item[config.assignFilterItem]}}</span> <i class="icon-close-cyan selectedItem-close" (click)="cancleSelected(item)"></i>
                </md-chip>
            </span>
        </md-list>
    </div>
</div>
<div md-dialog-actions class="multiple-dialog-actionsContainer">
    <md-slide-toggle (change)="selectAll(slideToggleModel)" [(ngModel)]="slideToggleModel" [checked]="slideToggleModel">全选</md-slide-toggle>
    <div class="multiple-dialog-operate">
        <button md-raised-button color="primary" (click)="mdDialogRef.close()">{{ config.button || '确定' }}</button>
        <button md-raised-button md-dialog-close class="multiple-dialog-cancel">取消</button>
    </div>
</div>

2)把组件注入到服务

为了通用,把组件注入服务,方便在其他地方使用。这样的话,就不用在每次使用的时候重新定义组件。

multipleSimpleDialog.service.ts
import { Component, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
import { MdDialog, MdDialogRef, MdDialogConfig } from '@angular/material';
import { MultipleSimpleDialogComponent } from './multipleSimpleDialog.component';
import { Observable } from 'rxjs/Observable';


export class MultipleSimpleDialogService {
    constructor( @Inject(MdDialog) public _multipleDialog: MdDialog, @Inject(DOCUMENT) doc: any) {
        _multipleDialog.afterOpen.subscribe((ref: MdDialogRef<any>) => {
            if (!doc.body.classList.contains('no-scroll')) {
                doc.body.classList.add('no-scroll');
            }
        });
        _multipleDialog.afterAllClosed.subscribe(() => {
            doc.body.classList.remove('no-scroll');
        });
    }

    public setMultipleData(contentOrConfig: any, title?: string): Observable<any> {
        let config = new MdDialogConfig();
        config = {
            width: '700px'
        };
        if (contentOrConfig instanceof Object) {
            config.data = contentOrConfig;
        } else if ((typeof contentOrConfig) === 'string') {
            config.data = {
                content: contentOrConfig,
                title: title
            }
        }
        return this._multipleDialog.open(MultipleSimpleDialogComponent, config).afterClosed();
    }
}

3)使用方法

属性 描述
arg1 <ol><li>string, searchText筛选的属性。<br />eg.数据源的属性为:title,name,number 假设输入searchText需要筛选的是Title,则assignFilterItem="title";</li><li>列表的内容</li><li>已选项展示的值,即设置已选项展示的数据是title的值。</li></ol>

4)例子

multiple-example.component.html
<button md-raised-button (click)="openSimpleDialog('title')">Open Simple dialog</button>
multiple-example.component.ts
import { Component, OnInit, HostListener } from '@angular/core';
import { MultipleSimpleDialogService } from './multipleSimpleDialog.service';

@Component({
    selector: 'multipleExample',
    templateUrl: 'multiple-example.component.html',
    styleUrls: ['multiple-example.component.css'],
    providers: [MultipleSimpleDialogService]
})

export class MultipleExampleComponent implements OnInit {

    public constructor(public _multipleSimpleDialogService: MultipleSimpleDialogService) { }
    public ngOnInit() { }

    datas = [{ title: '你', name: '1' }, { title: 'Banana' }, { title: 'Cat' }, { title: 'Dog', name: '1' }, { title: 'Egg' }, { title: 'Food' }, { title: 'Girl', name: '1' }, { title: 'Hello' }, { title: 'In' }];

    // 简单多选框
    public openSimpleDialog(assignFilterItemName) {
        this._multipleSimpleDialogService.setMultipleData({ content: this.datas, assignFilterItem: assignFilterItemName }).subscribe(res => {

            // 返回结果
            let selectedArr = [];
            let data: any = this.datas;
            for (let i in data) {
                if (data[i].selected) {
                    selectedArr.push(data[i]);
                }
            }

            // console.log(selectedArr);

        });
    }

效果图:
简单多选Dialog Example

详细的源码,请看!

上一篇 下一篇

猜你喜欢

热点阅读