Я использую Angular12, и здесь я использую автозаполнение в угловом материале, здесь проблема в том, что я могу получить результат на основе обращения к API, но в html я всегда получаю последний ответ-1.
Ц:
private getAutoPopulateData(serchVal: any): Observable<string[]> {
let data: any = [];
let results: any = [];
if (serchVal && serchVal.length > 0) {
this.searchService.searchOpenSearchData(serchVal).subscribe((searchData: AutoPopulate) => {
results = searchData.hits;
if (results.hits.length > 0) {
results.hits.forEach(h=>{
let item=h._source;
let addressProps=Object.keys(item).filter(p=> p.startsWith('AddressLine') && item[p].length >0);
addressProps.forEach(ap=>{
let addresses=item[ap].map((ai,idx)=>{
let address= `${ai} ${item.City[idx]} ${item.State} ${item.Zip[idx]}`;
return {name:item.ProfileName,address}
});
data= data.concat(addresses);
this.seeResultsData = data.length;
})
});
}
this.resultData = of(data);
this.isLoading = false;
});
}
else {
this.isLoading = false
}
if (this.resultData) {
return this.resultData;
} else
return null
}
private autoCompleteFormInit() {
this.stateCtrl.valueChanges.pipe(
debounceTime(500),
tap((() => this.isLoading = true)),
map(value => (this.getAutoPopulateData(value))
.pipe(finalize(() => this.isLoading = false)))
).subscribe(value => {
this.filteredOptions = value
});
}
public resultData: Observable<any> = of([]);
filteredOptions: Observable<any> = of([]);
searchOpenSearchData(searchValue:any): Observable<AutoPopulate> {
let url = URLConstants.openSearchUrl + searchValue;
return this.http.get<AutoPopulate>(url);
}
HTML:
<input matInput aria-label = "State" placeholder = "Enter a Name" [matAutocomplete] = "auto" class = "paddingleft-5 text-medium" (ngModelChange) = "updatedVal($event)" type = "text" [formControl] = "stateCtrl" *ngIf = "form.value.tradingPartnerValue && dropdownSelection == 'tradingPartnerName'"/>
<mat-autocomplete #auto = "matAutocomplete" (optionSelected) = "onOptionSelected($event.option)">
<div *ngIf = "showAutocomplete" class = "{{seeResultsData >3 ? 'set-height' : ''}}">
<mat-option *ngIf = "isLoading" class = "is-loading content-center">
<mat-spinner diameter = "50" class = "show-center"></mat-spinner>
</mat-option>
<ng-container *ngIf = "!isLoading">
<mat-option class = "option-custom text-medium" *ngFor = "let state of filteredOptions | async"
[value] = "state" [ngClass] = "{'hide-autocomplete': !showAutocomplete}">
<span [innerHTML] = "state.name | highlight : stateCtrl.value"></span>
<span [innerHTML] = "state.address | highlight : stateCtrl.value"></span>
</mat-option>
</ng-container>
</div>
</mat-autocomplete>
Json-ответ:
{
"took": 178,
"timed_out": false,
"_shards": {
"total": 0,
"successful": 0,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 10000,
"relation": "gte"
},
"max_score": 12.9226,
"hits": [
{
"_index": "pulse",
"_id": "17320",
"_score": 12.9226,
"_source": {
"ProfileName": "Pharmarx Pharmaceutical Inc",
"State": "CA",
"BusinessModel": "Dispenser",
"LicenseInfo": [
{
"LicenseType": "Resident Licensed Sterile Compounding",
"LicenseNumber": "99658",
"AddressLine1": "21441 Osborne St Ste C & D",
"AddressLine2": "",
"AddressLine3": "",
"AddressLine4": "",
"Zip": "91304",
"City": "Canoga Park"
},
{
"LicenseType": "Retail Pharmacy",
"LicenseNumber": "50511",
"AddressLine1": "21441 Osborne St Ste C & D",
"AddressLine2": "",
"AddressLine3": "",
"AddressLine4": "",
"Zip": "91304",
"City": "Canoga Park"
}
]
}
},
{
"_index": "pulse",
"_id": "7723",
"_score": 10.891928,
"_source": {
"ProfileName": "ENCINO PHARMACY_AKA MDR PHARMACEUTICAL CARE",
"State": "MI",
"BusinessModel": "Dispenser",
"LicenseInfo": [
{
"LicenseType": "PHARMACY",
"LicenseNumber": "5301010993",
"AddressLine1": "17071 VENTURA BLVD STE 100",
"AddressLine2": "",
"AddressLine3": "",
"AddressLine4": "",
"Zip": "91316",
"City": "ENCINO"
}
]
}
},
{
"_index": "pulse",
"_id": "7724",
"_score": 9.796367,
"_source": {
"ProfileName": "Encino Pharmacy_aka Mdr Pharmaceutical Care",
"State": "CA",
"BusinessModel": "Dispenser",
"LicenseInfo": [
{
"LicenseType": "Retail Pharmacy",
"LicenseNumber": "34818",
"AddressLine1": "17059-17071 VENTURA BLVD.",
"AddressLine2": "STE. 100",
"AddressLine3": "",
"AddressLine4": "",
"Zip": "91316",
"City": "ENCINO"
}
]
}
},
{
"_index": "pulse",
"_id": "192",
"_score": 9.656487,
"_source": {
"ProfileName": "Abdin Pharmacies Pharma LLC",
"State": "FL",
"BusinessModel": "Dispenser",
"LicenseInfo": [
{
"LicenseType": "Pharmacy",
"LicenseNumber": "036936",
"AddressLine1": "1873 SECOND AVE. NEW",
"AddressLine2": "",
"AddressLine3": "",
"AddressLine4": "",
"Zip": "10029",
"City": "YORK"
},
{
"LicenseType": "Pharmacy",
"LicenseNumber": "033404",
"AddressLine1": "1401 BRONX RIVER AVE.",
"AddressLine2": "",
"AddressLine3": "",
"AddressLine4": "",
"Zip": "10472",
"City": "BRONX"
},
{
"LicenseType": "Pharmacy",
"LicenseNumber": "PH33043",
"AddressLine1": "32866 US Hwy 19N",
"AddressLine2": "",
"AddressLine3": "",
"AddressLine4": "",
"Zip": "34684",
"City": "PALM HARBOR"
}
]
}
},
{
"_index": "pulse",
"_id": "17304",
"_score": 9.186218,
"_source": {
"ProfileName": "PHARMALABS, LLC PharmaLabs",
"State": "FL",
"BusinessModel": "Dispenser",
"LicenseInfo": [
{
"LicenseType": "Pharmacy",
"LicenseNumber": "PH26495",
"AddressLine1": "10901 ROOSEVELT BOULEVARD NORTH SUITE 1200",
"AddressLine2": "",
"AddressLine3": "",
"AddressLine4": "",
"Zip": "33716",
"City": "Saint Petersburg"
}
]
}
}
]
}
}
в пользовательском интерфейсе мне нужно отобразить, Имя профиля как имя в пользовательском интерфейсе, а также несколько адресов, представленных под одним и тем же именем профиля, например, один образец, который я взял из json, поэтому из этого массива объектов должен содержать,
[{name:'Pharmarx Pharmaceutical Inc', address:'21441 Osborne St Ste C & D,Canoga Park CA 9104'},
{name:'Pharmarx Pharmaceutical Inc', address:'21442 Osborne St Ste C & D(Address2/Address3/Address4)what ever is present must show, Canoga Park CA 9104'}]
так что это похоже на одно имя профиля, у нас есть несколько адресов местоположения
"_source": {
"ProfileName": "Pharmarx Pharmaceutical Inc",
"State": "CA",
"BusinessModel": "Dispenser",
"LicenseInfo": [
{
"LicenseType": "Resident Licensed Sterile Compounding",
"LicenseNumber": "99658",
"AddressLine1": "21441 Osborne St Ste C & D",
"AddressLine2": "",
"AddressLine3": "",
"AddressLine4": "",
"Zip": "91304",
"City": "Canoga Park"
},
{
"LicenseType": "Retail Pharmacy",
"LicenseNumber": "50511",
"AddressLine1": "21441 Osborne St Ste C & D",
"AddressLine2": "",
"AddressLine3": "",
"AddressLine4": "",
"Zip": "91304",
"City": "Canoga Park"
}
]
}
У вас есть некоторые проблемы в вашем коде, но основная причина, по которой вы получаете предыдущий результат, заключается в том, что вы делаете:
if (this.resultData) {
return this.resultData;
}
Если this.resultData
заполнен данными из предыдущего запроса, он вернется непосредственно перед тем, как наблюдаемый (this.searchService.searchOpenSearchData(serchVal)
) испустит и установит новое значение для this.resultData
.
Вы должны установить this.resultData
результат наблюдаемого из запроса API и дождаться результата, а не возвращать его, как вы сделали в своем коде.
Что-то вроде:
private getAutoPopulateData(serchVal: any): Observable<string[]> {
let data: any = [];
let results: any = [];
if (serchVal && serchVal.length > 0) {
this.isLoading = true;
this.resultData = this.searchService.searchOpenSearchData(serchVal).pipe(
map((searchData: AutoPopulate) => {
results = searchData.hits;
if (results.hits.length > 0) {
results.hits.forEach(h => {
let item=h._source;
let addressProps=Object.keys(item).filter(
p => p.startsWith('AddressLine') && item[p].length > 0
);
addressProps.forEach(ap => {
let addresses=item[ap].map((ai,idx)=>{
let address= `${ai} ${item.City[idx]} ${item.State} ${item.Zip[idx]}`;
return {name:item.ProfileName, address}
});
data = data.concat(addresses);
this.seeResultsData = data.length;
});
return data;
}
return null;
}),
finalize(() => this.isLoading = false);
);
} else {
this.resultData = of(null);
}
return this.resultData;
}
Я попытался вернуть null
там, где это необходимо, но проверьте, соответствуют ли эти места вашим потребностям (возможно, вместо этого вы хотите вернуть пустой массив). Я использовал pipe
, map
и finalize
из rxjs, которые нужно импортировать. Я переместил ваш isLoading = false
в завершение, чтобы он также «переставал загружаться» при ответах на ошибки.
Если еще вопросы, оставьте комментарий.
После того, как вы добавили дополнительный код к своему вопросу в «редактировании», я должен обновить свой ответ:
С изменениями, о которых я упоминал выше, ваш метод autoCompleteFormInit
должен измениться следующим образом:
private this.subscription: Subscription;
private autoCompleteFormInit() {
this.subscription = this.stateCtrl.valueChanges.pipe(
debounceTime(500),
switchMap(value => this.getAutoPopulateData(value))
).subscribe(value => this.filteredOptions = value);
}
// To prevent memory leaks, store subscription and unsubscribe on destroy
public ngOnDestroy(): void {
if (this.subscription) this.subscription.unsubscribe();
}
Я также изменил логику относительно isLoading
, лучше, чтобы он вызывался только в методе, который фактически отправляет запрос.
Еще многое можно улучшить, но это должно работать с минимальными изменениями кода в исходном опубликованном примере кода.
@Bhrungarajni Вам нужно подписаться на наблюдаемое, где вы вызываете getAutoPopulateData
вне этого кода. Если вы нигде не подпишитесь, он не будет выполнять наблюдаемое.
да, я подписался на метод автозаполнения
@Bhrungarajni Этот код с методом автозаполнения был добавлен к вопросу после того, как я ответил. Когда вы задаете вопрос, вы должны убедиться, что добавлены все соответствующие части кода. Я посмотрю позже, смогу ли я обновить свой ответ...
Пожалуйста, Уилт, сегодня я добавил данные json на основе ответа Дэниела.
спасибо за ответ, Уилт, так что мне нужно добавить оба метода из вашего кода, верно?
API работает, но не может видеть данные в html, я имею в виду, что значение в раскрывающемся списке не отображается
Давайте продолжим обсуждение в чате.
привет @Wilt, не могли бы вы проверить это, stackoverflow.com/questions/76217665/…
с приведенным выше кодом он не попадает в API, и я не могу увидеть ошибку также в консоли