angular8 搜索组件封装

效果

使用方法

html

<app-search-bar #searchBar [searchInfo]="searchList" (returnFilter)="getFilters($event)"></app-search-bar>

ts

// 初始化数据模型
searchList: Array<SearchBarInfo>;

// constructor内赋值,optionList可以从接口获取之后重新在赋值(防止下拉框没数据)
this.searchList = [
            {
                type: 'select',
                placeHolder: '请选择',
                ngModalValue: 'enabled',
                labelName: '商品状态',
                defaultValue: 1,
                optionList: [
                    { label: '全部商品', value: '' },
                    { label: '已停用商品', value: 0 },
                    { label: '已启用商品', value: 1 },
                ]
            },
            {
                type: 'select',
                placeHolder: '请选择',
                ngModalValue: 'categoryCode',
                labelName: '商品分类',
                optionList: this.categoryList,
                optionLabel: 'name',
                optionValue: 'code'
            },
            {
                type: 'input',
                placeHolder: '商品名称/拼音简称/编号',
                ngModalValue: 'keyword',
                labelName: '',
            },
            {
                type: 'checkbox',
                ngModalValue: 'isSeasonalDishes',
                labelName: '时价菜',
            },
]

/* filter为返回选择值的数据,可以直接赋值给当前的搜索对象,也可以单独赋值 */
getFilters(filters) {
        this.filters = JSON.parse(JSON.stringify(filters));
        this.getDataList();
    }

组件代码

search-bar.component.html

<div class="search-bar">
    <ng-container *ngFor="let item of searchInfo;let i = index">

        <div class="operate-item" *ngIf="item.type === 'input' && !item.hide">
            <span *ngIf="item.labelName">{{item.labelName}}:</span>
            <input type="text" nz-input [placeholder]="item.placeHolder || '请输入'" [disabled]="item.disabled"
                [(ngModel)]="item[item.ngModalValue]" />
        </div>

        <div class="operate-item" *ngIf="item.type === 'select' && !item.hide">
            <span *ngIf="item.labelName">{{item.labelName}}:</span>
            <nz-select nzShowSearch nzAllowClear [nzPlaceHolder]="item.placeHolder || '请选择'"
                [nzDisabled]="item.disabled" [(ngModel)]="item[item.ngModalValue]">
                <nz-option [nzLabel]="options[item.optionLabel] || options.label"
                    [nzValue]="options[item.optionValue] || options.value" *ngFor="let options of item.optionList">
                </nz-option>
            </nz-select>
        </div>

        <div class="operate-item" *ngIf="item.type === 'dateRange' && !item.hide">
            <span *ngIf="item.labelName">{{item.labelName}}:</span>
            <app-range-date-time [hiddenBtn]="true" [initialValue]="false" [(startDate)]="item[item.beginTime]"
                [(endDate)]="item[item.endTime]">
            </app-range-date-time>
        </div>

        <div class="operate-item" *ngIf="item.type === 'datePicker' && !item.hide">
            <span *ngIf="item.labelName">{{item.labelName}}:</span>
            <nz-date-picker [(ngModel)]="item[item.ngModalValue]" (ngModelChange)="onChange($event)"></nz-date-picker>
        </div>

        <div class="operate-item cant-selected" *ngIf="item.type === 'checkbox' && !item.hide">
            <label nz-checkbox [(ngModel)]="item[item.ngModalValue]" [nzDisabled]="item.disabled">
                {{item.labelName}}
            </label>
        </div>
    </ng-container>

    <div class="btn-groups">
        <button (click)="searchByFilter()" nz-button nzType="primary">
            <i class="iconfont fxsousuo"></i>
            搜索</button>
        <button (click)="resetFilters()" nz-button>
            <i class="iconfont fxreset"></i>
            清空
        </button>
    </div>
</div>

search-bar.component.less

