基于ng-alain开发的addFilter组件

1、效果

2、开发过程

  • 1、高级查询是有几个基础模块组成

input、select、时间、IP输入框等等

首先简单封装下这些基础组件,然后根据类型来进行绘制不同的查询项。

  • 2、基础组件提供输入后或者选中后的查询值,给高级查询。并留一个focus处理方法

import {
  Component,
  ElementRef,
  Input,
  ViewChild,
  Output,
  EventEmitter
} from '@angular/core';
import { Key as KeyBoard} from 'ts-keycode-enum';
import { AdvancedSearchValueService } from './advanced.searchValue.service';
import { AdvancedUtils } from './advanced.utils';

@Component({
  selector: 'app-input-search',
  template: `
    <nz-input-group [nzSuffix]="suffixIconSearch" 
                    [ngStyle]="width"
                    [nzAddOnBefore]="nzAddOnBefore"
                    nzSearch class="app-input-search"
                    [ngClass]="{'app-input-search-nzSuffix' : nzAddOnBefore}"
                    [nzAddOnAfter]="nzAddOnAfter">
      <input class="app-input-search-input" 
             #input (blur)="onblur($event)" (keydown)="onkeydown($event)" 
             [(ngModel)]="searchValue" type="text" nzAllowClear 
             nz-input [placeholder]="placeholder"/>
    </nz-input-group>
    <ng-template #suffixIconSearch>
      <span [ngClass]="{'span-margin' : nzAddOnBefore}">
        <div class="app-input-search-input-div" *ngIf="_searchValue">
        <i (mousedown)="onmousedown($event)" (click)="clear()" theme="fill" nz-icon type="close-circle"
           class="app-input-search-input-i app-input-search-input-del">
        </i>
      </div>
      <button (mousedown)="onmousedown($event)" (click)="_search()" nz-button nzType="primary">
        <i nz-icon type="search"></i>
      </button>
      </span>
    </ng-template>
  `,
  styleUrls: ['./advanced.searchbox.component.less'],
})
export class InputSearchComponent {
  static readonly KEY = 'app-input-search';
  constructor(
    private el: ElementRef,
    private searchValueService: AdvancedSearchValueService
  ) {
  }

  /**
   * 查询数据控制
   */
  _searchValue: any;
  get searchValue() {
    return this._searchValue;
  }

  @Input() set searchValue(val) {
    this._searchValue = val;
  }
  _width = 200;
  get width() {
    const width: any = this._width;
    return {'width': width + 'px'};
  }
  @Input() set width(_width){
    this._width = Number(_width);
  };
  @Input() searchKey: string; // 查询字段的key 有这个字段会拼成一个对象返回
  @Input() nzAddOnBefore: any;
  @Input() nzAddOnAfter: any;
  @Input() placeholder: string = '请输入查询内容';
  /**
   * search动作
   * @type {EventEmitter<number>}
   */
  @Output('search') // 对外提供接口 获取查询的值
  search: EventEmitter<number> = new EventEmitter<number>();
  @ViewChild('input') input;

  /**
   * 设置光标位置
   */
  focus() {
    this.input.nativeElement.focus();
  }

  /**
   * 获取查询项
   * @returns {any}
   */
  getValue() {
    return this._searchValue;
  }

  /**
   * 清理动作
   */
  clear() {
    this.searchValue = null;
    this.focus();
    this._search();
  }

  /**
   * 鼠标失去焦点事件
   * @param event
   */
  onblur(event) {
    this._search();
  }

  /**
   * 鼠标点击事件
   * @param event
   */
  onmousedown(event) {
    event.preventDefault();
  }

  /**
   * 查询动作
   */
  _search() {
    let searchValue: any = AdvancedUtils.getSearchValue(this.searchValue, this.searchKey);
    this.searchValueService.sendSearchValue(searchValue, this.searchKey);
    this.search.emit(searchValue);
  }

  /**
   * 键盘事件监听
   * @param ev
   */
  onkeydown(ev) {
    if (ev.which === KeyBoard.Enter) {
      this._search();
    }
  }
}
  • 3、高级查询组件拿到查询后的值,通知表格刷新

