I am using Angular 2 for my web application. Now I am trying to populate a checkbox list from backend service call. This is what I am trying.
main.ts
import {bootstrap} from 'angular2/platform/browser';
import {ROUTER_PROVIDERS} from 'angular2/router';
import {HTTP_PROVIDERS} from 'angular2/http';
import 'rxjs/add/operator/map';
import {DataService} from './service'
import {AppComponent} from './app.component';
bootstrap(AppComponent, [ROUTER_PROVIDERS,HTTP_PROVIDERS,DataService]);
service.ts
import {Http, Response} from 'angular2/http'
import {Injectable} from 'angular2/core'
#Injectable()
export class DataService {
http: Http;
constructor(http: Http) {
this.http = http;
}
getCheckboxList() {
return this.http.get('http://localhost:8080/test/getList').map((res: Response) => res.json());
}
}
checkbox.ts
import {Component} from 'angular2/core';
import {DataService} from '../service';
#Component({
templateUrl: 'views/checkboxlist.html'
})
export class CheckboxComponent {
message = "hello";
constructor(dataService: DataService) {
dataService.getCheckboxList().subscribe(function(res) {
console.log(res.result);
this.list = res.result;
console.log(this.list);
})
}
}
checkboxlist.html
<div>
<label *ngFor="#item of list">
<input type="checkbox">{{item.value}}
</label>
</div>
Backend service is successful and returns a response and line console.log(this.list); prints an object array (HTTP response). Although, it doesn't display the checkbox list and there is not any error on the console log.
Does anyone have any idea what's wrong with my code?
Thank You
You should use an arrow function in your component to be able to use the lexical this. In this case, the this keyword will correspond to the instance of the component. In your case, you use a "normal" function and the this keyword used in it doesn't correspond to the component instance...
dataService.getCheckboxList().subscribe((res) => { // <--------
console.log(res.result);
this.list = res.result;
console.log(this.list);
})
See this plunkr: https://plnkr.co/edit/r1kQXlBVYvuO5fvQJgcb?p=preview.
See this link for more details:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
I would expect an error message in the browser console
Try the safe-navigation ?.
<input type="checkbox">{{item?.value}}
Related
Hi i have problem with my code.
import { Injectable } from '#angular/core';
import { Car } from "./models/car";
import { Observable } from "rxjs/Observable";
import { Http } from "#angular/http";
import 'rxjs'
#Injectable()
export class CarsService {
private apiUrl = "http://localhost:3000/api/cars";
constructor(private http : Http) { }
getCars() : Observable<Car[]> {
return this.http.get(this.apiUrl)
.map((res) => res.json())
}
}
With this code i have error:
this.http.get(...).map is not a function
but when i add:
import 'rxjs/add/operator/map'
Still have problem but error is:
Cannot read property 'map' of undefined
Can you help me? Thanks
As mentioned by others Http is deprecated, use HttpClient instead. HttpClient parses your response to an Object, so you remove the mapping of the response. Also, to avoid type checking errors, tell Angular what kind of response you are expecting.
So import HttpClientModule and add it to imports array, after BrowserModule. In your Service import HttpClient, inject it in your constructor and use it the following way:
import { Injectable } from '#angular/core';
import { Car } from "./models/car";
import { Observable } from "rxjs/Observable";
import { HttpClient } from "#angular/common/http";
import 'rxjs'
#Injectable()
export class CarsService {
private apiUrl = "http://localhost:3000/api/cars";
constructor(private httpClient : HttpClient) { }
getCars() : Observable<Car[]> {
// tell Angular you are expecting an array of 'Car'
return this.httpClient.get<Car[]>(this.apiUrl)
}
}
With angular5 HttpClient implementation already includes inner using of the map.so it works for you automatically.
just update it as
getCars() : Observable<Car[]> {
return this.http.get(this.apiUrl)
}
Also make sure you are using HttpClient instead of Http.
You can read more about this here
Edit your code
import { Injectable } from '#angular/core';
import { Car } from "./models/car";
import { Observable } from "rxjs/Observable";
import { Http } from "#angular/http";
#Injectable()
export class CarsService {
private apiUrl = "http://localhost:3000/api/cars";
constructor(private http : Http) { }
getCars() : Observable<Car[]> {
return this.http.get(this.apiUrl)
}
}
since it automatically parse the response as JSON. You don't have to explicitly parse it.
ngOnInit() {
this.loadCars();
}
loadCars() : void {
this.carsService.getCars().subscribe((cars) => {
this.cars = cars;
this.countTotalCost();
})
}
So i move this this.countTotalCost();
from ngOnInit to loadCars
and now .map its ok.
I have only this error: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'NaN'.
<div class="row" *ngIf="grossCost"> //this line error/error context
<div class="col-sm-12">
<div class="total-cost">
<p class="text-right">TOTAL GROSS COST: {{ grossCost}} PLN</p>
</div>
</div>
</div>
In my Angular 4 app I'm trying to get some data from an API. I'm using this article which explains how to do that, but I'm getting an exception:
TypeError: this.http.get(...).map is not a function
This is my code:
import { Injectable } from '#angular/core';
import { Http, Response, Headers } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import { Person } from '../../../interfaces/Person';
import {configuration} from "../config";
#Injectable()
export class AdsService{
private baseUrl: string = configuration.serverUrl;
constructor(private http : Http){
}
getAll(): Observable<Person[]>{
let people$ = this.http
.get(`${this.baseUrl}/people`, {headers: this.getHeaders()})
.map(mapPeople);
return people$;
}
}
function mapPeople(response:Response): Person[]{
return response.json().results;
}
Any help will be profoundly appreciated!
I dont see the map method imported.
Add this to your imports
import rxjs/add/operator/map
You must import map in this file, for that you just need to add the following line:
import 'rxjs/add/operator/map';
OR
import 'rxjs/add/operators/map';
Also, if you are using Angular 5 or above, then the above imports have been sorted to :
import { map } from 'rxjs/operator';
OR
import { map } from 'rxjs/operators';
Add this and Enjoy !!! :-)
I tried everything and I cannot get an http request to go out to my node server on heroku. I can hit the route manually so its not the server. I will paste my service and my page.
**Class is subscription.service.ts
import {Http, Response} from '#angular/http'
import {Injectable} from '#angular/core'
import 'rxjs/add/operator/map';
#Injectable()
export class SubscriptionService {
http:Http;
constructor(http:Http){
this.http = http;
}
getEntries() {
return this.http.get('my url here *****').map(res => res.json());
}
}
**Class is dashboard.component.ts
import {Component, ViewEncapsulation} from '#angular/core';
import {SubscriptionService} from '../../_services/subscription.service';
import 'rxjs/Rx';
#Component({
selector: 'dashboard',
providers: [SubscriptionService],
encapsulation: ViewEncapsulation.None,
styles: [require('./dashboard.scss')],
template: require('./dashboard.html')
})
export class Dashboard {
getData: string;
constructor(private subscriptionService: SubscriptionService) {
}
ngOnInit() {
console.log("test!!");
this.subscriptionService.getEntries()
.subscribe(data => this.getData = JSON.stringify(data),
error => console.log("Error!"),
() => console.log("finished!")
);
}
}
My ngOnInit() is being called, I see the console print, but no request shows up in logs on heroku. Also no errors show up in console.
Make sure you have imported the HttpModule in root.
I don't see anything else which can cause this. For make sure http is working you can put a break point in SubscriptionService on getEntries method and follow where it leads you.
Update:- as pointed out by #peeskillet there is nothing wrong with your dependency. try to debug and update your question with more information.
Screenshot of error:
Code where error exists:
import {Component, OnInit} from 'angular2/core';
import {Router} from 'angular2/router';
import {Hero} from './hero';
import {HeroService} from './hero.service';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {HeroesComponent} from './heroes.component';
import {HeroDetailComponent} from './hero-detail.component';
import {DashboardComponent} from './dashboard.component';
import {SpreadSheetComponent} from './spreadsheeteditall.component';
import {SwitchUsersComponent} from './SwitchUsers.component';
import {BiddingPageComponent} from './BiddingPage.component';
import { Injectable } from 'angular2/core';
import { Jsonp, URLSearchParams } from 'angular2/http';
#Component({
selector: 'SearchAndDisplayComponent',
templateUrl: 'app/SearchDisplay.component.html',
styleUrls: ['app/SearchDisplay.component.css'],
providers: [HeroService],
directives: [ROUTER_DIRECTIVES]
})
#Injectable()
export class SearchAndDisplayComponent{
constructor(private jsonp: JSON) {}
search (term: string) {
// let ebayURL = 'http://en.wikipedia.org/w/api.php';
var params = new URLSearchParams();
params.set('search', term); // the user's search value
params.set('action', 'opensearch');
params.set('format', 'json');
params.set('callback', 'JSONP_CALLBACK');
// TODO: Add error handling
return this.jsonp
.get({ search: params })
.map(request => <string[]> request.json()[1]);
}
}
Context of the problem:
I am trying to create a search bar for a website that is basically a clone of ebay.
Here is a question I posted earlier with links to the whole project (plunker/full project zipped)
Search bar that hides results that aren't typed into it
HTML code of how I'm trying to display it by the click of a button next to the search bar:
<button (click)="search(term)">Search</button>
You need to inject the Jsonp class instead of the JSON one in the constructor. The Jsonp object will allow you to execute JSONP requests.
import {Jsonp} from 'angular2/http';
(...)
export class SearchAndDisplayComponent{
constructor(private jsonp: Jsonp) {} // <-----
(...)
}
JSON is javascript namespace object. You have imported Jsonp from the module angular2/http, so in constructor of yout service change JSON to Jsonp. And don't forget to add Jsonp provider to some component above at component hierarchy.
Angular2, now in beta, my company decide to work on it a little bit.
I tried to set a request from my service. I browse all the internet, but nothing working. (Maybe posts was written before Beta release).
So, I have my boot.ts like this :
import {bootstrap} from 'angular2/platform/browser';
import {Component, provide} from 'angular2/core';
import {HTTP_PROVIDERS} from 'angular2/http';
import {BrandsComponent} from './brands/brands.component';
import {BrandsService} from './brands/brands.service';
#Component({
selector: 'my-app',
template: `
<brands></brands>
`,
directives: [BrandsComponent]
})
export class AppComponent {
}
bootstrap(AppComponent, [HTTP_PROVIDERS, BrandsService]);
My BrandsComponent inject my BrandsService.
Here my service code :
import {Http} from 'angular2/http';
import {Injectable, Inject} from 'angular2/core';
#Injectable()
export class BrandsService{
constructor(public http: Http) {
console.log('Task Service created.', http);
http.get('http://google.fr');
}
getBrands(){
//return this.http.get('./brands.json');
return [];
}
}
In my console, I have the 'Task service created' log, but any ajax request is going.
I can't tell you what I've tried, cause I change my code about a billion times.
Thank for your help !
#Edit :
Here my BrandsComponent code :
import {Component} from 'angular2/core';
import {Brand} from './brand.interface';
import {BrandsService} from './brands.service';
import {ModelsComponent} from './../models/models.component';
#Component({
selector: 'brands',
templateUrl: 'templates/brands/list.html',
providers: [BrandsService],
directives: [ModelsComponent]
})
export class BrandsComponent implements OnInit{
public brands;
public selectedBrand : Brand;
constructor(private _brandsService: BrandsService) { }
/*
* Get all brands from brands service
*/
getBrands(){
this.brands = this._brandsService.getBrands();
}
/*
* On component init, get all brands from service
*/
ngOnInit(){
this.getBrands();
}
/*
* Called when li of brand list was clicked
*/
onSelect(brand : Brand){
this.selectedBrand = brand;
}
}
In fact observables are lazy. This means that corresponding HTTP requests aren't sent before attaching some response listeners on them using the subscribe method.
Adding a subscribe method in the constructor of your BrandsService should trigger your HTTP request:
import {Http} from 'angular2/http';
import {Injectable, Inject} from 'angular2/core';
#Injectable()
export class BrandsService{
constructor(public http: Http) {
console.log('Task Service created.', http);
http.get('http://google.fr').subscribe();
}
(...)
}
Hope it helps you,
Thierry