Angular2 - Unresolved Variables - html

Complete noob looking for help,
I've been learning Angular2 and attempting to make a basic app but now its broken!
The component.ts file
import {Component, OnInit} from '#angular/core';
import { Player } from './player.model';
#Component({
selector : 'app-player',
templateUrl : '/player.component.html'
})
export class PlayerComponent implements OnInit {
players: Player[] = [
new Player('Malus', 'Lina', 'lol', 3000)
];
constructor() {}
ngOnInit() {}
}
model.ts
export class Player {
public playerName: string;
public favHero: string;
public heroImage: string;
public mmr: number;
constructor( name: string, favHero: string, heroImage: string, mmr: number) {
this.playerName = name;
this.favHero = favHero;
this.heroImage = heroImage;
this.mmr = mmr;
}
}
lastly where the error is in the HTML
I am trying to use {{ players.playerName }} etc but they are unresolved? I think this is why my app is broken now
apparently, the variables of my array are unresolved?. I don't get it and cant work out why.
Appreciate any help thanks

You are trying to access an object key of an array (players.playerName), which you can't do. You either need to access a particular index players[0].playerName or loop through your players and create a DOM block for each player
<div *ngFor="let player of players">
{{player.playerName}}
</div>

Related

How to use private properties in my html-file?

I am trying to show a list of Animals in my html page with their corresponding name and color.
My frontend gets the data from a spring backend that returns a list of Animals.
And I stumbled upon 2 questions that I have:
1)
I made the name and color properties private in the Animal class.
Code of the animal class:
interface AnimalJson {
name: string;
color: string;
}
export class Animal {
constructor(private name: string, private color: string) {}
static fromJSON(json: AnimalJson): Animal {
const a = new Animal(json.name, json.color);
return a;
}
}
code of my animal-component:
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
import { DataServiceService } from '../data-service.service';
import { Animal } from '../models/Animal';
#Component({
selector: 'app-animal',
templateUrl: './animal.component.html',
styleUrls: ['./animal.component.css'],
})
export class AnimalComponent implements OnInit {
public animals: Observable<Animal[]>;
constructor(private dataService: DataServiceService) {
this.animals = new Observable<Animal[]>();
}
ngOnInit(): void {
this.animals = this.dataService.getAnimals();
}
}
code of the service:
#Injectable({
providedIn: 'root',
})
export class DataServiceService {
constructor(private http: HttpClient) {}
getAnimals(): Observable<Animal[]> {
return this.http
.get<Animal[]>('http://localhost:8080/animals')
.pipe(map((animals: any[]): Animal[] => animals.map(Animal.fromJSON)));
}
}
code of the html-page:
<div *ngFor="let animal of animals | async">
<p>{{ animal.name }}</p>
</div>
Now when I try to get the animal.name, it gives an error that the name is private so I cant use it in my html page. How should I fix this? Should I just make it public? Or is there something I forget?
2)
Is this how you work with observables? Or am I using my observables in a wrong way?
Using the http get methode to get the observable and than call it in my animal-component and use async in my html-file to go over all the values in it?
If you use private then it should not be used in the html, am not sure why you are using a class for initializing the array. Just use a simple map statement.
If you are going to show it in the HTML then don't make the property private.
So the changes are.
interface Animal {
name: string;
color: string;
}
Service will be.
#Injectable({
providedIn: 'root',
})
export class DataServiceService {
constructor(private http: HttpClient) {}
getAnimals(): Observable<Animal[]> {
return this.http
.get<Animal[]>('http://localhost:8080/animals')
.pipe(map((animals: any[]): Animal[] => animals.map((item: Animal) => ({name: item.name, color: item.color}))));
}
}
Note: class can also be used as an interface, so when using animal you defined the properties as private, so you are unable to use in the HTML.

ERROR NullInjectorError: R3InjectorError(AppModule)[Number -> Number -> Number]: NullInjectorError: No provider for Number

