I am getting an HTTP response and need to display the length of an array (the array is called 'Notifications'). I need to display "10" which is the length, but this is what I'm now displaying: NaN
The error shown in my console: ERROR Error: InvalidPipeArgument: '10' for pipe 'AsyncPipe'
Please find my html code below:
<a href="#" class="dropdown-toggle dk" data-toggle="dropdown">
<i class="fa fa-bell"></i>
<span class="badge badge-sm up bg-danger m-l-n-sm count" id="notcountbadge">{{cfNotificationsLength | async}}</span>
</a>
and my ts code below:
public cfNotificationsLength: Observable<number>;
public cfNotifications: any;
ngOnInit() {
console.log("HeaderBarComponent loaded successfuly!");
this.referenceDataService.fetchNotifications(token)
.subscribe((x: any) => {
this.cfNotifications = x.Notifications;
this.cfNotificationsLength = x.Notifications.length;
console.log("cfNotifications", this.cfNotifications);
console.log("cfNotificationsLength", this.cfNotificationsLength);
},
(err: any) => console.log("error", err)
);
}
and my service below:
constructor(private http: HttpClient) {
super(null);
}
public fetchNotifications(token: string): Observable<any> {
//console.log("token in fetchNotifications", token);
this.BASE_URL = window.location.origin;
let fetchcfNotificationsCallResult = this.http
.get(`${this.BASE_URL}` + `/` + token + `/api/Notifications`)
.pipe(
map((response: any) => <any>response)
);
return fetchcfNotificationsCallResult;
}
Thank you very much in advance.
The async pipe is used for Observables and is therefore not needed if you set the property by subscribing to the Observable. Just remove the pipe and it should work as expected.
Edit
Async pipe may be the way, try this:
public cfNotifications: Observable<any>;
ngOnInit() {
console.log("HeaderBarComponent loaded successfuly!");
this.cfNotifications = this.referenceDataService
.fetchNotifications(token)
.map((x: any) => x.Notifications);
}
With the following html:
<span class="badge badge-sm up bg-danger m-l-n-sm count" id="notcountbadge">
{{(cfNotifications | async)?.length}}
</span>
Related
Error trying to diff '[object Object]'. Only arrays and iterables are allowed
I am getting the following error
Error: Error trying to diff '[object Object]'. Only arrays and
iterables are allowed
I am consuming a JSON response and trying to display it in the UI in a ComboBox. please find the attached code and let me know what the error is in the code I made
here are the errors when I receive and the data when I do console.log
model.ts
export class FamilleProblem {
familleId!: number;
familleLibelle!: string;
}
service.ts
export class DeclarProblemService {
apiUrlFamille: string = 'https://www.mytds.fr/webservices_test/ws/gig/getFamille';
apiUrlType = 'https://www.mytds.fr/webservices_test/ws/gig/';
familleProblem!: Observable<FamilleProblem[]>;
currentUser!: AuthLoginInfo;
currentParc!: GestionParc;
familleId = null;
constructor(private http: HttpClient,
private tokenService: TokenStorageService,
private gestionParc: GestionParcService) { }
getFamille(): Observable<FamilleProblem[]>{
this.currentUser = this.tokenService.getUser();
let IdxUser = this.currentUser.userId;
let IdUser: string= '' + IdxUser;
this.currentParc = this.tokenService.getParc();
let IdxTypeMat = this.currentParc.materielIdxTypeMat;
let IdTypeMat: string= '' + IdxTypeMat;
let httpOptions = new HttpHeaders({'Content-Type': 'application/json',
'accept': 'application/json',
'LoginUser': IdUser,
'IdxTypeMat': IdTypeMat})
return this.http.get<FamilleProblem[]>(this.apiUrlFamille, {headers: httpOptions});
}
component.ts
export class DeclarProblemComponent implements OnInit {
currentUser = new AuthLoginInfo();
parcs!: GestionParc[];
materielCode!: number;
matrielImmat!: string;
mode!: number;
familleListe: FamilleProblem[] = [];
isLoggedIn= false;
errorMessage: any;
typeProblem: TypeProblem[] = [];
familleId!: number;
constructor(private router: Router,
private gestionParcService: GestionParcService,
private declarProblem: DeclarProblemService,
private tokenService: TokenStorageService) { }
ngOnInit(): void {
this.declareProbleme();
}
declareProbleme(){
this.declarProblem.getFamille().subscribe({
next: (familleListe: any) => {
//this.tokenService.saveToken(data.accessToken);
this.familleListe = familleListe;
//this.familleListe = [];
console.log(this.familleListe);
//this.familleListe = Array.from(Object.values(res.data));
this.isLoggedIn = true;
},
error: err => {
this.errorMessage = err.error.message;
}
});
}
template.html
<div class="row">
<label class="col-sm-4 col--form-label">Problème constaté :</label>
<div class="col-sm-8">
<select class="form-select" id="familleId" name="familleId" >
<option *ngFor="let famille of familleListe [value]="famille.familleId" >
{{famille.familleLibelle}}
</option>
</select>
</div>
</div>
finally the problem is that I used a our name for iterated and not the one of the server response is an object, but not an array.
Service.ts
getFamille(): Observable<FamilleProblem[]>{
let httpOptions = new HttpHeaders({'Content-Type': 'application/json',
'accept': 'application/json'
})
return this.http.get<{listeDesFamilles:FamilleProblem[]}>(this.apiUrlFamille, {headers: httpOptions}).pipe(
map(listeDesFamilles => listeDesFamilles.listeDesFamilles)
);
I am using Nativescript with Angular and have code written that succesfully calls an onQueryEvent from the nativescript-firebase-plugin for data set upon first building the application. However after following a route to a second component containing the exact same onQueryEvent the data succeeds to retreive a complete list but skips the onQueryEvent.
In all honesty I don't know best practices for queries in any situation let alone this one, so I hope it is just a matter of manipulating how I call the onQueryEvent.
I believe the problem to be in the firebase.query inside the getMyTransactionList() function of the firebase.service.ts file.
the overview.component.html page has a transaction | async RadListView that successfully filters upon running tns run android. Then clicking any link directing to the deal-summary.component.html page where the function is re-iterated refuses to query by the static storage variable set in the firebase.service
Here is my code:
firebase.service.ts
export class FirebaseService {
private _allItems: Array<any> = [];
items: BehaviorSubject<Array<any>> = new BehaviorSubject([]);
public storage: any = '-KomUSGcX-j6qQmY4Wrh'; // set statically to test different routes
constructor(
private ngZone: NgZone,
){}
// fetch data
getMyDealList(): Observable<any> {
return new Observable((observer: any) => {
let path = `deals/${BackendService.token}`;
let onValueEvent = (snapshot: any) => {
this.ngZone.run(() => {
let results = this.handleSnapshot(snapshot.value);
observer.next(results);
});
};
firebase.addValueEventListener(onValueEvent, `/${path}`);
}).share();
}
getMyTransactionList(): Observable<any> {
return new Observable((observer: any) => {
let path = `transactions/${BackendService.token}`;
// this is a merge of jen loopers giftler code combined with nativescrip-firebase-plugins standard onQueryEvent. It works on the first load but routing to a second instance of the same function retrieves all the data without queryEvent
let onQueryEvent = (snapshot: any) => {
this.ngZone.run(() => {
let results = this.handleSnapshot(snapshot.value);
observer.next(results);
});
};
firebase.query(
onQueryEvent,
`/transactions/${BackendService.token}`,
{
singleEvent: true,
orderBy: {
type: firebase.QueryOrderByType.CHILD,
value: 'dealId' // mandatory when type is 'child'
},
range:
{
type: firebase.QueryRangeType.EQUAL_TO,
value: `${this.storage}` // this calls a static variable for testing consistency
}
,
}
);
firebase.addValueEventListener(onQueryEvent, `/${path}`);
console.log("transaction Listener added");
}).share();
}
handleSnapshot(data: any) {
//empty array, then refill and filter
this._allItems = [];
if (data) {
for (let id in data) {
let result = (<any>Object).assign({id: id}, data[id]);
this._allItems.push(result);
}
this.publishUpdates();
}
return this._allItems;
}
publishUpdates() {
// here, we sort must emit a *new* value (immutability!)
this._allItems.sort(function(a, b){
if(a.date < b.date) return -1;
if(a.date > b.date) return 1;
return 0;
})
this.items.next([...this._allItems]);
}
}
app.component.ts
<page-router-outlet></page-router-outlet>
overview.component.ts
export class OverviewComponent implements OnInit {
public deals: Observable<any>;
public transactions: Observable<any>;
constructor(private router: Router,
private firebaseS: FirebaseService,
){ }
ngOnInit() {
this.deals = <any>this.firebaseS.getMyDealList();
this.transactions = <any>this.firebaseS.getMyTransactionList();
}
viewDealSumm(id){
this.router.navigate(['dashboard/deal-summary', id]);
}
}
overview.component.html
<RadListView [items]="deals | async ">
<ng-template tkListItemTemplate let-item="item">
<StackLayout (tap)="viewDealSumm(item.id)">
<Label [text]="item.dealName"></Label>
</StackLayout>
</ng-template>
</ListViewGridLayout>
</RadListView>
<RadListView [items]="transactions | async " >
<ng-template tkListItemTemplate let-item="item">
<GridLayout>
<Label [text]="item.transName"></Label>
</GridLayout>
</ng-template>
</RadListView>
deal-summary.component.ts
export class DealSummaryComponent implements OnInit {
public transactions: Observable<any>;
constructor(
private firebaseS: FirebaseService,
){ }
ngOnInit() {
this.transactions = <any>this.firebaseS.getMyTransactionList();
}
deal-summary.component.html
<RadListView [items]="transactions | async " >
<ng-template tkListItemTemplate let-item="item">
<GridLayout >
<Label col="1" [text]="item.transName"></Label>
</GridLayout>
</ng-template>
</RadListView>
I am not sure if I am confused, is it true that I should leave the job of getting data from database for controller and processing the data for vue? Or is this the best practice or something?
Here I am trying to get the subcat from my subcategories table, not error on devtool but subcats is not being set. Please help or feel free to suggest a better practice. Thanks!
Item-sorting-list.vue
<template>
<div>
<div v-show="isActive">
<li v-for="subcat in subcats" class="list-group-item">
<a name="" href="">{{subcategory.name}}</a>
</li>
</div>
</div>
</template>
<script>
export default {
props:[
],
data(){
return {
subcats:[]
}
},
mounted() {
this.getAllSubcat()
},
methods: {
getAllSubcat(){
var vm = this;
vm.$http.get('/getSubcat').then((response)=>{
vm.subcats = response.data.data.subcat.data;
});
}
}
}
</script>
SubcategoryController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Subcategory;
class SubcategoryController extends Controller
{
public function getSubcat()
{
$subcat = Subcategory::Orderby('name')->get();
$response = [
'data' => [
'subcat' => $subcat
]
];
return response()->json($response);
}
}
web.php
Route::get('/getSubcat', 'SubcategoryController#getSubcat');
Thanks for #saurabh that I double check and response.data.data.subcat should be the correct calling. paginate does read the data differently.
I'm having some trouble displaying my data in the browser. To explain my problem I'm using some dummy code. I have some nested objects that are causing my problem. Here I'll display one nested object to showcase my problem.
First of all, I only make http calls for the Car-object. So saveCar acts like updating the car as well, depending on what the user does in the app. All the methods in the service works as they should.
So my service looks something like this:
#Injectable()
export class Service {
constructor(private http: Http) { }
saveCar(car: Car) {
return this.http.post ....
}
getCars(){
return this.http.get...
}
getById(id: string) {
return this.http.get...
}
}
Then I have a Car-class, where the nested object "Brand" comes in to play, Brand then has it's own class, but I'll leave it out.
export class Car {
private brands: Array<Brand>;
constructor(public id: string, public name: string) {
this.brands = new Array<Brand>();
}
public getBrands(): Array<Brand> {
return this.brands;
}
public addBrand(value: Brand): void {
this.brands.push(value);
}
//some other methods.
}
Then I have a list-component that lists all cars, this works as it should!
#Component({
selector: 'car-list',
template: `
<h1>Add Car</h1>
<form (submit)="saveCar()">
<input required [(ngModel)]="name" placeholder="Add car">
</form>
<br>
<table>
<tr *ngFor="let car of cars" >
<td>{{car.name}}</td>
<td><button (click)="goToDetail(car)">Detail</button></td>
</tr>
</table>
`,
})
export class ListComponent implements OnActivate {
id: string
name: string;
cars: Array<Car>
constructor(public _service: Service, public _router: Router) { }
routerOnActivate(): void {
this._service.getCars()
.subscribe(cars => this.cars = cars);
}
saveCar() {
let car = new Car(this.id, this.name)
this._service.saveCar(Car)
.subscribe(car => this.cars.push(car));
this._service.getCars()//
.subscribe(cars => this.cars = cars);
}
goToDetail(car:Car) {
this._router.navigate(['/cardetail', car.id]);
}
}
The problem I have is in the detail-component, where the user gets navigated after clicking a specific car. The routing and retrieving the Car from the db works as it should. That I know, because if I remove all the template except <h1>Car: {{car?.name}}</h1> the name gets printed out fine with the elvis operator.
But my detail-component looks something like this:
#Component({
selector: 'car-detail',
template: `
<h1>Car: {{car?.name}}</h1>
<hr>
<button (click)="addBrand()">Add Brand</button>
<div *ngFor="let brand of car.getBrands(); let i=index">
<h2>Brand {{i+1}}</h2>
</div>
`,
})
export class DetailComponent implements OnActivate {
#Input() car: Car;
constructor(public _service: Service, public _router: Router) { }
routerOnActivate(curr: RouteSegment): void {
let id = curr.getParam('id');
this._service.getById(id)
.subscribe(car => {
this.car = car;
});
}
addBrand() {
this.car.getBrands().push(new Brand());
}
//some other methods
}
So in my detail component I call all methods like: car.someMethod() and further on the nested Brand object like: brand.someMethod() in the template. So the error comes at the call of the method e.g in the template 'cannot get getBrands of undefined' I've tried putting the elvis operator like this: car?.getBrands() It doesn't work. I've tried to wrap the whole thing in a div, both with elvis operator and a <div *ngIf = "car"></div>, doesn't work. Even tried with <template *ngIf="car"></template>, well that doesn't work either....
Edit: my mess-up, wrapping like below, it does "kind of" work, meaning, it gives a new error....
Template:
#Component({
selector: 'car-detail',
template: `
<h1>Car: {{car?.name}}</h1>
<hr>
<button (click)="addBrand()">Add Brand</button>
<div *ngIf="car">
<div *ngFor="let brand of car.getBrands(); let i=index">
<h2>Brand {{i+1}}</h2>
</div>
</div>
You mention <h1>Car: {{car?.name}}</h1> with ? but the full code example has <td>{{car.name}}</td> without ? which will cause an error.
<div *ngFor="let brand of car.getBrands(); let i=index">
also needs a ? to avoid errors when Angular tries to render the view and car is not yet set
<div *ngFor="let brand of car?.getBrands(); let i=index">
I am using Angular 2.0.0-beta.0 and TypeScript 1.7.5
When you type something in the search box and something is found and shown on the screen, then you delete the search input box and you want to show an empty list. It work using this piece of code:
this.searchTermStream.next("makesureyoudontfindanything");
Does anyone has a better cleaner solution without doing a http request?
#Component({
selector: 'contact-search',
template: `
<div class="container">
<div class="form-group">
<label for="inputUser">Search</label>
<input #inputUser (keyup)="search(inputUser.value)">
</div>
<ul>
<li *ngFor="#contact of contactList | async">{{contact.name}}</li>
</ul>
</div>
`
})
export class ContactSearch {
private searchTermStream = new Subject<string>();
private contactList: Observable<Contact[]> = this.searchTermStream
.debounceTime(300)
.distinctUntilChanged()
.switchMap((value: string) => this.contactService.searchContacts(value))
constructor(private contactService: ContactService) {}
search(value: string) {
if (value) {
this.searchTermStream.next(value);
}
else {
this.searchTermStream.next("makesureyoudontfindanything");
}
}
}
You can check if value is empty before calling service:
private contactList: Observable<Contact[]> = this.searchTermStream
.debounceTime(300)
.distinctUntilChanged()
.switchMap((value: string) =>
0 < value.length ? this.contactService.searchContacts(value) : Observable.of([]))
search(value: string) {
this.searchTermStream.next(value);
}