程序小屋

记录生活中的点滴,分享、学习、创新

文章内容 1623902336

在Angular中实现一个级联效果的下拉框的示例代码

实现一个具有级联效果的下拉搜索框,实现的结果如下图所示

我们主要通过这个组件,来学习一些细微的逻辑,比如: 如何计算input框内文字的长度; 如何获取光标的位置;如何实现滚动条随着上下键盘的按动进行移动......

具体需求如下

  1. 级联搜索最多不超过三级,以”.“作为级联搜索的连接符
  2. 搜索框跟着文本框中的”.“进行向后移动,向右移动的最大距离不能超过文本框的宽度
  3. 当用户修改之前的级联内容,则不进行搜索,并隐藏搜索框;若用户在之前输入的是”.“, 则将此”.“之后的内容全部删除并搜索当前的相关内容

接下来我们根据需求,来写我们的逻辑

首先我们搭建html页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<input
 #targetInput
 autocomplete="off"
 nz-input
 [(ngModel)]="searchValue"
 (keydown)="handlePress($event)"
 (input)="handleSearchList()"/>
 
<div #searchList class="search-popup" [hidden]="!visible" (keyDown)="onKeydown($event)">
  <nz-spin [nzSpinning]="searchLoading" [class.spinning-height]="searchLoading">
   <div class="data-box" *ngIf="searchData && searchData.length !== 0">
    <ul>
    // 这里在上篇文章中已经讲解过,如何实现让匹配的文字高亮显示~
     <li
      id="item"
      *ngFor="let item of searchData;let i = index;"
      [class.item-selected]="curIndex === i"
      (mouseover)='hoverDataItem(i)'
      (click)="onSelectClick(item)">
      <span [innerHTML]="item | highlightSearchResult:searchValue | safe: 'html'"></span>
     </li>
    </ul>
   </div>
  </nz-spin>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
.search-popup {
 height: 376px;
 width: 246px;
 overflow-y: auto;
 box-shadow: 0 2px 8px rgba(0,0,0,.15);
 border-radius: 4px;
 position: absolute;
 background-color: #fff;
 z-index: 999;
 top: 92px;
 right: 61px;
 
 .data-box {
  margin: 0 10px;
 
  &:not(:last-child) {
   border-bottom: 1px solid #E4E5E7;
  }
 
  .no-search-data {
   display: inline-block;
   width: 100%;
   text-align: center;
   color: #C3C9D3;
   line-height: 40px;
  }
 }
 
 & ul {
  margin: 0 -10px;
  margin-bottom: 0;
  text-align: left;
 }
 
 & li {
  padding: 3px 10px;
  position: relative;
  list-style: none;
  height: 32px;
  line-height: 26px;
  &:hover {
   cursor: pointer;
   background-color: #e6f7ff;
  }
  &.item-selected {
   background-color: #E6F7FF;
  }
 }
 
 &.item-selected {
  background-color: #E6F7FF;
 
 }
 
.hidden-box {
 display: inline-block;
 border: 1px solid #ddd;
 visibility: hidden;
}

实现相关的逻辑

根据前两个需求,我们需要根据文本框中的”.“进行向后移动,向右移动的最大距离不能超过文本框的宽度。

思路: 我们需要将文本框中的字符串根据”.“来转换成数组,并且要想办法获取文本框中文字的长度。如何获取文本框中文字的长度呢?我们可以将文字的内容,重新放到一个display: inline-block的div容器中,然后获取容器的宽度,如下代码所示~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// html
 <!-- 用于测量input框的文字宽度 -->
 
*