我在我的项目中使用ngx-mat-select-search组件。我提到了以下示例:
此示例在我的角度项目中运行良好。但是,如果我将动态数据用作下拉选项,则搜索栏将无法正常工作。
我的代码如下:
HTML文件:
<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文件:
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)
);
}
}
我通过以下方式传递了动态数据,而不是静态库值:
this.banks: Bank[] = appsData.filter(app => {
if(app.id != null) {
return app;
}
});
但是它给'Bank'仅指一种类型,但是在这里被用作值。
该如何解决? 请提供解决此问题的解决方案。
感谢与问候
希尔帕·库尔卡尼
答案 0 :(得分:0)
在当前代码中,您已经在类声明的正下方声明了“ banks”类变量的类型:
export class AdminLayoutComponent implements OnInit, OnDestroy {
banks: any;
...
因此,您无需再次声明类型。只需将上面的代码片段更改为以下内容:
this.banks = appsData.filter(app => {
if(app.id != null) {
return app;
}
});
注意-从代码中还不清楚您实际上要完成什么。此答案将解决您提到的错误,但可能无法帮助您解决实际上要解决的问题。
答案 1 :(得分:0)
此问题已在此处回答并接受:
https://github.com/bithost-gmbh/ngx-mat-select-search/issues/72
模板需要更改为
*ngFor="let app of apps"
到
*ngFor="let app of filteredBanks | async"
和
getDeployedApps() {
this.appsProcessService.getDeployedApplications()
.subscribe(data =>{
...
this.filteredBanks.next(data.slice());
})
}
由于问题的作者已接受https://github.com/bithost-gmbh/ngx-mat-select-search/issues/72中的答案并确认解决方案有效,因此应将其作为接受的答案。