I'm trying to get spotify API from current user's playlists
I have it in my console but I tried to put it into html and i'm getting this error:
ERROR Error: Cannot find a differ supporting object '[object Object]'
of type 'object'. NgFor only supports binding to Iterables such as
Arrays.
at NgForOf.ngDoCheck (common.js:4841)
at checkAndUpdateDirectiveInline (core.js:31913)
at checkAndUpdateNodeInline (core.js:44367)
at checkAndUpdateNode (core.js:44306)
at debugCheckAndUpdateNode (core.js:45328)
at debugCheckDirectivesFn (core.js:45271)
at Object.eval [as updateDirectives] (PlaylistsComponent.html:2)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:45259)
at checkAndUpdateView (core.js:44271)
at callViewAction (core.js:44637)
Here's my user.service.ts:
public getUserPlaylists(): Observable<any> {
const endpoint = environment.spotifyApi.host + "me/playlists";
const httpOptions = {
headers: new HttpHeaders({
Authorization: `Bearer ${this.accessToken}`,
}),
};
return this.http.get(endpoint, httpOptions);
}
Here's my playlists.component.ts:
playlists: any;
constructor(private router: Router, private userService: UserService) {}
ngOnInit() {
this.getPlaylists();
}
getPlaylists() {
let observable = this.userService.getUserPlaylists();
observable.subscribe((data) => {
this.playlists = data;
console.log(this.playlists);
});
}
and here is my html:
<div class="playlists text-center">
<div class="test" *ngFor="let playlist of playlists">
{{playlist.name}}
</div>
</div>
Update console from browser:
Object
href: "https://api.spotify.com/v1/users/12164174667/playlists?offset=0&limit=20"
items: Array(2)
0: {collaborative: false, description: "", external_urls: {…}, href: "https://api.spotify.com/v1/playlists/0tNJ7TiGOqqbiFratEY8WD", id: "0tNJ7TiGOqqbiFratEY8WD", …}
1: {collaborative: false, description: "Songs I'm currrently listening to; updated every 2 weeks.", external_urls: {…}, href: "https://api.spotify.com/v1/playlists/24G8qVxmH4Sg6WfsaRAumW", id: "24G8qVxmH4Sg6WfsaRAumW", …}
length: 2
__proto__: Array(0)
limit: 20
next: null
offset: 0
previous: null
total: 2
__proto__: Object
As you can clearly see in the logs that ngFor expects Iterables. Instead of assigning full object just assign items
Upate your method like this:
getPlaylists() {
let observable = this.userService.getUserPlaylists();
observable.subscribe((data) => {
this.playlists = data.items;
console.log(this.playlists);
});
}
I went through Spotify API and found what it returns in playlist object. in external_urls node you can get required playlist url. then you can iterate this.playlists.
getPlaylists() {
let observable = this.userService.getUserPlaylists();
observable.subscribe((res) => {
this.playlists = res.external_urls;
console.log(this.playlists);
});
}
Related
I have this object defined based on the elements that I retrieved from my HTTP request. The problem is that I'm trying to access these elements in the Object Array, I'm getting this 'Cannot read property of undefined' error. Can you please advise where do I go wrong? Because I think I'm accessing it the right way.
console image
app.module.ts
export class AppComponent {
...
public blockchain;
constructor(private blockchainService: BlockchainService) {
this.blockchain = blockchainService.blockchainInstance;
}
ngOnInit() {
}
...
}
Object class
export class BlockchainDB {
id?: any;
provider?: string;
recipient?: string;
rxInfo?: string;
timestamp?: string;
published?: boolean;
}
Code
export class BlockchainService {
...
currentBlockchain: BlockchainDB = {
rxInfo: '',
provider: '',
recipient: '',
timestamp: '',
published: false
};
...
public sampledata = [];
public arraydata3: BlockchainDB [];
constructor(private blockchainService: BlockchainDBService) {
this.retrieveBlockchain();
this.createChainData();
console.log(this.arraydata3);
console.log(this.arraydata3[0].rxInfo);
}
createChainData() {
this.getBlockchain('1', 0);
this.getBlockchain('2', 1);
}
getBlockchain(id: string, seqnr: number): void {
console.log(id);
this.blockchainService.get(id)
.subscribe(
data => {
this.currentBlockchain = data;
this.arraydata3.push(this.currentBlockchain);
console.log(data);
},
error => {
console.log(error);
});
}
Debug Logs
1
blockchain.service.ts:78 2
blockchain.service.ts:50 Array(2)0: {id: 1, provider: "steve", recipient: "me", rxInfo: "{brandname:neozep,genericname:paracetamol,prescribedDosageCount:20}", timestamp: "1630747314781", …}1: {id: 2, provider: "qwerty", recipient: "trewq", rxInfo: "{brandname:biogesic,genericname:paracetamol,prescribedDosageCount:20}", timestamp: "1730747314781", …}length: 2[[Prototype]]: Array(0)
core.js:6479 ERROR TypeError: Cannot read property 'rxInfo' of undefined
at new BlockchainService (blockchain.service.ts:51)
at Object.BlockchainService_Factory [as factory] (blockchain.service.ts:122)
at R3Injector.hydrate (core.js:11438)
at R3Injector.get (core.js:11257)
at NgModuleRef$1.get (core.js:25332)`enter code here`
at Object.get (core.js:25046)
at lookupTokenUsingModuleInjector (core.js:3342)
at getOrCreateInjectable (core.js:3454)
at Module.ɵɵdirectiveInject (core.js:14737)
at NodeInjectorFactory.AppComponent_Factory [as factory] (app.component.ts:9)
defaultErrorLogger # core.js:6479
main.ts:12 TypeError: Cannot read property 'rxInfo' of undefined
at new BlockchainService (blockchain.service.ts:51)
at Object.BlockchainService_Factory [as factory] (blockchain.service.ts:122)
at R3Injector.hydrate (core.js:11438)
at R3Injector.get (core.js:11257)
at NgModuleRef$1.get (core.js:25332)
at Object.get (core.js:25046)
at lookupTokenUsingModuleInjector (core.js:3342)
at getOrCreateInjectable (core.js:3454)
at Module.ɵɵdirectiveInject (core.js:14737)
at NodeInjectorFactory.AppComponent_Factory [as factory] (app.component.ts:9)
The code inside the subscription is executed when the api call is completed which is asynchronous.
Therefore, "console.log(this.arraydata3[0].rxInfo);" is executed before "this.arraydata3.push(this.currentBlockchain);"
You can handle this asynchronous behvior by following this solution
I'm have a NextJS application which I've just done two things on. 1) I've upgraded to the latest version of NextJS (9.0.1), and 2) I've copied files (package.json, pages/, components/ etc.) from my project root to a new src/app/ sub-directory in my project root.
Pages which don't use dynamic routing load perfectly fine, but there's an issue when I need to use the router object from Next. My original code (which was working fine before the above two things):
import { useRouter } from "next/router";
import { mockConsts } from "../../public/mockConsts";
const router = useRouter();
const userObj = mockConsts.users.filter(
user => user.username === router.query.username
)[0];
This gives me the error: TypeError: Cannot read property 'query' of null.
If I wrap a try/catch around it:
let userObj = mockConsts.users[0];
try {
const router = useRouter();
userObj = mockConsts.users.filter(
user => user.username === router.query.username
)[0];
console.log("QUERY", router.query);
} catch (e) {
console.log("ERR", e);
}
the client and server return two different errors. The server still returns the above error (TypeError: Cannot read property 'query' of null).
The client returns (via console.log):
QUERY Object { } [username].tsx:16
Warning: Did not expect server HTML to contain a <div> in <div>. index.js:1
QUERY Object { username: "dog" } [username].tsx:16
With the try/catch I can get the code to work as intended, but only after it has displayed mockConsts.users[0] (The first "QUERY" in console log is blank). Obviously this isn't ideal.
EDIT:
I have rewritten the try/catch so the functionality is as I'd expect:
try {
router = useRouter();
console.log("ROUTER", router);
userObj = mockConsts.users.filter(
user => user.username === router!.query.username
)[0];
} catch (e) {
console.log("ERR", e);
}
ROUTER is logged twice:
ROUTER
Object { pathname: "/user/[username]", route: "/user/[username]", query: {}, asPath: "/user/[username]", components: {…}, events: {…}, push: field(), replace: field(), reload: field(), back: field()
, … }
[username].tsx:23
ROUTER
Object { pathname: "/user/[username]", route: "/user/[username]", query: {…}, asPath: "/user/dog", components: {…}, events: {…}, push: field(), replace: field(), reload: field(), back: field(), … }
[username].tsx:23
As you can see, the query attribute has values in it now, and the asPath attribute is different.
I'm trying to create a variable to set one of the properties of an object obtained by the get method.
When I give console in subscribe I retrieve the value of the array, but I'm having difficulty (i'm beginner) to set only one of the properties of the objects in that array.
Component:
this.mainService.getGraph()
.subscribe(res => {
console.log(res)
this.name = res[''].map(res => res.name)
console.log(this.name)
Console.log:
(5) […]
0: Object { name: "Carlos", lastname: "Moura", participation: 5 }
1: Object { name: "Fernanda", lastname: "Oliveira", participation: 15 }
2: Object { name: "Hugo", lastname: "Silva", participation: 20 }
3: Object { name: "Eliza", lastname: "Souza", participation: 20 }
4: Object { name: "Anderson", lastname: "Santos", participation: 40 }
length: 5
<prototype>: Array []
main.component.ts:26:6
ERROR TypeError: "res[''] is undefined"
ngOnInit main.component.ts:27
RxJS 13
Angular 8
You are redefining res in your passed in function to map.
Use a plural of name to names, you want a string array so the plural is more appropriate and conveys what the field contains.
Do not try to access a non existent field or index on res, you had res[''] which is not correct.
I put the call in ngOnInit, it might be located elsewhere but this allowed me to define the assigned variable member above it.
names: string[];
ngOnInit() {
this.mainService.getGraph()
.subscribe(res => {
console.log(res);
this.names = res.map(_ => _.name);
console.log(this.names);
}
From the comments:
...the IDE says property 'map' doesnt exist on type 'Object'. would it just be a bug
About your service. Make sure the signature is correct on the return type. Here is an example, you can also define an interface and return that instead of {name:string} (but keep the [] which denotes there is an array being returned).
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
export class MainService {
constructor(private readonly http: HttpClient){}
getGraph() : Observable<{name: string}[]> {
return this.http.get<{name: string}[]>('/some/url');
}
}
Just use res.map(res => res.name). instead of res[''].map(res => res.name). In your case you are trying to access property with key equal to empty string inside of your object, and it doesn't exist
You can do it directly in the http get Method
this.http.get(url).pipe(
map(res => {
res['newProperty'] = 'value';
return res;
})
);
Even if you want just call back just one property
this.http.get(url).pipe(
map(res => {
return res.name;
})
);
i created a provider in my ionic project to retrieve the user object from the storage and heres my code
import { Injectable } from '#angular/core';
import { Storage } from '#ionic/storage';
#Injectable()
export class ApiProvider {
public user: any;
constructor(
public storage: Storage
) {}
getStoredUser(){
this.storage.get('user').then(
data => {
this.user = data;
console.log(data);
}
);
return this.user;
}
when i console log the user object from the getStoredUser() function,
this is what i get
{
authcode: "USR_65267H4390"
church_id: 2
email: "test#gmail.com"
fullname: ""An**a A***e""
id: 55
phone: "08*****7"
skills: "Football, chess, scrabble"
}
the json data logs properly, but then when i try to do this on a different component
export class HomePage {
obj: any;
userObj:any = {
name:'',
email:'',
phone:'',
skills:'',
unit:'',
church_id:2 //hardcoded on every request...
};
constructor(
public navCtrl: NavController,
public api: ApiProvider,
public storage: Storage
) {}
ngOnInit():void{
this.obj = this.api.getStoredUser();
//console.log(this.obj) - outputs the object above, no errors..
//if(this.obj.length < 1) - gives me error too.. i've tried everything
if(this.obj !== null){ //------------ this line gives me error.
this.userObj = {
name: this.obj.fullname, // ------- this property gives me error.
email: this.obj.email,
phone: this.obj.phone,
skills: this.obj.skills,
unit:'',
church_id: this.obj.church_id
}
} else{
// do something else.
}
}
This is the error i get when i try to read fullname...
" Uncaught(in promise): TypeError: Cannot read property
'fullname' of undefined TypeError: at Homepage.webpack.jsonp
and this is the error i get when i try to read the length of this.obj
" Uncaught(in promise): TypeError: Cannot read property
'length' of undefined TypeError: at Homepage.webpack.jsonp...
i have tried everything and i dont know what to do.. the json object is constructed properly, i need help.
the method getStoredUser returns a promise and you are trying to access it's value immediately.
You should access the return object after the promise is resolved using the then method:
this.api.getStoredUser().then(obj => {
this.userObj = {
name: obj.fullname, // ------- this property gives me error.
email: obj.email,
phone: obj.phone,
skills: obj.skills,
unit:'',
church_id: obj.church_id
}
});
Or use async\await if you are ES7 compatible:
this.obj = await this.api.getStoredUser();
//if(this.obj.length < 1) - gives me error too.. i've tried everything
if(this.obj !== null){ //------------ this line gives me error.
this.userObj = {
name: this.obj.fullname, // ------- this property gives me error.
email: this.obj.email,
phone: this.obj.phone,
skills: this.obj.skills,
unit:'',
church_id: this.obj.church_id
}
}
I need to add PipeTransform that serach for substring in array of objects property. I'm using lodash when the filter is by name it will be fine and works like a charm. but when i change name property to another, like title. its return:
Cannot read property 'indexOf' of null
my pipe code:
import * as _ from 'lodash';
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'dataFilterTitle'
})
export class DataFilterPipeByTitle implements PipeTransform {
transform(array: any[], query: string): any {
debugger;
if (query) {
return _.filter(array, row=>row.title.indexOf(query) > -1);
}
return array;
}
}
error:
ERROR TypeError: Cannot read property 'indexOf' of null
at datafilterpipebyTitle.ts?071a*:12
at arrayFilter (lodash.js:603)
at Function.filter (lodash.js:9190)
at DataFilterPipeByTitle.webpackHotUpdate.../../../../../src/app/plugins/datatable/datafilterpipebyTitle.ts.DataFilterPipeByTitle.transform (datafilterpipebyTitle.ts?071a*:12)
at checkAndUpdatePureExpressionInline (core.es5.js:11350)
at checkAndUpdateNodeInline (core.es5.js:12244)
at checkAndUpdateNode (core.es5.js:12177)
at debugCheckAndUpdateNode (core.es5.js:12880)
at debugCheckDirectivesFn (core.es5.js:12821)
at Object.eval [as updateDirectives] (ListComponent.html:17)
Error clearly states that Cannot read property 'indexOf' of null, which means that title property could be null sometimes. So before doing indexOf check title exists or not.
transform(array: any[], query: string): any {
if (query) {
return _.filter(array, row=> row.title && row.title.indexOf(query) > -1);
}
return array;
}