Angular RxJs TypeError "undefined" - node.js

Sorry if this question doesn't make sense, I'm very new to the MEAN stack. I have been trying to get an array from an express middleware to display on an angular frontend. The problem I have been having is even though everything compiles and appears to work I get an error in the console saying "ERROR TypeError: 'this.brackets is undefined'".
This is the code that appears to be the problem
'''
import { Injectable } from "#angular/core";
import { Bracket } from './bracket.model';
import { Subject } from 'rxjs';
import { HttpClient } from '#angular/common/http';
#Injectable({providedIn: 'root'})
private brackets: Bracket[] = [];
private bracketsUpdated = new Subject<Bracket[]>();
constructor(private http: HttpClient) {}
getBracket() {
this.http.get<{message: string, brackets: Bracket[]}>('http://localhost:3000/api/brackets')
.subscribe((bracketData) => {
this.brackets = bracketData.brackets;
this.bracketsUpdated.next([...this.brackets]); // this is the problem line
});
console.log(this.brackets);
}
'''
and this is where the array is coming from
'''
app.use("/api/brackets", (req, res, next)=>{
const bracket= [
{
id: 'alksdfjalskj',
bracketTitle:'bracket from node',
bracketBuyIn: "2",
bracketPlayer1:'name',
bracketPlayer2:'name2',
bracketPlayer3:'name3',
bracketPlayer4:'name4',
bracketPlayer5:'name5',
bracketPlayer6:'name6',
bracketPlayer7:'name7',
bracketPlayer8:'name8'
}
];
console.log(bracket);
res.status(200).json({
message:'Bracket from node',
bracket:bracket
});
});
'''
In vs code it is defined so I'm confused as to why it doesn't work.
EDIT: the bracket referred to is not a naming error. It's referring to an imported model called Bracket

There is a naming error, you have
res.status(200).json({
message:'Bracket from node',
bracket:bracket
});
calling bracket
and in Angular you are using by plural
this.brackets = bracketData.brackets;
bracket(s)
leave either bracket, or brackets and it will work fine

The model you're using in the front-end has nothing to do with the value you receive from the back-end. The model is only there to assert the type of the data you're trying to assign to the variable.
But if you see in the backend
res.status(200).json({
message:'Bracket from node',
bracket:bracket
});
You're clearly assigning the object to a property called bracket, NOT brackets. To be extra sure, the value you receive from the backend is this
{
message:'Bracket from node',
bracket: [{
id: 'alksdfjalskj',
bracketTitle:'bracket from node',
bracketBuyIn: "2",
bracketPlayer1:'name',
bracketPlayer2:'name2',
bracketPlayer3:'name3',
bracketPlayer4:'name4',
bracketPlayer5:'name5',
bracketPlayer6:'name6',
bracketPlayer7:'name7',
bracketPlayer8:'name8'
}]
}
So it's called bracket WITHOUT a s.
Now the front-end part.
this.brackets = bracketData.brackets;
Here the LHS this.brackets for sure abides 100% by the model you've defined. It doesn't jump over any hoops to assign any values that doesn't conform to the model Bracket you've defined. But the RHS bracketData.brackets doesn't care a single percent about your model. It doesn't have to. It comes from the backend, and that's the only thing it abides to.
If you do a console.log(bracketData), you'll see the following
{
message:'Bracket from node',
bracket: [{
id: 'alksdfjalskj',
bracketTitle:'bracket from node',
bracketBuyIn: "2",
bracketPlayer1:'name',
bracketPlayer2:'name2',
bracketPlayer3:'name3',
bracketPlayer4:'name4',
bracketPlayer5:'name5',
bracketPlayer6:'name6',
bracketPlayer7:'name7',
bracketPlayer8:'name8'
}]
}
Now, please take a look again closely. You will never be able to find brackets property. Because you call it bracket in the backend.
So when you try bracketData.brackets there is no data in that property. It might as well be bracketData.magicData for all Javascript cares. It WILL return undefined for undefined properties.

Related

Unable to add event listener to webNavigation.onCompleted

