Laravel 4 - AngularJS - Routing - angularjs

I'm trying to biuld an app with L4 and Angular. I'm struggling a bit with routes. I'm using the html5Mode(true) to have nice looking urls. It all works fine as long as I don't reload.
If I reload a page with a url other than /, L4 takes over and tries to send me to the appropriate page. I don't want that. I'd like all pages to be routed to the homepage where angular can take over.
I found a way to redirect all traffic to the home by using this:
Route::get('{all}', function($uri){
return View::make('home');
})->where('all', '.*');
Only issue is that once I try doing request with angular it sends me back the HTML of the homepage instead of the resource I need.
Any idea how I could solve this problem?
Thanks

I am also making the same and my solution is, make some api routes which is grouped and call this in angular. This route should be placed before your main route.
/*
API Routes
*/
Route::group(array('prefix' => 'api/v1', 'before' => 'auth.basic'), function()
{
Route::resource('pages', 'PagesController', array('only' => array('index', 'store', 'show', 'update', 'destroy')));
Route::resource('users', 'UsersController');
});
Route::get('{all}', function($uri){
return View::make('home');
})->where('all', '.*');
And access this like api/v1/pages in angular js. If you don't want to authenticate, you can remove 'before' => 'auth.basic'

I was battling this for a few hours as well and came up with a solution. In my project i am using angular to control the actual view switching. so what i did was to define two separate route groups in L4, one that returns actual pages directly from laravel's routing system and another that returns HTML fragments for angulars routing system.
Here is an example of my routing
//Laravel pages and API routes
Route::get('/', function()
{
return View::make('hello');
});
Route::get('/register',function(){
return View::make('registration');
});
//Angular SPA routes(HTML fragments for angulars routing system)
Route::get('/getstarted', function(){
return View::make('getStarted');
});
Route::get('/terms',function(){
return View::make('terms');
});
So in this scenario, laravel sends your home page when you call "/", and the ng-view asks for "/getstarted" by ajax which returns your html fragment. Hope this helps :)

What web server software do you use, server side? Apache? Nginx?
You must configure your http server to support your push state app.
Here is a sample Apache .htaccess that can do this:
# html5 pushState support
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index
RewriteRule (.*) index.html [L]
</IfModule>

Related

CodeIgniter3 - routes do not work when serving app as example.com/codeigniter

I have an application based on codeigniter3 framework hosted on VM bitnami lampstack. Initially I have set up the apache to serve the application from the root domain: example.com/. Furthermore I have an .htaccess file for removing the index.php from url as per CI3 documentation.
The content of my .htaccess is as follows:
RewriteEngine on
RewriteCond $1 !^(index\.php|assets|static|vendor|images|js|css|uploads|favicon.png)
RewriteCond %(REQUEST_FILENAME) !-f
RewriteCond %(REQUEST_FILENAME) !-d
RewriteRule ^(.*)$ index.php/$1 [L]
Recently I have changed the apache configuration as such that the application to be served from example.com/codeigniter and although the main page is loading correctly all the links in application are broken and when clicked they return not found message: The requested URL /about was not found on this server.
My routes in config/routes.php looks like this:
##---------------- Home Routes ------------------##
$route['about'] = 'home/about';
$route['login'] = 'home/login';
The link in the navbar is set like this:
<li class="navbar-item" role="presentation">
<a class="navbar-link" href="/about">
<i class="far fa-address-card"></i> About
</a>
</li>
When the link is clicked it is pointing to example.com/about instead of example.com/codeigniter/about. But even if I add as href="/codeigniter/about"it is still does not work. Seems to me that the somehow the codeigniter fails to map the path to the correct controller.
The problem is solved in part by adding index.php before the route (e.g. example.com/codeigniter/index.php/about). It is loading the correct page but fails to load the static files (css, js and images files).
So seems to me that problem results from .htaccess file but I do not know how to fix it. What should I add to or remove from that file?
Do you have any ideea how this problem may be solved?
Thanks!

Redirect unknown requests to index.html in springboot

