Angular ngx-mat-select-search not working with dynamic data




Asked on October 22, 2018
Hello,

I am using ngx-mat-select-search component in my project. I referred the following example:
  • https://stackblitz.com/github/bithost-gmbh/ngx-mat-select-search-example?file=src%2Fapp%2Fapp.component.html
  • https://github.com/bithost-gmbh/ngx-mat-select-search
This example works fine in my angular project. But if I use my dynamic data as drop down option then the search bar is not working properly.
My code is as follows:

HTML file:
<mat-form-field>
<mat-select [formControl]="bankCtrl" #singleSelect>
<ngx-mat-select-search [formControl]="bankFilterCtrl"></ngx-mat-select-search>
<mat-option value = "select">Select bank</mat-option>
<mat-option *ngFor="let app of apps" [value]="app">
{{app.name}}
</mat-option>
</mat-select>
</mat-form-field>

TS File:
import { Component, NgZone, OnInit, OnDestroy, ViewChild, HostListener, ViewEncapsulation } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
//import { MenuItems } from '../../shared/menu-items/menu-items';
import { MenuItems } from '../../bridle-menus/menu-items/menu-items';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/filter';

import { TranslateService } from '@ngx-translate/core';

import { PerfectScrollbarConfigInterface, PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
import { ClientService, User, LocationService, ProcessAdminServices, Userinfo } from '../../shared/services/index';
import { AuthService } from "../../shared/services/auth.service";
import { env_host } from "../../shared/services/endpoints";
import { Globals } from '../../shared/services/globals';

import { AppDefinitionRepresentationModel, ProcessService, ProcessDefinitionRepresentation, ProcessInstance } from "../../process-services/index";
import {FormControl} from '@angular/forms';
import { Observable, ReplaySubject, Subject } from 'rxjs';
import { map, startWith, takeUntil, take } from 'rxjs/operators';
import { AppsProcessService, AuthenticationService, LogService, UserPreferencesService } from "../../core/index";
//added on 22-10-2018
import { VERSION, MatSelect } from '@angular/material';

const SMALL_WIDTH_BREAKPOINT = 960;
//added on 22-10-2018
interface Bank {
/** id: number;
name: string;**/
defaultAppId: string;
deploymentId: string;
name: string;
description: string;
theme: string;
icon: string;
id: number;
modelId: number;
tenantId: number;
}
@Component({
selector: 'app-layout',
templateUrl: './admin-layout.component.html',
styleUrls: ['admin-layout.component.scss'],
providers:[ClientService,AuthService,LocationService,ProcessAdminServices,AppsProcessService,ProcessService],
encapsulation: ViewEncapsulation.None
})
export class AdminLayoutComponent implements OnInit, OnDestroy {
banks: any;

private _router: Subscription;

mediaMatcher: MediaQueryList = matchMedia(`(max-width: ${SMALL_WIDTH_BREAKPOINT}px)`);
today: number = Date.now();
url: string;
showSettings = false;
dark: boolean;
boxed: boolean;
collapseSidebar: boolean;
compactSidebar: boolean;
currentLang = 'en';
dir = 'ltr';
sidePanelOpened;
user;
scopes: string;
returnscope: string;
userinform = [];
locationId: string;
dspName: string;
dropdownStyle: string;
apps = [];
//Bank=[];
statusCode: number;
currentApp: string = "";
selectedApp= [];
myapp;
processDefinitions: ProcessDefinitionRepresentation[] = [];
processDefinitionKey:string;
start:string="start";
authenticated: boolean;
userinfo: Userinfo;
@ViewChild('sidemenu') sidemenu;
@ViewChild(PerfectScrollbarDirective) directiveScroll: PerfectScrollbarDirective;

public config: PerfectScrollbarConfigInterface = {};
//Added on 22-10-2018
version = VERSION;
/** control for the selected bank */
public bankCtrl: FormControl = new FormControl();

/** control for the MatSelect filter keyword */
public bankFilterCtrl: FormControl = new FormControl();
/*private banks: Bank[] = [
{name: 'Bank A (Switzerland)', id: 'A'},
{name: 'Bank B (Switzerland)', id: 'B'},
{name: 'Bank C (France)', id: 'C'},
{name: 'Bank D (France)', id: 'D'},
{name: 'Bank E (France)', id: 'E'},
{name: 'Bank F (Italy)', id: 'F'},
{name: 'Bank G (Italy)', id: 'G'},
{name: 'Bank H (Italy)', id: 'H'},
{name: 'Bank I (Italy)', id: 'I'},
{name: 'Bank J (Italy)', id: 'J'},
{name: 'Bank Kolombia (United States of America)', id: 'K'},
{name: 'Bank L (Germany)', id: 'L'},
{name: 'Bank M (Germany)', id: 'M'},
{name: 'Bank N (Germany)', id: 'N'},
{name: 'Bank O (Germany)', id: 'O'},
{name: 'Bank P (Germany)', id: 'P'},
{name: 'Bank Q (Germany)', id: 'Q'},
{name: 'Bank R (Germany)', id: 'R'}
];*/

/** list of banks filtered by search keyword */
public filteredBanks: ReplaySubject<Bank[]> = new ReplaySubject<Bank[]>(1);
@ViewChild('singleSelect') singleSelect: MatSelect;
/** Subject that emits when the component has been destroyed. */
private _onDestroy = new Subject<void>();

constructor(
private router: Router, public menuItems: MenuItems, private globals: Globals,
public translate: TranslateService, zone: NgZone,private clientService:ClientService,private authService: AuthService,private processAdminServices: ProcessAdminServices,
private appsProcessService:AppsProcessService,
private processService: ProcessService,
private authenticationService: AuthenticationService,
private logService: LogService,
private userPreferenceService: UserPreferencesService

) {
userPreferenceService.authType='BPM';

const browserLang: string = translate.getBrowserLang();
translate.use(browserLang.match(/en|fr/) ? browserLang : 'en');
this.mediaMatcher.addListener(mql => zone.run(() => {
this.mediaMatcher = mql;
}));
}

ngOnInit(): void {
this.getScopes();
this.login();
this.getUserInfo();
this.url = this.router.url;
this.dropdownStyle = "dropdown-content";
//ADDED ON 22-10-2018
// set initial selection
this.bankCtrl.setValue(this.apps[0]);
// load the initial bank list
this.filteredBanks.next(this.apps.slice());
// listen for search field value changes
this.bankFilterCtrl.valueChanges
.pipe(takeUntil(this._onDestroy))
.subscribe(() => {
this.filterBanks();
});



this._router = this.router.events.filter(event => event instanceof NavigationEnd).subscribe((event: NavigationEnd) => {
document.querySelector('.app-inner > .mat-drawer-content > div').scrollTop = 0;
this.url = event.url;
this.runOnRouteChange();
});

}

//ADDED on 22-10-2018
ngAfterViewInit() {
this.setInitialValue();
}

/**
* Sets the initial value after the filteredBanks are loaded initially
*/
private setInitialValue() {
this.filteredBanks
.pipe(take(1), takeUntil(this._onDestroy))
.subscribe(() => {
// setting the compareWith property to a comparison function
// triggers initializing the selection according to the initial value of
// the form control (i.e. _initializeSelection())
// this needs to be done after the filteredBanks are loaded initially
// and after the mat-option elements are available
this.singleSelect.compareWith = (a: Bank, b: Bank) => a && b && a.id === b.id;
// this.multiSelect.compareWith = (a: Bank, b: Bank) => a && b && a.id === b.id;
});
}
ngOnDestroy(): void {
this._router.unsubscribe();
//added on 22-10-2018
this._onDestroy.next();
this._onDestroy.complete();
}

runOnRouteChange(): void {
if (this.isOver()) {
this.sidemenu.close();
}

this.updatePS();
}

isOver(): boolean {
if (this.url === '/apps/messages' ||
this.url === '/apps/calendar' ||
this.url === '/apps/media' ||
this.url === '/maps/leaflet' ||
this.url === '/taskboard') {
return true;
} else {
return this.mediaMatcher.matches;
}
}

menuMouseOver(): void {
if (this.mediaMatcher.matches && this.collapseSidebar) {
this.sidemenu.mode = 'over';
}
}

menuMouseOut(): void {
if (this.mediaMatcher.matches && this.collapseSidebar) {
this.sidemenu.mode = 'side';
}
}

updatePS(): void {
if (!this.mediaMatcher.matches && !this.compactSidebar) {
setTimeout(() => {
this.directiveScroll.update();
}, 350);
}
}

// addMenuItem(): void {
// this.menuItems.add({
// state: 'menu',
// name: 'MENU',
// type: 'sub',
// icon: 'trending_flat',
// role: 'admin',
// children: [
// {state: 'menu', name: 'MENU'},
// {state: 'timeline', name: 'MENU'}
// ]
// });
// }

logout(){
//alert("coming in logout");
// this.clientService.logout();
// this.router.navigate(["/"]);
this.clientService.logout()
/**.subscribe(
data => {
this.router.navigate(['']);
});**/
.subscribe(successCode => {
//alert("logged out");
         // this.router.navigate(['/']);
// this.router.navigate(['']);
// this.router.navigateByUrl('');
// this.returnUrl = this.route.snapshot.queryParams['localhost:8088'] || '/';
//alert("returnUrl Is:"+this.returnUrl);
// this.router.navigate([this.returnUrl]);
//localStorage.removeItem('loggedInUserName');

window.location.href=env_host+"/";

         }
       );
}

getScopes() {
this.authService.getScopes()
.subscribe(
data => {
this.scopes = data;
console.log("scopes=>"+this.scopes);
if (this.scopes.includes("admin")) {
this.returnscope = "yes";
return this.returnscope
}
});
}

getUserInfo(){
this.clientService.getUserInform()
.subscribe(
data => {

this.userinform = data;
console.log("userInform data=>",this.userinform);
//localStorage.setItem('loggedInUserName', this.userinform[0].username);
this.dspName= this.userinform[0].displayname;
this.locationId = this.userinform[0].location_id;
//var loggedInUser = localStorage.getItem('loggedInUserName');
//this.getApps(loggedInUser);
}
)
}

public getLocationId(locationIdAndName: any) {
this.globals.locationIdAndName = locationIdAndName;
}

//lists logged in user's applications
getApps(loggedInUser) {
this.processAdminServices.getApps(loggedInUser)
   .subscribe(
data =>{
let appsData = data["data"];
this.apps = appsData.filter(app => {
if(app.id != null) {
return app;
}
});
},
errorCode => {this.statusCode = errorCode}
);

}

//On select application from drop down should redirect to start process form of the selected app
onAppClickToStartProcess(myapp) {
this.selectedApp = this.getSelectedAppByName(myapp);
let appName = this.selectedApp['name'];
let appId = this.selectedApp['id'];
this.processService.getProcessDefinitions(appId).subscribe(

data => {
this.processDefinitions = data;
this.processDefinitionKey = this.processDefinitions[0].key;
this.router.navigate(['app-list/activiti/start1',appId || 0,appName,this.processDefinitionKey,this.start,this.processDefinitions[0].id]);
});
}
//get selected application details by app name
getSelectedAppByName(myapp: string) {
return this.apps.find(app => app.name === myapp);
}

public enableDropdown() {
if (this.dropdownStyle == "dropdown-content") {
this.dropdownStyle = "dropdown-content-enable";
}
else {
this.dropdownStyle = "dropdown-content";
}
}

@HostListener('mouseup')
onMouseUp() {
if (this.dropdownStyle == "dropdown-content-enable") {
this.dropdownStyle = "dropdown-content";
}
}

login() {
this.clientService.getUserInfo()
.subscribe(
data => {
this.userinfo = data;
this.authenticationService.login(this.userinfo.email, 'Bridle@456', true)
.subscribe(
(ticket: any) => {
this.logService.info(ticket);
this.authenticated=true;
if(this.authenticated == true){
this.getDeployedApps();
}
},
(err: any) => {
// this.actualLoginStep = LoginSteps.Landing;
this.authenticated=false;
},
() => console.log('Login done')
);}
)
}

getDeployedApps() {

this.appsProcessService.getDeployedApplications()
.subscribe(
data =>{
let appsData = data;
this.apps = appsData.filter(app => {
if(app.id != null) {
return app;

}
});
/**this.Bank = appsData.filter(app => {
if(app.id != null) {
return app;

}
});**/
this.banks: Bank[] = appsData.filter(app => {
if(app.id != null) {
return app;

}
});
console.log("BANK DETAILS");
// console.dir(this.Bank);
},

errorCode => {this.statusCode = errorCode}
);

}

//ADDED on 22-10-2018
private filterBanks() {
if (!this.apps) {
return;
}
// get the search keyword
let search = this.bankFilterCtrl.value;
if (!search) {
this.filteredBanks.next(this.apps.slice());
return;
} else {
search = search.toLowerCase();
}
// filter the banks
this.filteredBanks.next(
this.apps.filter(app => app.name.toLowerCase().indexOf(search) > -1)
);
}

}


Instead of static bank values I passed the dynamic data as follows:
this.banks: Bank[] = appsData.filter(app => {
if(app.id != null) {
return app;

}
});
But it is giving 'Bank' only refers to a type, but is being used as a value here.

How to resolve this ? 
Please provide solution for solving this issue.

Thanks & Regards,
Shilpa Kulkarni



Replied on October 22, 2018
getDeployedApps() {

        this.appsProcessService.getDeployedApplications()
.subscribe(
    data =>{ 
      let appsData = data;
      
            this.apps = appsData.filter(app => { 
            if(app.id != null) { 
           return app;

            } 
           });
         
            },
                                 

    errorCode =>  {this.statusCode = errorCode}
    
                  );

}

This is the dynamic data I am passing. I am able to get this in drop down but filter is not working. How to map this dynamic values to interface?




Replied on October 24, 2018
Try enclosing the code within ngIf

<div *ngIf="apps">
<mat-form-field>
  <mat-select [formControl]="bankCtrl"  #singleSelect>
<ngx-mat-select-search [formControl]="bankFilterCtrl"></ngx-mat-select-search>
<mat-option value = "select">Select bank</mat-option>
<mat-option *ngFor="let app of apps" [value]="app">
  {{app.name}}
</mat-option>
  </mat-select>
</mat-form-field>
</div>


Write Answer











©2024 concretepage.com | Privacy Policy | Contact Us