Hi, I want to use typeahead with http but I get an error which is "options.slice is not a function".Please Help Me
@Injectable()
export class UserService {
constructor(private http: Http ) { }
getAllUsers(email: string): Observable <any>{
let params = new URLSearchParams();
params.set('email', email);
return this.http.get("http://localhost:8080/user/list",{ search: params })
.map((res:Response) => this.extractData );
}
private extractData(res: Response) {
let body = res.json();
return body || { };
}
}
@Component({
selector: 'app-device-add',
templateUrl: './device-add.component.html',
styleUrls: ['./device-add.component.scss']
})
export class DeviceAddComponent implements OnInit {
ngOnInit(){}
public asyncSelected:string = '';
public statesComplex:Array<any>;
public dataSource: Observable<any>;
public typeaheadLoading:boolean = false;
public typeaheadNoResults:boolean = false;
public constructor(private userService: UserService) {
this.dataSource = Observable.create((observer:any) => {
this.userService.getAllUsers(this.asyncSelected)
.subscribe((result: any) => {
observer.next(result);
})
});
}
public changeTypeaheadLoading(e:boolean):void {
this.typeaheadLoading = e;
}
public changeTypeaheadNoResults(e:boolean):void {
this.typeaheadNoResults = e;
}
public typeaheadOnSelect(e:TypeaheadMatch):void {
console.log('Selected value: ', e.value);
}
}
<h4>Asynchronous results</h4>
<pre class="card card-block card-header">Model: {{asyncSelected | json}}</pre>
<input [(ngModel)]="asyncSelected"
[typeahead]="dataSource"
(typeaheadLoading)="changeTypeaheadLoading($event)"
(typeaheadNoResults)="changeTypeaheadNoResults($event)"
(typeaheadOnSelect)="typeaheadOnSelect($event)"
[typeaheadOptionsLimit]="1"
[typeaheadOptionField]="'email'"
placeholder="Locations loaded with timeout"
class="form-control">
<div *ngIf="typeaheadLoading===true">
<i class="glyphicon glyphicon-refresh ng-hide" style=""></i>
</div>
<div *ngIf="typeaheadNoResults===true" class="" style="">
<i class="glyphicon glyphicon-remove"></i> No Results Found
</div>
@valorkin
Hi everyone, I have the same issue with the same syntax. Tried several ways to do it.
I skipped some of the methods/properties in order to make it more clear.
Note: The service returns the array of Schools and component successfully subscribes to it.
When observer.next(result); is executed, the Error gets thrown: EXCEPTION: options.slice is not a function
NOTE 2: I know that in Angular RC4, we had to have a hack to make it work with the service that gets the data for typeahead. The hack was as follows:
1) The HTML markup
<input [disabled]="!IsFormAuthorized" id="School" name="School" [(ngModel)]="asyncSelected"
[typeahead]="autoCompleteRef"
2) Component code (
public autoCompleteRef = this.getAsyncData.bind(this); //getAsynData returned promise <School[]>
3) May be something similar can be done with the service that returns observable?
core.umd.js:3010 TypeError: options.slice is not a function
at TypeaheadDirective.prepareMatches (ng2-bootstrap.umd.js:5376)
at TypeaheadDirective.finalizeAsyncCall (ng2-bootstrap.umd.js:5358)
at SafeSubscriber.eval [as _next] (ng2-bootstrap.umd.js:5314)
at SafeSubscriber.__tryOrUnsub (Subscriber.ts:238)
at SafeSubscriber.next (Subscriber.ts:190)
at Subscriber._next (Subscriber.ts:135)
at Subscriber.next (Subscriber.ts:95)
at MergeMapSubscriber.notifyNext (mergeMap.ts:144)
at InnerSubscriber._next (InnerSubscriber.ts:17)
at InnerSubscriber.Subscriber.next (Subscriber.ts:95)ErrorHandler.handleError @ core.umd.js:3010next @ core.umd.js:6654schedulerFn @ core.umd.js:5952SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:5944NgZone.triggerError @ core.umd.js:6248onHandleError @ core.umd.js:6227ZoneDelegate.handleError @ zone.js:207Zone.runTask @ zone.js:139ZoneTask.invoke @ zone.js:304
Subscriber.ts:241 Uncaught TypeError: options.slice is not a functionTypeaheadDirective.prepareMatches @ ng2-bootstrap.umd.js:5376TypeaheadDirective.finalizeAsyncCall @ ng2-bootstrap.umd.js:5358(anonymous function) @ ng2-bootstrap.umd.js:5314SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95MergeMapSubscriber.notifyNext @ mergeMap.ts:144InnerSubscriber._next @ InnerSubscriber.ts:17Subscriber.next @ Subscriber.ts:95(anonymous function) @ locations.component.ts:226SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95MapSubscriber._next @ map.ts:84Subscriber.next @ Subscriber.ts:95Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95onLoad @ http.umd.js:1083ZoneDelegate.invokeTask @ zone.js:236onInvokeTask @ core.umd.js:6197ZoneDelegate.invokeTask @ zone.js:235Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304
Module Code Snippet
`import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { TypeaheadModule } from 'ng2-bootstrap/ng2-bootstrap';
//component and routing module
import { LocationsComponent } from './locations.component';
import { LocationsRoutingModule } from './locations-routing.module';
import { SchoolService } from '../school/schoolService';
@NgModule({
imports: [
CommonModule,
LocationsRoutingModule,
FormsModule,
TypeaheadModule
],
declarations: [
LocationsComponent
],
providers: [
SchoolService
],
exports: [CommonModule]
})
export class LocationsModule { }`
Component Code Snippet
@Component({
selector: 'locations-form',
templateUrl: './locations.html'
})
export class LocationsComponent implements OnInit {
` public dataSource: Observable
constructor(private _schoolService: SchoolService,) {
this.dataSource = Observable.create((observer: any) => {
return this._schoolService.getSchools4(this.asyncSelected)
.subscribe((result: any) => {
observer.next(result); //this line fails; result contains array of schools
})
});
}`
HTML Template Code Snippet
<input [disabled]="!IsFormAuthorized" id="School" name="School" [(ngModel)]="asyncSelected"
[typeahead]="dataSource"
[typeaheadOptionField]="'Name'"
(typeaheadLoading)="changeTypeaheadLoading($event)"
(typeaheadNoResults)="changeTypeaheadNoResults($event)"
(typeaheadOnSelect)="typeaheadOnSelect($event)"
class="form-control"
required>
Service Code Snippet
` getSchools4(query: string): Observable
return this.http.get(this._userAPIUrl + '/' + query)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || {};
}
private handleError(error: Response) {
// in a real world app, we may send the error to some remote logging infrastructure
// instead of just logging it to the console
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}`
School Class Code Snippet
export class School {
constructor(
public OrganizationId: number,
public Name: string
) { }
}
@binarydigits thanks for stack, now I will be able to kick it directly :)
@valorkin Spasibo Dmitriy!
I don't think you have your data source setup properly. From the documentation
this.dataSource = Observable.create((observer:any) => {
// Runs on every search
// asyncSelected is a component variable bound to [(ngModel)]
// when user types into the input .next is called with the value from the input
observer.next(this.asyncSelected);
}).mergeMap((term: string) => this.myAsyncDataService.search(term));
Make sure you have that last mergeMap and that your service returns an array.
Hi everyone, sorry for late reply. I was away.
The typeahead works as expected after I pulled the latest code.
Awesome, closing :)
In case this will help others... I was also receiving "options.slice is not a function", and the issue was the way I implemented the async service returning my array of objects in Angular4.
I forgot to map my response to json in the service (Angular1 habits die hard) like this:
getList(listName:string, query:string): Observable<any> {
return this.http.get(${this.apiUrl}/${listName}?query=${query});
}
Once I changed it to this, the "options.slice" problem was resolved.
getList(listName:string, query:string): Observable<any> {
return this.http.get(${this.apiUrl}/${listName}?query=${query})
.map((res: Response) => res.json())
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
}
I checked in the ngx-bootstrap library typeahead.directive.js line 259, and noticed that the limited variable was just a truncated string like '[{ "foo:', and realized the response was not converted to a json object, but was merely a string.
Following @avalonabecker, here's another example
getStatesAsObservable(token: string): Observable<any> {
const query = new RegExp(token, 'ig');
const fn = () => {
return new Observable((observer) => {
setTimeout(() => {
const res = this.statesComplex.filter((state: any) => {
return query.test(state.name);
});
observer.next(res);
}, 1000);
});
};
return fn();
}
Most helpful comment
In case this will help others... I was also receiving "options.slice is not a function", and the issue was the way I implemented the async service returning my array of objects in Angular4.
I forgot to map my response to json in the service (Angular1 habits die hard) like this:
getList(listName:string, query:string): Observable<any> { return this.http.get(${this.apiUrl}/${listName}?query=${query}); }Once I changed it to this, the "options.slice" problem was resolved.
getList(listName:string, query:string): Observable<any> { return this.http.get(${this.apiUrl}/${listName}?query=${query}) .map((res: Response) => res.json()) .catch((error:any) => Observable.throw(error.json().error || 'Server error')); }I checked in the ngx-bootstrap library typeahead.directive.js line 259, and noticed that the limited variable was just a truncated string like '[{ "foo:', and realized the response was not converted to a json object, but was merely a string.