.search-bar {
    box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.2);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    border-radius: 2px;
    padding: 10px 0 0 0;

    .operate-item {
        margin: 0 10px;
        display: flex;
        margin-bottom: 10px;

        .ant-input,
        .ant-picker {
            width: 200px;
            height: 34px;
        }

        nz-select {
            width: 200px;
            height: 34px;
        }

        span {
            min-width: 80px;
            padding: 7px 0;
            white-space: nowrap;
            text-align: right;
            margin-left: auto;
            font-size: 12px;
            margin-right: 10px;
        }
    }

    .cant-selected {
        user-select: none;
    }

    .btn-groups {
        flex: 1;
        text-align: right;
        min-width: 150px;
        margin-bottom: 10px;

        .ant-btn {
            margin-right: 15px;
        }
    }
}

search-bar.component.ts

import { Component, ComponentRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { SearchBarInfo } from '@app/core/models/common-model';

@Component({
    selector: 'app-search-bar',
    templateUrl: './search-bar.component.html',
    styleUrls: ['./search-bar.component.less']
})
export class SearchBarComponent implements OnInit {
    @Input() notRefreshAfterReset: boolean;             // 重置之后是否刷新 传ture过来则不刷新
    @Input() searchInfo: Array<SearchBarInfo>;          // 传过来的搜索项
    @Output() returnFilter = new EventEmitter<any>();   // 返回搜索对象 filters

    filters: {};
    defaultBeginTime: Date;
    defaultEndTime: Date;

    constructor() {
        this.filters = {};
        this.defaultBeginTime = null;
        this.defaultEndTime = null;
    }

    onChange(e) {
        console.log(e);
    }

    searchByFilter() {
        const tempFilters = {};
        this.searchInfo.map(item => {
            if (item.type !== 'dateRange') {
                if (item[item.ngModalValue] !== undefined && item[item.ngModalValue] !== null) {
                    tempFilters[item.ngModalValue] = item[item.ngModalValue];
                }
            } else {
                if (!item.beginTime) {
                    console.warn('请设置时间开始默认值');
                    return;
                }
                if (item[item.beginTime] !== undefined && item[item.beginTime] !== null) {
                    tempFilters[item.beginTime] = item[item.beginTime];
                }
                if (!item.endTime) {
                    console.warn('请设置时间结束默认值');
                    return;
                }
                if (item[item.endTime] !== undefined && item[item.endTime] !== null) {
                    tempFilters[item.endTime] = item[item.endTime];
                }
            }
        });
        this.returnFilter.emit(tempFilters);
    }

    resetFilters() {
        this.searchInfo.map(item => {
            // TODO: clearable 基本是undefined,但是传进来的值不可预估(尽管有类型限制,但是万一有傻逼),
            // 所以只要clearable传了fasle进来,则认为是不可清除,其他均可清除
            if (item.clearable !== false) {
                item[item.ngModalValue] = undefined;
            }
        });
        if (!this.notRefreshAfterReset) {
            this.returnFilter.emit({});
        }
    }

    ngOnInit() {
        this.searchInfo.map((item, index) => {
            // 设置搜索栏的默认值
            if (item.defaultValue !== undefined && item.defaultValue !== null) {
                item[item.ngModalValue] = item.defaultValue;
            }
        });
    }

}

Interface


export interface SearchBarInfo {
    hide?: boolean;                            // 搜索条件显示隐藏
    type: string;                              // 搜索框类型(input/select/...)
    ngModalValue?: string;                     // 输入框对应的ngmodal值
    labelName?: string;                        // 搜索框label,不填则不展示
    placeHolder?: string;                      // placeHolder
    defaultValue?: string | number | boolean;  // 输入框默认值
    optionList?: Array<any>;                   // Array<{ label: string; value: string | number | boolean }>
    optionLabel?: string;                      // 不写则默认为 label
    optionValue?: string;                      // 不写则默认为 value
    beginTime?: string;                        // type为dateRange 时间范围时的控件对应的初始值
    endTime?: string;                          // type为dateRange 时间范围时的控件对应的结束值
    disabled?: boolean;                        // 是否设为不可选中状态
    clearable?: boolean;                       // 是否可清除 默认可清楚,传入false则不可清除
}

app-range-date-time 是自己根据业务进一步封装的时间选择控件,可以直接删除这个一项

posted @ 2021-06-08 15:12  可乐雪碧芬达  阅读(275)  评论(0编辑  收藏  举报