import {
  Component,
  OnInit,
  OnChanges,
  SimpleChanges,
  ViewChild,
  ElementRef,
  OnDestroy,
  Input,
  Output,
  EventEmitter,
  HostListener,
  ViewChildren, QueryList, AfterViewInit,
} from '@angular/core';

import { AppUtil } from '@core/util/util.service';
import { TimeSearchComponent } from './time.search.component';
import { InputSearchComponent } from './input.search.component';
import { SelectSearchComponent } from './select.search.component';
import { IpInputWidgetComponent } from '../input/ipInput.widget';
import { Subscription } from 'rxjs';
import { AdvancedSearchValueService } from './advanced.searchValue.service';

@Component({
  selector: 'app-advanced-searchbox',
  templateUrl: './advanced.searchbox.component.html',
  styleUrls: ['./advanced.searchbox.component.less'],
})
export class AdvancedSearchboxComponent implements OnInit, OnDestroy, AfterViewInit {
  static readonly KEY = 'app-advanced-searchbox';
  private _subscription: Subscription;
  constructor(
    private util: AppUtil,
    private searchValueService: AdvancedSearchValueService
  ) {
    this._subscription = searchValueService.Status$.subscribe((searchValue)=> {
      this._advancedSearch(searchValue);
    });
  }

  ngOnInit() {
    // items 有使用get赋值的场景 此时不直接使用 拿到items后 添加uuid 赋值给__advanceditems
    // 使用__advanceditems来进行增删改
    this.__advanceditems = this.setAdvancedItem(this.items);
    this.__allItems = this.util.cloneAllItems(this.__advanceditems);
  }

  ngOnDestroy() {
    this._subscription.unsubscribe();
  }

  ngAfterViewInit() {
    setTimeout(() => {
      this._setAAdvancedValue();
    });
  }
  /**
   * advancedSearch动作
   * @type {EventEmitter<number>}
   */
  @Output('advancedSearch') // 动态获取宽度 动态调整
  advancedSearch: EventEmitter<number> = new EventEmitter<number>();
  /**
   * 时间查询项
   */
  @ViewChildren(TimeSearchComponent) timeSearchComponents: QueryList<TimeSearchComponent>;
  /**
   * 输入框查询项
   */
  @ViewChildren(InputSearchComponent) inputSearchComponents: QueryList<InputSearchComponent>;
  /**
   * 选择框查询项
   */
  @ViewChildren(SelectSearchComponent) selectSearchComponents: QueryList<SelectSearchComponent>;
  /**
   * IP地址查询项
   */
  @ViewChildren(IpInputWidgetComponent) IPSearchComponents: QueryList<IpInputWidgetComponent>;
  /**
   * 添加过滤对象
   */
  @ViewChild('dropdown_button') dropdown_button;

  keydown(e, currentViewModel?, options: {id?: any , blackList?: any} = {}) {

  }

  /**
   * items form表单的样式
   */
  @Input('itemsStyle') itemsStyle: object;

  /**
   * 查询参数
   */
  @Input('params') set params(_params) {
    this.advancedSearchValue = _params || {};
  };

  /**
   * 缓存下来所有的条件 用于后续增加和修改
   */
  private __allItems: any[];
  @Input('items') items: any[];
  public __advanceditems: any[];
  // select 和 input 的宽度
  public _width = 160;
  /**
   * 添加uuid
   */
  private setAdvancedItem(_items) {
    const items = this.util.cloneAllItems(_items);
    if (items) {
      const len = items.length;
      for (let i = 0; i < len; i++) {
        const singleItems = items[i];
        if (!singleItems.uuid) {
          singleItems.uuid = this.util.uuid();
        }
        items[i] = singleItems;
      }
    }
    return items;
  }

  /**
   * 数据绘制完后 开始赋值
   * @private
   */
  private _setAAdvancedValue() {
    if (this.__advanceditems && !this.util.isEmptyObject(this.advancedSearchValue)) {
      const oldItems = this.util.cloneAllItems(this.__advanceditems);
      const len = oldItems.length;
      for (let i = 0; i < len; i++) {
        const keyArr = oldItems[i].searchKey.split(',');
        const keylen = keyArr.length;
        const _value = [];
        for (let j = 0; j < keylen; j++) {
          if (this.advancedSearchValue[keyArr[j]]) {
            _value.push(this.advancedSearchValue[keyArr[j]]);
          }
        }
        if (_value.length) {
          oldItems[i]._value = _value.length > 1 ? _value : _value[0];
          this.itemClick(oldItems[i], i, false);
        }
      }
    }
  }

