I am in the process of moving from using http to using socket.io to bring data into to my Angular 2 app. In the example I'd like help with I am using a private version of the api.service in my component constructor. All I need to do now is call the "get" function that's defined in the api.service (already set up to use socket.io). This is what the "get" function from the api.service looks like:
public get(req: string, options: any, callback: IRequestCallback) {
// go get stuff
}
Now in my component I had been using an http get function that looked like this:
getByCategory() {
return this._http.get(this._url)
.map((response:Response) => response.json())
.catch(this._errorsHandler);
}
Now I am change this to use the socket.io function from my api.service instead. As you can see in my code at the top, the socket "get" call from the api.service is asking for 3 parameters (a string, options, and a callback). I tried this:
getByCategory() {
return this.__socket.get(this._url, this.args, function(data) {
});
}
... but now I realize the URL is already being provided in the api.service. So what's stumping me, as silly as this may sound, is what I can pass as the first parameter. I tried passing in an empty string as the first parameter, but that errored out. What string could I pass here, instead of the url? Or is there some other way around this?
First, I've had no issues with the Http module, so I'm curious why you made the switch (not that I know all of the use cases!)
That being said, it sounds like it really depends on how socket.io is handling the underlying code -- optional parameters in Typescript ("optional") normally expect undefined as a placeholder, so you could try passing undefined in this case.
Related
I'm trying to call custom API in angular but for some reason it doesn't call it. Before this I made 10 functions in angular (in _api.service.ts) that call web API in the same way and they are correct, my web API is called and data is returned, everything is good. Then I made one more method in web API and one more component in angular (function getList() is called in it), and it didn't work, API is never called.
getList(id: string, chosen: string): Observable<StopListModel[]> {
let myUrl: string = API_URL + '/stop/list';
myUrl += '/' + id;
myUrl += '/' + chosen;
//debugger goes to this line, url is correct but API not called
return this.http.get<StopListModel[]>(myUrl, this.httpUtils.getHTTPHeader());
}
When I was debugging I saw that url for API is correctly sent from angular, like in 10 other functions that successfully call API in my project, so I think I don't need to send you code from my web API. I was confused so I moved line that is calling the getList() from new component to existing component, where I already know my _api.service will successfully call web API because in that component there is a function (for example getUsers() ) that correctly calls API. And it didn't work, API is not called for getList().
I assumed there is something wrong with web API for getList(), but just to be sure in that second component I called another _api.service function (that works when called from another component), and surprisingly - API was not called for that function either.
Then I saw what I think the problem is: when I try to call any function in any of my components, all this "new" functions never call API, just the old ones that have already been there, even though they correctly work in their own components.
export class DetaljiStopoviComponent{
stops$: Observable<StopStatisticsModel[]>;
list$: Observable<StopListModel[]>
constructor(
private apiService: APIService,
route: ActivatedRoute
) {
var id = route.snapshot.params['id'];
this.stops$ = this.apiService.getStopStatistics(id); //this works, it was there before - but any other calling I add under this, API is not called (this is the case for every component, every function)
this.list$ = this.apiService.getList(id, '3'); //this is the newest one, I can't make it call API even in the empty components
}
}
I am so confused and not experienced in angular, I'm very courious what the problem is. I don't think something is wrong with web API, but I'm not sure. Does anyone have suggestion?
I believe it is a syntax issue, for get method try this
return this.http.get<StopListModel[]>(myUrl, {headers:this.httpUtils.getHTTPHeader()});
Looks like you are forgot to subscribe to:
this.stops$ = this.apiService.getStopStatistics(id);
this.list$ = this.apiService.getList(id, '3');
I think this.stops$ works for you because somewhere in the template you have async pipe(stops$ | async).
So try to do:
this.list$.subscribe(response => console.log(response));
after that request should sent
I want to retrieve data from api and assign it to some value inside the angular component. In subscribe I'm trying to assign the data to loggedUser and then call function inside this subscribe to navigate to another component with this received object. Unfortunately I got the error : The requested path contains undefined segment at index 1. I want to have this object set outside the subscribe too. How can I achieve this?
logIn() {
this.portfolioAppService.logIn(this.loggingUser).subscribe((data) => {
this.loggedUser = data;
console.log(this.loggedUser);
console.log(data);
this.navigateToProfile(this.loggedUser.Id);
});
}
navigateToProfile(id: number) {
this.router.navigate(['/profile', id]);
}
console output
You are using an incorrectly named property when calling navigateToProfile.
From your console output, I can see that the data object in the subscribe looks like this:
{
id: 35,
// ..
}
But you are calling the function like this:
this.navigateToProfile(this.loggedUser.Id);
Instead, use the property id (lower case)
this.navigateToProfile(this.loggedUser.id);
To narrow this problem down in the future, try being more specific in your testing. Humans are good at seeing what they want to see and will assume the problem is more complicated than it is. If you had tried console.log(this.loggedUser.Id), you would have seen the result undefined, and worked out the problem yourself.
In JQuery:
initSliders(socket, '!{request}');
request is an object (an HTTP request object in Express.js web app) that has such info as my session. When I pass this in to initSliders() it come in on the other side as the String literal "[object Object]". Why? I don't know. It behaves like an object before it passes in since commands like these execute:
console.log('!{request.session.user}');
console.log('!{request.session.date}');
console.log('!{request.session.city}');
Display things like
Alfred
11/13/2013
Manitoba
How can I keep it's structure when being passed into the function so I can reference it's properties like those above??
The request object is coming in through a render, via an app.js handler like this (which is why I use the single quotes and curly brackets around it, it's the only way I know how to reference this)
exports.dashboard = function(req, res){
res.render('dashboard', {request: req});
}
It prints out [object Object] because req.toString() returns it. res.render('dashboard', { request: JSON.stringify(req) }) also does not make much sense just because request is particularly huge object and you probably do not really want ALL the object properties being passed to render script. However, you can try... So it is highly recommended to pass only what is required as follows:
red.render('dashboard', { parameters : JSON.stringify({ param1 : req..., param2 : req.... and so on })
So I want to subscribe to a publish function which only returns one object of a collection.
Meteor.publish("singleobject", function(bar) {
return MyCollection.find({foo: bar});
});
This should give me the SINGLE one object of the collection "MyCollection" where the foo property is equal to "bar", right? (There is only one object where this is true ... so findOne() should also work). What it does instead is returning me ALL objects of my collection, even those where foo is NOT equal to bar.
It works perfectly with another collection where there are more than one object where foo: "bar" is true.
I can't really see what I am doing wrong. Can I not subscribe to a publish function which returns only one object?
Anyone has any ideas on this?! :-)
best regards
Patrick
The code you've used:
Meteor.publish("singleobject", function(bar) {
return MyCollection.find({foo: bar});
});
doesn't return just one object, but every object that has foo equal to bar. If you want just one (and no matter which one), you should use findOne instead:
Meteor.publish("singleobject", function(bar) {
return MyCollection.findOne({foo: bar});
});
If you see also objects that have foo !== bar, it means that you fetch them elsewhere. There are two possible explanations:
You have another publish method for the same collection, or
You have autopublish package still on.
Take care of these two things and you should be fine.
For subscription, this is the usual pattern:
Deps.autorun(function(){
Meteor.subscribe('channel');
});
If you want the subscription to only work from time to time, there are few ways to achieve it.
The simplest one is to add a boolean argument to the subscription, and set it to true only if you want the channel to work. In the publish method you then simply return null if the flag is false.
More clean way is to track all your subscription handles and call stop() on those you don't want to use at this moment. It's nice, but hard to recommend in this version of Meteor as everything has to be done manually, which adds some not really necessary work.
So ... do NOT put
Meteor.subscribe()
inside of
Meteor.autorun()
or
Deps.autorun()
. Everything inside Meteor.autorun()/Deps.autorun() is ALWAYS executed, even if it's inside a template specific .js file. I was thinking every single one of these js files is only loaded when the according template is loaded, which of course is totally wrong.
This is only for structuring your app properly.
So if you want to subscribe to a publish function depending on the template loaded, put the Meteor.subscribe into the router callback functions and subscribe there.
Works perfect for me now! :)
I am using meteorjs and there are so called publications and meteor methods. Inside of these you can access a variable this.connection that holds information about all the http headers and connection you have with the specific user, for example the hostname over which they got access to your site.
As I want to make my application multidomain like slack, I now need to hook the database methods to limit the returned dataset to the right hostname.
Problem: This data is only available inside of the poblication or meteor method.
Is there any way to get the this of the calling method without changing the signatures of all my model functions?
Example:
mySpecialMethodWhereThisIsRight = function(param1) {
console.log(this.connection.httpHeaders.host) //Prints out the servername
modelname.mySelfMadeFunction(someData);
}
modelname = {
mySelfMadeFunction: function (data) {
console.log(this.connection.httpHeaders.host) //prints nothing
# some voodo
console.log(this.connection.httpHeaders.host) //Prints out the hostname
}
}
I am now looking for that "voodo" otherwise I would have to rewrite a lot of functions and the places they are called. (not that easy as there is no refactoring tool for coffeescript that actually works reliably)
Not sure I understood, but if you're able to make changes to the calling methods, would this work for you?
mySpecialMethodWhereThisIsRight = function(param1) {
console.log(this.connection.httpHeaders.host) //Prints out the servername
modelname.mySelfMadeFunction.bind(this)(someData);
}