I'm trying to get an Angular2 app served up through a springboot web application. I've found lots of examples of how to do this very simply:
https://spring.io/blog/2015/01/12/spring-and-angular-js-a-secure-single-page-application#using-spring-boot-cli
https://github.com/zouabimourad/angular2-spring/tree/master/front
https://github.com/ehirsch/spring-angular2
However, these examples are very simple, and they just basically show how to display static content that happens to be Angular.
None of them show how to handle any of the URLs (I think they're called routes) the Angular2 app uses that don't map to "real" resources.
Eg. We have a "/login" route in the Angular app, but we don't have a #Controller/#RequestMapping("/login") for this, I want Spring to render index.html when it see's a request for "/login".
Generically - I want Spring to render "index.html" whenever it can't an actual resource. Is there a way to set a default view for all requests that can't be mapped to something or found?
I've tackled this before by using an htaccess file and have apache handle this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.html [L]
ErrorDocument 404 /index.html
</IfModule>
But I can't use apache or nginx in this case.
As a work-a-round I've added the Angular Routes in a RequestMapping annotation and pointed them all at the index.html:
#RequestMapping({"/login", "/logout"})
public String index() { return "index.html"; }
Edit: As a better work-a-round, you can make the controller implement ErrorController, override the getErrorPath method, then add a mapping for /error which will act as a catch-all (or mapping missing) method.
#Controller
public class TheOneController implements ErrorController {
#RequestMapping("/error")
public String index() {
return "index.html";
}
#Override
public String getErrorPath() {
return "index.html";
}
}
Now the index method will handle anything that can't be found and render the index.html.

I am making a website in angularjs and using ngRoutes. My query is about removing # fromt the url

Following is my code where I am configuring my routes:
/**
* Main AngularJS Web Application
*/
var app = angular.module('chocomelte', [
'ngRoute'
]);
/**
* Configure the Routes
*/
app
.controller('HomeCtrl',HomeCtrl)
.controller('AboutCtrl',AboutCtrl)
.config(['$routeProvider','$locationProvider', function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when("/", {
templateUrl: "partials/home.html",
controller: "HomeCtrl"
})
.when("/about", {
templateUrl: "partials/about.html",
controller: "AboutCtrl"
})
}]);
This removes # from my url. When I try to go to the /about route by clicking on a button in my UI, it works fine. But when I manually try to type the URL and go to it or refresh the page on /about url, I get this error:
500 internal server error.
I am not using node in the backend. A simple website using angular in the frontend. How to I configure this on the client side?
Make sure you're setting the base url with this meta tag:
<base href="/my-base">
Also, you may have to implement URL rewriting on your server when using html5 mode, to make sure that any requests are redirected to the root of your application instead of being interpreted as GET requests.
From the documentation:
Using this mode requires URL rewriting on server side, basically you have to rewrite all your links to entry point of your application
I am using Apache server. Finally fixed it. Had to rewrite the urls in the .htaccess file as follows:
Options +FollowSymLinks
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index
RewriteRule (.*) index.html [L]
</ifModule>
Had to specify index.html as the entry point.

External pages and Angular JS routing

I have a PHP page over at mysite.com/somedir/script.php.
When I have <a> tags in my Angular views that point to this script, Angular's routing always brings me back to mysite.com/index.html when I click on them.
This is my $routeProvider configuration:
siteModule.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl:'/views/blog.html',
controller:'blogController'
})
.when('/blog',{
templateUrl:'/views/blog.html',
controller:'blogController'
})
.when('/work',{
templateUrl:'/views/work.html',
controller:'workController'
});
// For Pretty URLs
$locationProvider.html5Mode(true);
});
I'm also using some Apache mod_rewrite to handle 404s / page refreshes in an .htacess file that I think may be interfering:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index
RewriteRule (.*) index.html [L]
The aforementioned PHP page is a valid (existing) resource so I'm not sure why Angular or Apache would redirect / rewrite away from it. I'm using the target="_blank" on the <a> tags and have the <base href="/"> set in the index page's <head> tag as well.
I just want to be able to access my script normally instead of being pointed back to the index page.
In javascript you can still use window.location.href to escape the router, so in the 'otherwise' section of your router, use window.location.href = {the route} instead of allowing it to use the default index.
See these other answers to this question:
Angular routes - redirecting to an external site?
Using $routeProvider to redirect to routes outside of Angular

