0

I am building the below drop-down component using Angular-2.

My dropdown has autocomplete as well and it works well as of now. My problem is with the CSS. The requirement is that when the user types in the characters, they should appear greyed out and all the characters printed should appear greyed out in the autocomplete options suggestions as well.

In this image, as the user types opt, the characters are greyed out and all the autocomplete options listed also have opt greyed out. I am not sure how to implement this. My code: Plunker:https://plnkr.co/edit/13RV3khyFt56eVkuw8ww?p=preview

HTML:

  <input #input type="text" [(ngModel)]="query" (keyup)="filter($event)">
  <button  (click)="showAll(input)">
    <span class="tn icon-icon_Dropdown_Arrow tn-dropdown-icon"></span>
    <i aria-hidden="true"></i>
  </button>

  <ul id="list-group" *ngIf="filteredList.length > 0">
      <li *ngFor="let item of filteredList" [id]="item.selected" [class.selected]="item.selected" (click)="select(item)">
        {{ item.option}}
      </li>
  </ul>
  <div *ngIf="queryError">{{errorMsg}}</div>

Code for filtering (relevant parts):

filterQuery() {
     this.filteredList = this.items.filter((el: any) => {
       //return el.option.toLowerCase().substr(0,this.query.length) === this.query.toLowerCase();

   return el.option.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
 });

 if(this.query.length>1){
   if(!this.filteredList.length){
     this.queryError =true;
     //console.log("Query length",this.query.length);
   }
   else{
      this.queryError =false;
   }
 }
 else{
   this.queryError =false;
 }

}

filter(event: any) {

 if (this.query !== '') {
   if (this.opened) {
     if ((event.keyCode >= 48 && event.keyCode <= 57) ||
       (event.keyCode >= 65 && event.keyCode <= 90) ||
       (event.keyCode == 8)) {

       this.pos = 0;
       this.filterQuery();

     } else if (event.keyCode != 38 && event.keyCode != 40 && event.keyCode != 13) {
       this.filteredList = this.items;

     }
   } else {
     this.filterQuery();

   }
 } else {
   if (this.opened) {
     this.filteredList = this.items;

   } else {
     this.filteredList = [];
   }
 }

 for (let i = 0; i < this.filteredList.length; i++) {
   this.filteredList[i].selected = false;
 }

 if (this.selectedItem) {
   this.filteredList.map((i) => {
     if (i.id == this.selectedItem.id) {
       this.pos = this.filteredList.indexOf(i);
     }
   })
   this.selectedItem = null;
 }

 // Arrow-key Down
 if (event.keyCode == 40) {
   if (this.pos + 1 != this.filteredList.length)
     this.pos++;
 }
 //console.log(this.pos)

 // Arrow-key Up
 if (event.keyCode == 38) {
   if (this.pos > 0)
     this.pos--;
 }

 if (this.filteredList[this.pos] !== undefined)

   this.filteredList[this.pos].selected = true;

 //enter
 if (event.keyCode == 13) {
   if (this.filteredList[this.pos] !== undefined) {
     this.select(this.filteredList[this.pos]);
   }
 }

 // Handle scroll position of item
 let listGroup = document.getElementById('list-group');
 //console.log("listGroup",listGroup);
 let listItem = document.getElementById('true');
 //console.log("listItem",listItem)
 if (listItem) {
   listGroup.scrollTop = (listItem.offsetTop - 200);
 }

}

 select(item: any) {


   this.selectedItem = item;

   this.query = item.option;
   this.filteredList = [];
  // this.opened = false;
 }

showAll(input: any) { input.select();

 if (this.filteredList.length > 0) {
   this.opened = false;
   this.filteredList = [];
 } else {
   this.opened = true;
   this.filteredList = this.items;
 }
 if (this.query === '') {
   this.clearAll();
 }

 this.clearSelects();

}

2

1 Answer 1

1

Well, it's not just a css issue. Because there is simple text populating in <li>'s adding a Pipe to your application will work, which will match typed query and then wrap around a span, and then we can do CSS work.

Demo

Added JS and CSS

CSS

.matching , .input-list {
  color: #ccc;

}

JS - src/autocomplete.ts

Add this after first line in your src/autocomplete.ts

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'exponentialStrength'})
export class ExponentialStrengthPipe implements PipeTransform {
  transform(value: string, query: string): string {  
    return value.split(query).join('<span class="matching">' + query + '</span>');
  }   
} 

Change LI in template to this

<li *ngFor="let item of filteredList" [class.active]="item.selected" [id]="item.selected" class="list-group-item item-list" (click)="select(item)"  [innerHTML]="item.name | exponentialStrength:query"></li>

Add below code to @Component

pipes: [ExponentialStrengthPipe]   

Demo image just for reference

Demo image just for reference

Sign up to request clarification or add additional context in comments.

2 Comments

That worked!! thanks a ton! I didnt know about using Pipe here. Am new to Angular2. This is good learning. Thanks again!
happy that it helped. Am new to ng2 even. You can up vote also 🙂

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.