How can Laravel ignore everything except certain prefix? - angularjs

I have my angular app running off of my laravel route /
I have everything else under /api.
I want to be able to enable html5 mode in angular and maintain SPA like routing, but when I do, laravel catches the route.
So how can I get laravel router to ignore everything except api and the initial route?
using laravel 5.2

I think you can do the following:
// Catch any routes except 'api'
Route::any('{all}', 'InitController#index')->where('all','^((?!api).)*?');

You will need to have a catch-all route to render index view on every request - then let Angular handle routing. Remember, you will also need to create 404 pages etc within Angular app.
// API routes here
// Catch-all route to point everything to index page
Route::get('{something}', function() {
return view('index');
});
With regards to the API routes, you need to place these above your catch-all route so that they return an API response.
Angular Routing
Are you using Angular 1 or 2? What angular router are you using? e.g. with Angular1 using $location you add false as 2nd parameter to path:
$location.path('/some-path/', false);

Related

How to handle Laravel routing using AngularJs?

I am completely new to Laravel + AngularJs. What I want to do is handle my web.php routes using AngularJs. Is it possible? If it how can I do that?
If you have an SPA and your app is using HTML5 history mode, this should be similar to how people often combine Laravel and VueJS routing.
You'd usually have all of your non-Angular routes at the top of routes/web.php and then a "catch-all" route for your SPA. This "catch-all" route is basically a route that doesn't care what the route looks like; it will just send it on to the AngularJS app.
Similar to this answer or this article your routes/web.php might look something like:
Route::resource('Videos', 'VideoController')->middleware('auth','isAdmin');
Route::resource('Categories', 'CategoriesController')->middleware('auth');
...
Route::get('/{angularjs_capture?}', function () {
return view('angularjs.index');
})->where('angularjs_capture', '[\/\w\.-]*');
And then you'd have a view at /resources/views/angularjs/index.blade.php that contains the base HTML for your SPA.

Angular Router not updating browser URL when called from AngularJS

I have an AngularJS application, which I'm in the process of converting to a hybrid Angular/AngularJS application using ngUpgrade. The AngularJS application is unusual in that it doesn't use the AngularJS or Angular UI router - instead it has its own hand-rolled navigation solution, which doesn't update the URL displayed in the browser, or interact with the browser's history API. So far, so good.
I want to start using the Angular Router in the hybrid application, but initially only for new pages.
To get the 2 parts of the application - Angular and AngularJS - interoperating with each other, I have downgraded the Angular Router service and injected it into one of my AngularJS services, so that I can call Router.navigateByUrl() to navigate to a new Angular page component, from my AngularJS code.
This works correctly - the Angular page component is added to my <router-outlet> and is displayed in the browser as expected.
Strangely though, the browser URL does not change. When I enable tracing for the Router, I can see the new route being correctly processed, and the new page is displayed in the browser, but the browser URL still shows the old route. Also, if I look at the browser history, the new route has not been added to it.
I've tried injecting NgZone into my AngularJS service and calling Router.navigateByUrl() inside NgZone.run(), but it doesn't make any difference.
When I call Router.navigateByUrl() from my Angular code, everything works fine - except when I do this after I've done it from AngularJS, when I then see the same symptoms. It's as if calling the Router directly from AngularJS is somehow breaking the link between the route and the browser URL bar.
Can anyone help please...?
So the issue was that the AngularJS $location service wasn't being updated when the route changed, leaving a disparity between its value and the value being displayed in the browser. There was also a watch in this service which was being triggered in every digest cycle, that was then resetting the browser url from the value in the $location service!
Turns out this was because I needed to configure the Unified Angular Location Service in my AppModule viz:
imports: [
LocationUpgradeModule.config()
]
and downgrade the $locationShim service for injection into AngularJS viz:
angularJS.module('my-app')
.factory('$location', downgradeInjectable($locationShim));

MVC and AngularJS Single Page Application