Laravel 4 as RESTful backend for AngularJS

I am trying to build a web application which should use Laravel as a RESTful backend API and AngularJS on client side.
I read all the other post on Stackoverflow about the issue, but no one is definitely answering my doubts, at least, I did not find a definitive source example.
For instance...
Should I develop two completely distinct applications, a backend one with Laravel and another, purely client, with AngularJS?
But in this case: how to handle them through a single domain (or virtual host)?
Or should I create AngularJS templates inside Laravel, in the "views" folder and from them call Laravel services? I doubt this is the best approach: in this case the backend is not completely decoupled from the frontend implementation.
Also, how to correctly handle routing? I mean: I would like to manage from AngularJS routes like menu/page navigation, calling Laravel only to retrieve data and fill my views.
Moving the "public" folder as suggested in this post (Angular JS + Laravel 4: How to compile for production mode?) may help?
Thanx in advance for suggestions, examples...
Finally I found a working solution, perfect in my scenario, which does not require a subdomain.
In this case Laravel acts exclusively as a RESTful web service, no server side views or templates: the presentation layer is completely demanded to AngularJS.
Let's say I have two completely decoupled applications (FE e WS) inside the same root folder:
root
|__fe
|__ws
I modified virtual host settings under Apache httpd-vhosts.conf file the following way:
<VirtualHost *:80>
ServerName myapp.com
DocumentRoot "\www\root\fe"
alias /ws "\www\root\ws\public"
<Directory "\www\root\ws\public">
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
I then added "RewriteBase /ws" into my laravel/public/.htacces file:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteBase /ws
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [NC,L]
</IfModule>
This way I can write in the browser (for instance):
http://myapp.com (AngularJS client side root)
http://myapp.com/ws/users (RESTful service endpoint for "users")
And then define a client side, AngularJS routing the following way:
app.config(function($routeProvider) {
$routeProvider
.when('/', {controller: 'HomeController', templateUrl: 'templates/home.html'})
.when('/users', {controller: 'UsersController', templateUrl: 'templates/users.html'})
.otherwise({redirectTo: '/'});
});
Linking it to a RESTful resource this way:
app.factory('User', function($resource) {
return $resource('http://myapp.com/ws/users');
});
app.controller('UsersController', function($scope, User) {
$scope.title = "Users";
$scope.users = User.query();
});
I enabled HTML5 history API, adding this line to configure my Angular application:
$locationProvider.html5Mode(true);
together with (inside index.html head section):
<base href="/" />
<meta name="fragment" content="!" />
So the last requirement to solve problems like browser page refresh, deep linking, or direct page bookmark, is to add a .htaccess file in the root of the folder which contains the Angular application:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [NC,L]
</IfModule>
Hope it helps!
This is a half comment half answer, it got too long.
Matteo as you pointed out there are basically three different places you can do some sort of routing/redirecting with this stack. Ordinarily I haven't seen an advantage to doing the redirects at the Apache level, I imagine this might be more useful for localization or perhaps some sort of load/disk balancing. However you will have your VirtualHost configuration if you have multiple domains pointing to this address and you need to route those initial requests to the appropriate index.html (so if you consider this routing this would be my server side routing).
Generally speaking after that I rely on the Angular $routeProvider to handle client side "routes" really just mapping a URL to a view (possibly passing along some data).
I haven't gotten fancy with setting up a router in my PHP code to create a proper RESTful interface. In my particular case the data is being stored in a fairly abstract way and I had to do a fair amount of work in the PHP to get it organized in a coherent way, any straight ORM type solution wasn't going to work. This attempt has led me to consider options like MongoDB though since it should alleviate the workload necessary for doing the translation from persistent storage to client side and back.
Anyhow all that said I use $http to just make my calls from custom services to particular PHP endpoints that I need. My PHP folder with my scripts sits right next to where my index file is served up so requests from angular are all relative paths from the server root which keeps it simple. So they are physically "nested" so to speak or living side by side but the PHP code never writes any templates or affects the presentation it just gets data and serves it up (as JSON), so conceptually they remain separate.

Resources