Using the mock function below along with the dev console:
This call will work:
chrome.webNavigation.onCompleted.addListener(processWebNavChange, filtera);
but when I actually pass in my real var filter it throws this error:
Uncaught TypeError: Could not add listener
My actual data looks like this:
{
url: [ {hostContains: ".im88rmbOwZ"} ]
}
function registerWebNavListener() {
var matchers = getUrlMatchers();
var filter = {
url: matchers
};
// test with mock data filtera that actually works
const filtera = {
url:
[
{hostContains: "example.com"},
]
}
if (matchers.length > 0) {
chrome.webNavigation.onCompleted.addListener(processWebNavChange, filtera);
}
}
async function processWebNavChange(data) {
}
Is there something wrong with my data structure that I'm actually using? I don't believe that the filter object I returned is incorrect
}
EDIT:
I added a new
const filterb = {
url: [ {hostContains: ".im88rmbOwZ"} ]
};
and it still fails with that. The single entry {hostContains: ".im88rmbOwZ"}, was the first item returned from getURLMatchers() which I used as an example of real data being returned.
The above comment on the upper-case letters was the cause of the issue. Converting everything to lowercase resolved the problem.
Although, I am not clear as to why that was a problem to begin with. (If there are any hints in the chromium source code event filter handlers, I'd appreciate it if it could be pointed out).

coordinates does not exist in type 'GeometryDataType'

This is a follow up on this question. Now I am using the point object correctly however I get this error:
src/actions/collectGpsData.ts:22:43 - error TS2322: Type '{ type: string; coordinates: any[]; }' is not assignable to type 'GeometryDataType'.
Object literal may only specify known properties, and '"coordinates"' does not exist in type 'GeometryDataType'.
22 place.location = { "type": "Point", "coordinates": [point.latitude, point.longitude] };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 1 error.
import { Action } from "actionhero"; // No GeometryDataType sequelize.js definition
import { Place } from "../models/Place";
export class CollectGpsData extends Action {
constructor() {
super();
this.name = "collectGpsData";
this.description = "Collects GPS data and inserts it into the database";
this.outputExample = {};
this.inputs = {
gpsdata: {
required:true
}
}
}
async run(data) {
var GPSdata = data.params.gpsdata;
GPSdata.forEach(point => {
var place = new Place();
place.deviceimei = point.deviceimei;
place.location = { "type": "Point", "coordinates": [point.latitude, point.longitude] }; //error line
});
}
}
Why am I getting this error? and how can I avoid this error in the future?
I've answered it in your GitHub issue:
Hello #krlicmuhamed!
As #nainkunal933 noted, please include a complete code sample next time. The code you posted does not show how User is defined, for example. Please use a sequelize-sscce.
That said, I took the time to look into what's happening and tried to figure it out.
So, first of all, this issue is typescript-only. The code works fine in runtime. Please include this information directly next time.
I ventured into your stackoverflow question and comments and found this:
https://gist.github.com/krlicmuhamed/199c0bc3560a08718b553f3f609acbcd#file-places-ts-L22
Did you find any documentation instructing you to use this specific type explicitly here? If yes, please post the link so I can fix it. Regardless, I don't blame you because we really should have a set of recommended types to apply on each data type. It turns out GeometryDataType is not the correct type to use in this case.
The solution is to install #types/geojson:
npm install --save-dev #types/geojson
Then, import Geometry:
import type { Geometry } from '#types/geojson'
And then replace that line of code in which you put GeometryDataType with Geometry:
#AllowNull(false)
#Column(DataTypes.GEOMETRY)
- location: GeometryDataType;
+ location: Geometry;

This expression is not callable. Type 'Number' has no call signatures

Hi I'm new in Typescript, I have an object-type variable in which might be different values from different types or nested object. now my question is that how can I define a model for this object to don't face the example error when call different keys?
For example:
export class Controller {
protected static response(res: Response, statusCode: number = 200, data: any, user: string = '', dev: string = '', code: number = 200, result: string = 'success'){
res.status(statusCode).send({
data: data,
message: {
user: '',
dev: ''
},
code: 403,
result: 'Error'
})
}
ERROR: res.status ---> This expression is not callable. Type 'Number' has no call signatures
I was getting this error as well, and realized I'd just forgotten to import Response. Adding an import line solved the problem for me.
import express, {Request, Response} from 'express';
Im NextJS make sure you import the correct Response type.
import { NextApiResponse } from "next";
In case it helps anyone else, I have also seen the same error in cases like this:
const shift = progressWidth * percentage
(this.$refs.expected as Vue).$el.style.left = "100px"
Where percentage is a number. The error occurs because without semicolons the second line is being interpreted as part of the line, like this:
const shift = progressWidth * percentage(this.$refs.expected as Vue).$el.style.left = "100px"
This can be fixed by adding a leading semi-colon:
const shift = progressWidth * percentage
;(this.$refs.expected as Vue).$el.style.left = "100px"
Or even better, rearrange so it isn't needed at all:
const expected = (this.$refs.expected as Vue).$el
const shift = progressWidth * percentage
expected.$el.style.left = "100px"
res.status is a number according to that error message. It doesn't look like that Controller is being called with the correct arguments. console.log(res) in there before calling res.status and check your call site code.
In your contoller just import the response from express or the framework that you use and it will work.
import { Response } from 'express';

Reason for different API responses to request in node and chrome?

So I have a bunch of tracks from Spotify's API and I want their genres (which Spotify doesn't give) so for every track I make an API call to Last FM to get their top tags. Now this works for most tracks, I have to match the track name and artist as strings to last fm:
Here's my problem:
I do like this (pseudo:ish code):
let promises = spotifyTracks
.map(track => rp({url: "http://lastfmapi.com/?artist="+track.artist+"?track="+track.name })
.then(response => {
track.genre = response.genre;
return track;
})
);
return Promise.all(promises).then(() => console.log('done!'));
Using request promise.
Now there a few tracks that currrently baffles me. Like 10 in 600. I get a response from lastFM saying:
{ error: 6, message: 'Track not found', links: [] }
To double check I printed the url used:
"http://lastfmapi.com/?artist="+track.artist+"?track="+track.name
Inside the then-call along with the response.
Now if I copied that url from my output and pasted it right into my chrome-browsers address-bar, the API finds the track!?!??!
the actual example
http://ws.audioscrobbler.com/2.0/?method=track.gettoptags&artist=pugh+rogefeldt&track=små+lätta+moln&autocorrect=1&api_key=141bed9ffc180dd9b07ac93b7e3b56d7&format=json
When it is called in my node-code I get
{ error: 6, message: 'Track not found', links: [] }
when called in the chrome address bar I get
{"toptags": {
"tag":
[
{
"count":100,
"name":"swedish",
"url":"https://www.last.fm/tag/swedish"
},
{
"count":100,
"name":"singer-songwriter",
"url":"https://www.last.fm/tag/singer-songwriter"
},
...
],
"#attr":{
"artist":"Pugh Rogefeldt",
"track":"Små lätta moln"
}
}
}
Anyone got any idea what could be the reason behind this discrepancy?
Chrome address bar will encode the string into URL for you, which will make your actual example become
method=track.gettoptags&artist=pugh+rogefeldt&track=sm%C3%A5+l%C3%A4tta+moln&autocorrect=1&api_key=141bed9ffc180dd9b07ac93b7e3b56d7&format=json
You should do the same thing in your node-code with encodeURIComponent

ember.js update view after PUT using node.js/express

I'm pretty new to ember. I have a basic ember app in place with a CRUD page. I'm having trouble refreshing the view/template of the CRUD page after making a PUT request to a node API using mongoDB.
When I delete a model, the page refreshes fine, but not when I PUT. If I refresh the page, everything is fine and working, but I want the view to refresh as soon as I click the "approve" button I have.
Can someone point me in the right direction of how I should be dealing with this in Ember? Or am I not returning something properly from my API and Ember is doing what it should?
Thanks
Node API PUT:
router.put( '/:id', function( req, res ) {
return Picture.findById( req.params.id, function( err, picture ) {
picture.status = req.body.picture.status;
picture.url = req.body.picture.url;
//...and so on
return picture.save( function( err ) {
if( !err ) { return res.send( picture ); }
return res.send('ERROR');
});
});
});
Model:
App.Picture = DS.Model.extend
authorName: DS.attr('string')
pictureName: DS.attr('string')
url: DS.attr('string')
tags: DS.attr('string')
status: DS.attr('string')
Route:
App.AdminRoute = Ember.Route.extend
model: ->
return #store.find 'picture'
actions:
delete: (picture) ->
picture.destroyRecord() # view updates fine
approve: (picture) ->
picture.set('status', 'verified')
picture.save()
Note - I'm also getting this error in my console that I have no understanding of - I don't remember always getting it though, so I'm not sure how much it's related.
Error: No model was found for 'v'
at new Error (native)
at Error.r (http://localhost:3000/javascripts/libs/ember-1.7.0.js:4:992)
at Ember.Object.extend.modelFor (http://localhost:3000/javascripts/libs/ember-data.js:3:4754)
at t.default.i.extend.extractSingle (http://localhost:3000/javascripts/libs/ember-data.js:1:23642)
at y (http://localhost:3000/javascripts/libs/ember-1.7.0.js:4:30411)
at r [as extractSingle] (http://localhost:3000/javascripts/libs/ember-1.7.0.js:4:28863)
at e.default.Ember.Object.extend.extractSave (http://localhost:3000/javascripts/libs/ember-data.js:1:22390)
at e.default.Ember.Object.extend.extractUpdateRecord (http://localhost:3000/javascripts/libs/ember-data.js:1:22097)
at e.default.Ember.Object.extend.extract (http://localhost:3000/javascripts/libs/ember-data.js:1:21661)
at http://localhost:3000/javascripts/libs/ember-data.js:3:9807
The JSON payload being returned from the server is not in a format suitable for Ember to determine the model type. Ember is expecting something like this:
{
picture: {
"_id":"5428abf33e733af2fc0007ff","authorName":"Ben","pictureName":"Proud Chicken",
"status":"verified","tags":null,"url":"benrlodge.github.io/isotopeSearchFilter/img/four.jpg"
}
}
Since you say it works when you refresh, try comparing this payload with what is returned from the GET. The PUT response should be similar.
Refer to this Ember guide: http://emberjs.com/guides/models/connecting-to-an-http-server/#toc_json-conventions
To tweak the payload and (for example) remove the offending property, you can do this:
App.PictureSerializer = DS.RESTSerializer.extend({
normalizePayload: function(payload) {
if (payload['__v']) {
delete payload['__v'];
}
return this._super(payload);
}
});
This example is for PictureSerializer, but if you made it ApplicationSerializer it would work for any type. See the API here: http://emberjs.com/api/data/classes/DS.RESTSerializer.html#method_normalize

Resources