I am running a MEAN framework with express routing requests. I have two main routes to public/ and app.
With the APP being an API and public being a set of web pages which reads data from the API.
// Setting the app router and static folder
app.use(express.static(path.resolve('./public')));
I have two controllers in the public folder, home and header.
In the home controller I am using Angular JS to call the API and return the results.
The API allows for filtering through the use of query strings:
$http.get('http://search?sumBoth=1&customer=' + customer)
I would like to build up a route specific to this controller along the lines of
http://url/customers/CustomerName
Where CustomerName would be set as the customer variable
Question
a) Is this best done in Angular or Express?
b) Where and how do I implement such routing?
I hope this question is well received, please comment, if you need more information.
I understand that the response of $http.get('http://host/path?sumBoth=1&customer=' + customer) is a list of search results. In that case the path should be a collection path, it's not really a best practice to have search terms in the path. Subcollection paths are pretty standard (something like http://host/customers/search?params, but still the specific search terms should go in the query string)
If on the contrary you expect to retrieve just one result by some identificator (provided for instance the customer name is unique) that's a different story, you should really use http://host/customers/:identifier.
In any case you can use angular resources, both parts of your application need to be aware of the routing. In the front-end you define an additional verb that adds the filters (or just use the standard query one - see https://docs.angularjs.org/api/ngResource/service/$resource). In the back-end you need to route the call and parse the parameters. If it's a list, parse the query string and render your result array, if it's a single resource, parse the identifier, find the corresponding resource and render it back.
Related
I want to simulate a micro blogging application to learn Angular 2.
I am using the following json placeholder links:
users
post
As you can see, the post api has userId, (and not username). If I have to display the user name while listing all post, would I require another API with both post and user name, or can it be done using two different calls to the above APIs?
This is the way I will be listing the post :-
<li *ngFor="let post of posts">
<div>{{post.userId}}</div>
<div>{{post.id}}</div>
<div>{{post.title}}</div>
<div>{{post.body}}</div>
</li>
As you can see, here based on the api call, I am getting userId...Instead of that I want it to display user's name
The way to do this in angular is using services. You don't directly call to an API from within your component. You need to create a "service" to deal with APIs, then inject your service in your component and consume them in there.
In your particular scenario, you will have two services, a "UserService" and a "PostService". Each of those services have a proper "get" method that calls to an API. Then in your component, you inject both those services and call their respective methods separately.
Regarding your specific update on the question, imagine you have a "posts" array and a "users" array after you have received your result from the API. Now, pay attention to the following logic:
for (let i=0; i<posts.length; i++)
{
posts[i].username = users.filter(u => u.id === posts[i].userId)[0].username
}
What we did here is iterating through all "posts" and adding a "username" attribute to each of them by cross referencing them to the users array. Just make sure you use the right syntax and case sensitivity as I have not tested this line and just included the logic in it
Both the options are viable..
You can create another API that responds with the required data. The new API can cal the controller functions of the previous API endpoints and return the data in the required format.
note: this is possible if you are working with your own server.
you can also chain the API calls if you want to work with the existing APIs.. Call the user api and then when you get the user details, in the subscribe handler, make another request to the posts API.
note the only problem i can see with this approach is the number of requests.. as there will be a posts request for each user.
In the End the decision is yours. you'll have to see the pros and cons.. If the server code is also yours, ill suggest the first approach..
I am using MeanJs Stack
I need to call the following Api :
http://localhost/api/movies/movieId/Action?page=1&perPage=10
How to send params (page='+:id+page='+pageNum+'&perPage='+perPage) in Server Route
I am sending the Following way which is not Helping
movies.server.routes.js
app.route('/api/movies/:id/Action?page='+:id+'page'=+pageNum+'&perPage'=+perPage')//But it is not recognising by rout and parameters are not sending
.get(movies.readAllMovies);//triggers and call the api .
Could you guys give me some Hint of it ?
Sorry for the horizontal scroll guys :-) .
Thanks.
According to ExpressJS documentation, query strings are not part of a route definition.
Therefore, your route could be refined (apart from having a couple of syntax errors) as such:
app.route('/api/movies/:id/Action')
.get(movies.readAllMovies);
Then, in the handler movies.readAllMovies, you can access query strings with req.query. That is, the page query string can be retried as req.query.page and so on.
Note that since expressJS uses regular expressions to match routes, a ? will serve as a quantifier in regular expression terms.
First of all, in my opinion, you should be handling this through a service to return the result, and a RESTful endpoint on the node server to perform the query. I feel your above approach could use a serious re-visit conceptually, so here's how I'd tackle it.
You need to create a service or a factory for handling the requests to the api endpoint
Check out the below instructions for modifying your api endpoint so that it just pipes the response back to the service
Include the service in your angular module and consume it on demand in your controller / whatever
You should use request module and params, it is by far the easiest method of retrieving query params in get requests in my opinion and streaming the response is to just pipe the result of the url. This is super simple using request https://www.npmjs.com/package/request
First, lets modify your endpoint and include the request module
First npm install request --save
Then in your app include request var request = require('request');
req.query.--name of queryparam
and
req.params.--name of param
Then your endpoint is as simple as
app.get('/api/movies/:movieID/:Category', function(req, res){
var url='http://localhost/api/movies/' + req.params.movieID + '/' + req.params.Category +'?page=' + req.query.page + '&perPage=' + + req.query.page;
request(url).pipe(res);
});
**You should be able to hit this endpoint directly with a get request and it should work
Then Create a Service to consume the result and provide it to the controller
I'm running my app on localhost:3000/#!/, and trying to get URL parameters for use with Express, with no luck. I've created a new server routing file that contains the following:
admin.server.routes.js
'use strict';
module.exports = function(app) {
// Admin Routes
var admin = require('../../app/controllers/admin.server.controller');
// Both of these routes work fine.
app.route('/admin/test').
get(admin.populate).
put(admin.update);
// First attempt, didn't work.
app.route('/admin/test').get(admin.doSomething);
// Second attempt, didn't work.
app.param('foo', admin.doSomething);
// Third attempt, didn't work.
app.param('foo', function(req, res) {
console.log('Found foo!');
return res.status(400).send();
});
};
On my admin page, my admin.client.controller.js sends an $http.get request on loading to populate the data. I have a form with a button the sends an $http.put request to update the populated values. Both of these requests work fine.
The problem is when I try to visit my app using a URL with the foo parameter, like so: http://localhost:3000/#!/admin/test?foo=bar. I've tried each of the three attempts noted above in my code (commenting out the others out so I could try them one by one), but cannot seem to get the variable.
In my admin.server.controller file, in addition to the populate and update functions, I simply have this code:
admin.server.controller
exports.doSomething = function(req, res) {
console.log('Server - found foo!');
};
Using none of these efforts have I actually been able to demonstrate that I've successfully "grabbed" foo for server-side use. What am I missing?
In your
http://localhost:3000/#!/admin/test?foo=bar
all hashbang urls are handled by angularjs, this /admin/test?foo=bar wouldn't be considered as a request. To add a query string in your request, you can do it like this in angularjs resource:
function ($resource) {
$resource('/admin/test').query({foo: 'bar'});
}
This would be expressed as this http://localhost:3000/admin/test?foo=bar
Your issue relies mostly on how you send your request on your client-side.
By the way, in your express routes you can get the foo value like this: Pre-routing with querystrings with Express in Node JS
If you wanted to get the query string and use it in your request, refer to this: How can I get query string values in JavaScript?
A URL is in the form <protocol>://<hostname>?<query string>#<fragment>.
Any part of a URL after (and including) the first # is considered a fragment. Fragments are only used on the client (in this case the browser), and are not typically used by the server.
From section 3.5 of RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax:
Fragment identifiers have a special role in information retrieval systems as the primary form of client-side indirect referencing, allowing an author to specifically identify aspects of an existing resource that are only indirectly provided by the resource owner. As such, the fragment identifier is not used in the scheme-specific processing of a URI; instead, the fragment identifier is separated from the rest of the URI prior to a dereference, and thus the identifying information within the fragment itself is dereferenced solely by the user agent, regardless of the URI scheme.
Traditionally fragments are used to link to anchors on the same page. A good example is the link provided above to the RFC page, which will jump you down to the section 3.5. Fragment automatically in your browser.
The URL to the section is https://www.rfc-editor.org/rfc/rfc3986#section-3.5, so the fragment is section-3.5. In the HTML for the page there is an anchor within the <h3> denoting the section with:
<a class="selflink" name="section-3.5" href="#section-3.5">3.5</a>
The interesting property here is name, which names the anchor, allowing the browser to identify and jump to it because it matches the value requested by the fragment. In effect, the anchor is a client side 'secondary resource' that is being requested by the URI.
Client side javascript applications and frameworks such as angularjs take advantage of fragments; the fact that they are not for use on the server; and the fact they are included in the browser history stack; as a way to reference resources on the client side, for example to use a client side routing system.
(Aside: #! has risen as a popular idiom for denoting routes in client side applications. This is possibly related (grammatically but not technically) to the #! header used in *nix based executable scripts. These are typically followed by a path to an interpreter for the script. For example #!/bin/bash.)
So in the URI http://localhost:3000/#!/admin/test?foo=bar, the segment ?foo=bar is after the # denoting the fragment, and is therefore being defined as part of the fragment rather than the query string. A query string for a remote resource should always be defined before the fragment. For example:
http://localhost:3000/admin/test?foo=bar#!/route/in/angularjs
I am working on a project which is published in that way
A WebApi application hosted on Server1
An AngularJS application hosted on Server2 which call the APIs on the Server1
On the AngularJS application I have a javascript prototype used for common functions and one of these builds the base url to call the API on server 1 (so, it returns i.e https:\server1\api)
Right now the URL address "server1\api" is hard-coded (I know...i begging you for mercy) on a variable, but what I need is:
1) Use a file for the configuration (I thought should be good to put all the configuration on a single JSon file and load it when the app start)
2) Be able to configure which configuration copy on Server1 during the Visual Studio publishing process of the AngularApp (something like the web.config transform)
The first point is not tough, but how can I create the kind of transformation on the second point and automatically select the right Json file during the publish?
Thank you
You could use an angular constant from the angular side, and inject that where needed
//define your const
angular.module('MyModule').constant('serverUrl', 'VALUE');
//use your const via DI
angular.module('MyModule').factory('factoryName', function('serverUrl'){});
but set that code in your view (assuming Razor
angular.module('MyModule').constant('serverUrl', '#(ViewBag.ServerUrl)');
and you can pull that data from your web.config, which can be transformed during either your build or release process via a transformation.
It is an odd way to get there but it should work for you.
I'm attempting to build an API for two resources, one with Users, and the other with Movies. Both resources have associations -- a User will have multiple Movies, and a Movie will have multiple Users. Presumably, I'd design my API something like this:
/api/users/
/api/users/:id
/api/users/:id/movies
/api/movies/
/api/movies/:id
/api/movies/:id/users
But here's the issue: I'm also using Backbone.js on the client side to fetch the API data. If If I create a Collection at
/api/users/:id/movies
then this will work well for GET requests, but POST and PUT requests would seemingly then be directed at:
/api/users/:id/movies/:id
But, seemingly, it would be better if it was posted to
/api/movies/:id
instead. Is that correct? How do people generally deal with RestFul associations?
Not sure what you mean by "POST and PUT requests would seemingly then be directed at...". Does Backbone.js automatically adds parameters to URLs? If so, you should look at configuring it so that it doesn't do that, because it won't be usable with a REST API. Links provided by a REST API should be the full ones, there's nothing to add or remove from them.
Finally, if you want to associate a movie with a user. You would POST the movie (or just its ID) to:
/api/users/:id/movies
It is correct. This is because "movies" are independent from "users". Movies can exist without users, so their relationship are actually "associative".
To create movies, you don't need users at all, so it makes more sense for the POST URI to create movie to be "POST /api/movies".
Alternative of association in RESTful API that I can think of is to have the list of movie IDs in the GET users API response, e.g. a property named "associatedMovieIDs" which has an array of strings of the IDs of the movies associated to the user.
With this, your APIs will then become:
/api/users/
/api/users/:id
/api/movies/
/api/movies/:id