  /**
   * 已经点击过的查询条件
   * @type {Array}
   * @private
   */
  _searchItems: any[] = [];
  get searchItems() {
    return this._searchItems;
  }
  set searchItems(item) {
    this._searchItems = item;
  }

  /**
   * 点击查询项触发的事件
   * @param item
   * @param index
   */
  itemClick(item, index, focus = true) {
    this.searchItems.push(item);
    const len = this.__advanceditems.length;
    let k = index;
    for (let i = 0; i < len; i++) {
      if (item.uuid === this.__advanceditems[i].uuid) {
        k = i;
        break;
      }
    }
    this.__advanceditems.splice(k, 1);
    // 将光标定位到选中的查询项上
    if (focus) {
      setTimeout(()=> {
        this.focusSelectSearch(item);
      }, 100);
    }
    // 隐藏高级查询项
    this.dropdown_button ? this.dropdown_button.hide() : '';
  }

  /**
   * 将关闭定位到选择的这个高级查询项上
   * @param item
   */
  focusSelectSearch(item) {
    // 根据type拿到组件对象
    const _results = this[item.type+ 'SearchComponents']['_results'];
    const len = _results.length;
    for (let i = 0; i < len; i++) {
      const component = _results[i];
      /**
       * 根据uuid进行匹配 如果匹配上 调用focus进行定位
       * 每个组件都要提供一个focus方法进行定位
       */
      if (item.uuid === component.el.nativeElement.id && this.util.isFunction(component.focus)) {
        component.focus();
      }
    }
  }

  /**
   * 鼠标点击事件
   * @param event
   */
  onmousedown(event) {
    event.preventDefault();
  }

  /**
   * 删除当前的某个条件
   * @param item
   * @param index
   */
  itemClear(obj) {
    const item = obj.items;
    const index = obj.index;
    this._searchItems.splice(index, 1);
    this.__advanceditems.push(item);
    const searchValue = {
      key: item.searchKey,
      value: {}
    };
    this._advancedSearch(searchValue);
  }

  /**
   * 重置查询项
   */
  resetItems() {
    this.__advanceditems = this.util.cloneAllItems(this.__allItems);
    this.searchItems = [];
    this.advancedSearchValue = {};
    this._advancedSearch();
  }

  /**
   * 高级查询条件处理
   * @type {{}}
   * @private
   */
  private _advancedSearchValue: any = {};
  get advancedSearchValue() {
    return this._advancedSearchValue;
  }
  set advancedSearchValue(searchValue) {
    this._advancedSearchValue = searchValue;
  }

  /**
   * 获取最终的高级查询条件
   * @param searchValue
   * @private
   */
  private _advancedSearch(searchValue: any = null) {
    /**
     * 判断是否有有查询条件 没有就将条件删除
     */
    if (searchValue) {
      if (this.util.isEmptyObject(searchValue.value)) {
        const keyArr = searchValue.key.split(',');
        const len = keyArr.length;
        /**
         * 倒循环 提高性能
         */
        for (let i = len - 1; i >= 0; i--) {
          delete this.advancedSearchValue[keyArr[i]];
        }
      }
      this.advancedSearchValue = this.util.apply({},this.advancedSearchValue, searchValue.value);
    }
    const advancedSearchValue: any = this.advancedSearchValue;
    this.advancedSearch.emit(advancedSearchValue);
  }
}
<!--添加过滤条件按钮-->
<nz-dropdown [nzTrigger]="'click'" #dropdown_button *ngIf="__advanceditems"
             class="advanced-searchbox-dropdown" [hidden]="!__advanceditems.length">
  <button class="grid-tbar grid-tbar-add"
          [ngClass]="{'grid-tbar-filter': searchItems.length}"
          nz-button nzType="primary"nz-dropdown>
    <i nz-icon type="filter" theme="outline"></i>过滤
  </button>
  <ul nz-menu [hidden]="!__advanceditems.length">
    <li nz-menu-item *ngFor="let item of __advanceditems;let j = index">
      <a (click)="itemClick(item, j)">{{item.lable}}</a>
    </li>
  </ul>