I'm not sure what is going on here. The application was working fine then I came in to work on it and kept getting this error. My Compiler doesn't show errors, and I do not have any nulls in the code (or at least I don't think i do.) Here is what the console looks like:
Any help would be appreciated here. I'm trying to learn TS, Angular, and RxJS so still a noob. lol
We inject dependencies using the constructor generally.
Read this: https://angular.io/guide/dependency-injection
Your code should be
//...
public Bug_Number: number,
public Bug_Name: string,
public Created_By: string,
public Detail: string,
public Date_Started: number,
public Date_Completed: number,
public Date_Days_Worked: number,
public Completed: string
constructor() { }
//...
We usually inject a service/class by marking them as injectable using the #Injectable decorator
Example: Bug Service
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root',
})
export class BugService {
constructor() { }
// getBug()
// getBugById(bugId: number)
// addBug(Bug bug)
}
And inject it in component like,
constructor(bugService: BugService) { }
and access them anywhere in page like this.bugService.getBugs()

Angular 6 AOT issue - can't pass function as argument

I'm unable to pass a function as an argument to a base class from a child class when trying to build using ng build --prod. The build works fine without the --prod flag, which looks to indicate an issue with AOT. The error I get is:
ERROR in : Can't resolve all parameters for AppGridComponent in
/src/app/components/core/shared/app-grid.component.ts: (?, [object
Object])
I found this SO thread which has several different answers for solutions, but I haven't been able to get any to work. It appears that AOT wants to inject this argument as a service and can't resolve (which I don't need since I am passing the function as a value from the child).
Base Class - app-grid.component.ts
import { Component, OnDestroy, OnInit } from '#angular/core';
import { GlobalsService } from '../../../services/globals.service';
#Component({})
export class AppGridComponent implements OnInit, OnDestroy {
constructor(protected loadDataCallBack: any, protected globalsService: GlobalsService) {
}
ngOnInit() {
this.init();
}
// get api data
public init() {
this.loadDataCallBack()
.subscribe(result => result);
}
Child class - rules.component.ts
const loadApiData = function() {
return this.productRuleService.get();
};
#Component({
selector: 'app-rules',
template: `<div class="grid-wrapper">Data here...</div>`
})
export class RulesComponent extends AppGridComponent implements OnInit, OnDestroy {
constructor(protected globalsService: GlobalsService, protected productRuleService: ProductRelationshipRuleService) {
super(loadApiData, globalsService);
}
Any suggestions on how to get this to build would be appreciated.
I was able to get this to work by creating a class that extends Function and then using this class as the provider in the component.
// Base Class - app-grid.component.ts
export class LoadDataCallBack extends Function {
}
#Component({
template: '',
providers: [{provide: LoadDataCallBack, useValue: () => {}}]
})
This ultimately satisfied the compiler and it is able to identify the type to inject into the first argument: loadDataCallBack.

Angular 2 : Modified import Model don't update in view