I have an MVC Razor app that I have just converted to a Single Page Application using AngularJS and Angular UI Router.
I have a problem in that when I go to a URL (via a refresh) such as /settings/options MVC attempts to look for the Options() method on the Settings controller. Once the page has finished loading the Angular routing takes over and shows the correct page.
Because my layout page HAS to have a RenderBody() call (else an exception is thrown) I end up with my page looking correct but having a 404 page at the bottom. The 404 is rendered into RenderBody because it cannot find the Options() method on the Settings controller
How can I fix this? I presume using some kind of MVC Routing but not sure where to start. Here is my current route
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
This question has a similar problem except they use WebAPI and I have my endpoints within a normal controller. If I use the solution here all my AJAX requests get redirected too
I feel like this question (How to use ASP.NET MVC and AngularJS routing?) might help you. They're using different "Areas" of the site, but it's the same concept for the routing.
You could also look into the URL Rewriter for IIS config and use that to make rules to always route your SPA requests to the angular app...
How do I configure IIS for URL Rewriting an AngularJS application in HTML5 mode?

Angular And Node routing

I am using Node for back end Angular for front end but what will happen if will declare same route for front end and backend. I haven't tried it yet.
E.g: If I am building a TODO app and if I have /todos back end service and I am rendering todos view with same route using angular.
AngularJS is processing the route after the # by default. So nothing will happen if you don't change that.
Otherwise, the backend route will be called.
Angular is client side browser framework. Your app defaults to slash(/) which points to your index.html. Your routes prefixed with hash(#) which prevents browser to make requests to server.
Angular defaults to client side & use its own routing mechanism. Express provides server side RESTful routes which behaves like an REST Api for your angular app.
In case if you want to use HTML5 Pushstate API(removes hash(/)) from default angular routing mechanism, the only thing which separates angular routes and express/server routes, You just need to structure your app like below.
express()
.use('/api', backend) // backend is express app
.use('/', www) // www is public/static files
.all('/*', function (req, res, next) {
"use strict";
// Just send the index.html for other files to support HTML5Mode
res.sendfile('./app/index.html', {root: __dirname});
})
.listen(process.env.PORT || 8888, function () {
debug('Express dev server listening on port ');
});
Your express/server routes lies after /api part, and other routes(obviously your angular routes) will return index.html(html snapshot).
Above mechanism is mostly preferable for MEAN web apps.
Angular provides its own routes after # like myhost.io/angular/#/someroute while node provides ordinar routes like myhost.io/some/other/route witch makes almost impossible to fail!
NOTE:
But you must be careful with setting routes, because if you have static files (like angular client), your routes with same path won't work using express or connect.

How to handle non-root URLs in a singlepage app?

I try to make a single page app with Rails 3.2 and Backbone.js with pushState option but faced with something that I do not understand.
If I load the root URL of the app (/), everything goes right: Rails return an HTML-layout with JS which bootstraps Backbone which makes some XHRs for JSON-entities and renders the content.
But if I start using app from non-root URL (e.g. by manually typing it in the browser's address bar) then Rails will try to handle this request using theirs routing rules from routes.rb - that's wrong, cause it's a "Backbone's" route. How do I load the page and bootstrap Backbone for handling this URL in that case?
Finally I found the solution.
I put the following code into my routes.rb
class XHRConstraint
def matches?(request)
!request.xhr? && !(request.url =~ /\.json$/ && ::Rails.env == 'development')
end
end
match '(*url)' => 'home#index', :constraints => XHRConstraint.new
With this matcher all non-XHR requests are routed to HomeController which returns an HTML page. And XHR requests will be handled by other controllers which return JSON responses.
Also I left requests ending with ".json" as valid in development environment for debugging.
This is a somewhat tricky issue, but basically in a nutshell, you need to respond to all valid (HTML) requests in rails with the same (root) page, from there backbone will take over and route to the correct route handler (in your bakckbone router).
I've discussed this issue in more detail here: rails and backbone working together
Basically what I do is to create actions for every page that I want to handle, and blank views. I use respond_with to return the page (which is the same in each case) and because I handle GET actions only for HTML requests, I add this line at the top of the controller:
respond_to :html, :only => [ :show, :new ]
JSON requests are handled with respond_with as well, but unlike the HTML requests actually return the requested resource (and perform the requested action in the case of PUT, POST and DELETE).
Backbone will not be informed of your url change if you do it manually. This change will be catch by the browser and it will do its job sending the request to the server as usual.
Same if you click in a normal link, it will follow its href without inform Backbone.
If you want Backbone being in charge of a url change you have to do it through the Backbone tools you have available and this is the own Router.
So if you want to make an URL change in the Backbone way you have to do it explicitly, something like:
app.router.navigate("my/route", {trigger: true});

Resources