【问题标题】:How to search "next" term from a search input如何从搜索输入中搜索“下一个”字词
【发布时间】:2019-04-03 15:31:04
【问题描述】:

我正在尝试创建一个“搜索下一个”功能,在用户点击回车后,将调用一个专注于下一个匹配项的函数。棘手的部分是要搜索的文本是一个带有嵌套元素的 div 容器,所有元素都有各自的文本。我能够使用管道创建突出显示,但不确定如何导航到与搜索词匹配的下一个文本。有什么想法吗?

这里是高亮管道:

@Pipe({
    name: 'highlight'
  })
export class HighlightPipe implements PipeTransform {

transform(value: string, args: string): any {
  if (args && value) {
      value = String(value); // make sure its a string;
      const startIndex = value.toLowerCase().indexOf(args.toLowerCase());
      if (startIndex != -1) {
        console.log(startIndex);
        const endLength = args.length;
        const matchingString = value.substr(startIndex, endLength);
        return value.replace(matchingString, "<mark>" + matchingString + "</mark>");
      }

  }
  return value;
}

}

带有搜索输入和包含所有文本的 div 容器的模板:

<section *ngFor="let section of country.Section">
  <div class="main" [innerHTML]="section.Name | highlight: searchTerm"></div>
     <div *ngFor="let sectionParagraph of section.SectionParagraph">
       <p class="paragraph" [innerHTML]="sectionParagraph.ParagraphText | highlight: searchTerm"></p>
       <p class="paragraph" [innerHTML]="sectionParagraph.ChildParagraphs | highlight: searchTerm"></p>
     </div>
     <div *ngFor="let subsection of section.SubSection">
       <div class="secondary" [innerHTML]="subsection.Name | highlight: searchTerm"></div>
       <div *ngFor="let subSubsectionParagraph of subsection.SubSectionParagraph">
         <p class="paragraph" [innerHTML]="subSubsectionParagraph.ParagraphText | highlight: searchTerm"></p>
         <div *ngFor="let childParagraph of subSubsectionParagraph.ChildParagraphs">
           <p class="paragraph" [innerHTML]="childParagraph.ParagraphText | highlight: searchTerm"></p>
         </div>
       </div>
     </div>
  <hr>
</section>

和搜索输入在同一个模板上:

    <mat-form-field class="example-full-width" style="margin-left: 120px">
        <input matInput placeholder="Search Text" [value]="searchTerm" [(ngModel)]="searchTerm" (input)="highlight($event)" (keyup.enter)="nextTerm()">
    </mat-form-field>

编辑:我想避免使用任何 jQuery 作为解决方案

【问题讨论】:

    标签: javascript angular


    【解决方案1】:

    这个想法是使用带有两个参数的管道,“搜索”和“索引”,然后您需要更改管道以考虑这些变化

    transform(value: string, args: string,index:number=-1): any {
      if (args && value) {
          value = String(value); // make sure its a string;
          const startIndex = value.toLowerCase().indexOf(args.toLowerCase(),index);
          if (startIndex != -1) {
            console.log(startIndex);
            const endLength = args.length;
            const matchingString = value.substr(startIndex, endLength);
            return value.substring(0,startIndex)+"<mark>" + matchingString + "</mark>"+value.substring(startIndex+endLength);
          }
    
      }
      return value;
    }
    

    然后你调用管道就好了,我用一个

    做的,但重要的是如何传递这两个参数

    <p (click)="click()" class="paragraph" 
         [innerHTML]="text | highlight: search:index"></p>
    

    函数click()是这样的:

    //This are the variables I used in a more simple example
    
    index:number=0;
    text='Hola mundo, Hola Mundo';
    search="Hola";
    
    click()
      {
        let index=this.text.indexOf(this.search,this.index+1);
        this.index=index>0?index:0;
      }
    

    你可以在stackblitz做榜样

    更新 如果我们有一系列文本,那么我们的文本就会变成带有索引的对象

    sections = [
        { text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', index: 0 },
        { text: 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.', index: 1 },
        { text: 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', index: 2 },
        { text: 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. ', index: 3 }
      ]
    

    然后,我们的管道可以考虑“索引”

    //the .html
    <div *ngFor="let section of sections;let i=index">
     <p class="paragraph" [innerHTML]="section.text | highlight: search:index:(active==section.index)"></p>
     </div>
     <button (click)="click()">next</button>
    
    //the pipe
    //we get "active"
    transform(value: string, args: string,index:number=-1,active:boolean): any {
      //if active=false not do anything
      if (args && value && active) {
          value = String(value); // make sure its a string;
          const startIndex = value.toLowerCase().indexOf(args.toLowerCase(),index);
          if (startIndex != -1) {
            const endLength = args.length;
            const matchingString = value.substr(startIndex, endLength);
            return value.substring(0,startIndex)+"<mark>" + matchingString + "</mark>"+value.substring(startIndex+endLength);
          }
    
      }
      return value;
    }
    

    好吧,“点击”功能有点复杂

    click() {
        let index = -1;
        if (this.active < 0) {
          this.active = 0;
          index = this.sections[this.active].text.indexOf(this.search);
        }
        else {
    
          if (this.index < 0) {
            index = this.sections[this.active].text.indexOf(this.search);
            index = this.sections[this.active].text.indexOf(this.search, index + 1);
          }
          else
            index = index = this.sections[this.active].text.indexOf(this.search, this.index + 1);
        }
        if (index < 0)
        {
          let count=0;
          this.active = (this.active + 1) % this.sections.length;
          while (this.sections[this.active].text.indexOf(this.search)<0 
                  && count<this.sections.length)
          {
            this.active = (this.active + 1) % this.sections.length;
            count++;
          }
        }
        this.index = index;
      }
    

    在您的情况下,您需要计算节和小节的“索引”以使它们连续。

    new stackblitz

    【讨论】:

    • 谢谢你,但我的场景涉及一个嵌套对象,它涉及多个管道。在您的示例中,索引基于仅绑定到一个元素的文本。我有多个元素需要能够导航到下一个索引(请参阅 html 模板)
    • 在您的情况下,您可以在管道中添加一个新参数“active”(变为 true 或 false),并在 .ts 中添加一个活动变量。功能(点击)变得更加复杂。我在stackblitz.com/edit/… 中留下了一个“原样”的例子。希望对你有帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 2011-10-13
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    相关资源
    最近更新 更多