</nz-dropdown>
<button class="grid-tbar grid-tbar-clear" nzType="primary"
        (mousedown)="onmousedown($event)" nz-button
        *ngIf="searchItems.length" (click)="resetItems()"
        nz-tooltip nzTitle="重置过滤条件">
  <i nz-icon type="delete" theme="outline"></i>清空
</button>
<!--条件区域-->
<form nz-form [nzLayout]="'inline'"
      [ngClass]="{'advanced-searchbox-form': searchItems.length}"
      [ngStyle]="itemsStyle">
  <nz-form-item *ngFor="let search of searchItems;let i = index">
    <nz-form-control>
      <ng-container [ngSwitch]="search.type">
        <!--IP查询项-->
        <ng-container *ngSwitchCase="'IP'">
          <nz-input-group nzCompact>
            <app-advanced-searchbox-lable (itemClear)="itemClear($event)"
              [lable]="search.lable" [value]="{items: search, index: i}">
            </app-advanced-searchbox-lable>
            <app-ip-input class="advanced-app-ip-input-border"
                [border]="true"
                [searchValue]="search._value"
                id="{{search.uuid}}" [Prefix]="true"
                [searchKey]="search.searchKey">
            </app-ip-input>
          </nz-input-group>
        </ng-container>
        <!--事件查询项-->
        <ng-container *ngSwitchCase="'time'">
          <nz-input-group nzCompact>
            <app-advanced-searchbox-lable (itemClear)="itemClear($event)"
                                          [lable]="search.lable" [value]="{items: search, index: i}">
            </app-advanced-searchbox-lable>
            <app-time-search
                [searchValue]="search._value"
                [searchKey]="search.searchKey"
                id="{{search.uuid}}">
            </app-time-search>
          </nz-input-group>
        </ng-container>
        <!--选择框-->
        <ng-container *ngSwitchCase="'select'">
          <nz-input-group nzCompact>
            <app-advanced-searchbox-lable (itemClear)="itemClear($event)"
                  [lable]="search.lable" [value]="{items: search, index: i}">
            </app-advanced-searchbox-lable>
            <app-select-search
                [width]="_width"
                [url]="search.url"
                [selectedValue]="search._value"
                [searchKey]="search.searchKey"
                [optionList]="search.optionList"
                [lableKey]="search.lableKey"
                [valueKey]="search.valueKey"
                [APN]="search.APN"
                id="{{search.uuid}}">
            </app-select-search>
          </nz-input-group>
        </ng-container>
        <ng-container *ngSwitchDefault>
          <app-advanced-searchbox-lable (itemClear)="itemClear($event)"
              [lable]="search.lable" [value]="{items: search, index: i}">
          </app-advanced-searchbox-lable>
          <app-input-search
              [width]="_width"
              [searchValue]="search._value"
              id="{{search.uuid}}"
              [searchKey]="search.searchKey">
          </app-input-search>
        </ng-container>
      </ng-container>
    </nz-form-control>
  </nz-form-item>
</form>

3、应用

在表格中使用

<!--tags区域-->
    <nz-row class="grid-tags" *ngIf="tags">
      <ng-container *ngIf="!tags; else customizeTage"></ng-container>
    </nz-row>
    <!--tbar区域-->
    <nz-row class="grid-tbar" *ngIf="tbar || advancedItems">
      <app-input-search *ngIf="searchCapability" (search)="_search($event)" class="app-grid-input-search">
      </app-input-search>
      <ng-container *ngIf="!tbar; else customizeTbar"></ng-container>
      <app-advanced-searchbox (advancedSearch)="_advancedSearch($event)"
              [params]="advancedParams"
              [itemsStyle]="{'padding-left': '6px', 'margin-top': '12px'}"
              [items]="advancedItems">
      </app-advanced-searchbox>
    </nz-row>
    <!--自定义tags-->
    <ng-template  #customizeTage>
      <ng-template [ngTemplateOutlet]="tags"></ng-template>
    </ng-template>
    <!--自定义tbar-->
    <ng-template  #customizeTbar>
      <ng-template [ngTemplateOutlet]="tbar"></ng-template>
    </ng-template>

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值