I changed my model to fit requirements for uusing entityframework but the view related to this model can't use the new model wich is :
export class CV {
public Id: number;
public UserId: string;
public Context: string;
public Competences: Array<Competence>;
public Expertises: Array<Expertise>;
public Formations: Array<Formation>;
public Missions: Array<Mission>;
}
The model before changing is :
export class CV {
public id: number;
public userId: string;
public context: string;
public competences: Array<Competence>;
public expertises: Array<Expertise>;
public formations: Array<Formation>;
public missions: Array<Mission>;
Example, I show an object from my console :
Screenshot from my chrome console
So I want to update the model in my view but I don't know how. I tried different things like ChangeDetectorRef but nothing is working.
Thank you in advance for your help !
I'd suggest you'd use Interfaces instead of classes, since at looking at the model, you don't need a class. So change it to an interface instead:
export interface CV {
Id: number;
UserId: string;
Context: string;
Competences: Array<Competence>;
Expertises: Array<Expertise>;
Formations: Array<Formation>;
Missions: Array<Mission>;
}
Since your property names do not match the data you are receiving, you need to map the values and set the data with the properties that match your model.
So your service function should look something like this:
getData() {
return this.http.get('the url')
.map(res => res.json().map((x:any) =>
Object.assign({Id:x.id,UserId:x.userId,/* Rest of the properties here */})))
}
And then in your component you subscribe normally and assign the incoming data as an array of type CV.

Getting data from Web API in Angular 2

Thanks to tutorial on Angular 2 page called "Tour of Heroes", I managed to create a simple Angular 2 application. Then using Enitity Framework I decided to create a database. And fill the list of heroes from it (not from the file). I created Web Api Controller and added simple get method.
Then in hero.service.ts I call this method in order to get list of heroes. When I lunch my app it shows the list of heroes but without any values (name and id are blank). When I debug my application in the browser I can see this.heroes object in heroes.component.ts contains right data. So what is going on? Why aren't name and id showing?
hero.service.ts:
import {Injectable} from 'angular2/core';
import {HEROES} from './mock-heroes';
import {Hero} from './hero';
import {Http, Response} from 'angular2/http';
import 'rxjs/Rx';
import {Observable} from 'rxjs/Observable';
#Injectable()
export class HeroService {
public values: any;
constructor(public _http: Http) { }
private _heroesUrl = 'http://localhost:61553/api/values'; // URL to web api
getHeroes() {
return this._http.get(this._heroesUrl)
.map(res => <Hero[]>res.json())
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
heroes.component.ts:
import {Component, OnInit} from 'angular2/core';
import {Router} from 'angular2/router';
import {Hero} from './hero';
import {HeroDetailComponent} from './hero-detail.component';
import {HeroService} from './hero.service';
#Component({
selector: 'my-heroes',
templateUrl: 'templates/heroes.component.html',
styleUrls: ['styles/heroes-component.css'],
directives: [HeroDetailComponent]
})
export class HeroesComponent implements OnInit {
constructor(private _heroservice: HeroService, private _router: Router) { }
errorMessage: string;
public heroes: Hero[];
selectedHero: Hero;
ngOnInit() {
this.getHeroes();
}
onSelect(hero: Hero)
{
this.selectedHero = hero;
}
getHeroes() {
this._heroservice.getHeroes()
.subscribe(
value => this.heroes = value,
error => this.errorMessage = <any>error);
}
gotoDetail() {
this._router.navigate(['HeroDetail', { id: this.selectedHero.Id }]);
}
}
heroes.component.html:
<h2>My Heroes</h2>
<ul class="heroes">
<li *ngFor="#hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)">
<span class="badge">{{hero.Id}}</span> {{hero.Name}}
</li>
</ul>
<div *ngIf="selectedHero">
<h2>
{{selectedHero.Name | uppercase}} is my hero
</h2>
<button (click)="gotoDetail()">View Details</button>
</div>
hero.ts:
export class Hero {
Id: number;
Name: string;
}
Web API Controller:
using Microsoft.AspNet.Mvc;
using System.Collections.Generic;
using TestApplicationDataAccess;
using TestApplicationDataAccess.Entities;
namespace WebApplication2.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly TestAppDbContext _dbContext;
public ValuesController(TestAppDbContext dbContext)
{
_dbContext = dbContext;
}
// GET: api/values
[HttpGet]
public IEnumerable<Hero> Get()
{
return _dbContext.Heroes;
}
}
}
Hero Entity:
namespace TestApplicationDataAccess.Entities
{
public class Hero
{
public int Id { get; set; }
public string Name { get; set; }
}
}
JSON retrieved from WEB API Controller:
[{"Id":1,"Name":"Superman"}]
getHeroes() {
this._heroservice.getHeroes()
.subscribe(res=>{
this.heroes=res;
console.log(this.heroes); // make sure you get data here.
},
(err)=>console.log(err),
()=>console.log("Done")
);
}
Try this :public heroes: Hero[] = [];
In my case the issue was related to the visual studio 2015 bug. There was nothing wrong with the code itself. Sometimes changes made in vs were not refreshed in the browser. Updating vs to the latest version helped.