Raphael Rafatpanah
Raphael Rafatpanah

Reputation: 19967

How to serve a single page AngularJS app from Laravel views/templates directory?

I am trying to combine a SPA angular app based off of Mobile Angular UI that can take advantage of Laravel's features like csrf protection. I can place the entire AngularJS app in Laravel's public/ directory, but I'm not sure if that is the right way of doing it.

What I'm looking for is guidace on how to be able to serve an index.php that can interact with Laravel from which a single page AngularJS app would take over. In my case, Laravel is an API for the single page app.

The problem:

  1. Laravel route is defined for /app3 which returns index.php from templates/

Of course, I'd prefer to define the route for /app, however, all AngularjS assets are located in public/app/ and requesting app/ returns a default directory listing since there is no index.php/html in /app. Simply placing index.php in public/ results in a blank page since for some reason, the PHP never gets parsed by the server. Changing index.php to index.html works, but then how can I take advantage of things like Laravels csrf protection?

  1. index.php loads all AngularJS resources correctly and without console errors.

  2. Clicking on a sidebar link from index.php, which normally returns an AngularJS template which should be placed inside index.php, instead, loads the default directory listing shown when a directory contains no index.php/html.

Why do the AngularJS templates fail to load inside index.php?

What is the best way to combine a single page AngularJS app with Laravel?

Upvotes: 3

Views: 3028

Answers (3)

Joel Fernandes
Joel Fernandes

Reputation: 161

You can do something like this in the public folder

Content of each directories in the public folder:

public/app : Contains all AngularJS related JavaScript files (controllers and lib directories)
public/app/controllers: Contains all AngularJS controllers
public/app/lib : This directory will contain all AngularJS core files. You can also load AngularJS from a CDN network. 
public/css : Contains all CSS files.
public/js : Contains all regular JavaScript files for our UI.

You can have a read at a complete article at

http://deepdivetuts.com/create-laravel-and-angular-single-page-application-for-beginners-only

Upvotes: 0

Raphael Rafatpanah
Raphael Rafatpanah

Reputation: 19967

Finally got it. The problem was that my AngularJS route links were wrong.

Here are my working configurations:


Laravel
routes.php

...
$router->get('/app3', function() {
    return view('app3.index');
});

AngularJS
index.php

<base href="/" />

...

<!-- Sidebars -->
<div ng-include="'/app/sidebar.html'" 
        ui-track-as-search-param='true'
        class="sidebar sidebar-left"></div>

demo.js

  app.config(function($routeProvider) {
  $routeProvider.when('/',              {templateUrl: 'app/home.html', reloadOnSearch: false});
  $routeProvider.when('/app/',              {templateUrl: 'app/home.html', reloadOnSearch: false});
  $routeProvider.when('/app/scroll',        {templateUrl: 'app/scroll.html', reloadOnSearch: false}); 
  $routeProvider.when('/app/toggle',        {templateUrl: 'app/toggle.html', reloadOnSearch: false}); 
  $routeProvider.when('/app/tabs',          {templateUrl: 'app/tabs.html', reloadOnSearch: false}); 
  $routeProvider.when('/app/accordion',     {templateUrl: 'app/accordion.html', reloadOnSearch: false}); 
  $routeProvider.when('/app/overlay',       {templateUrl: 'app/overlay.html', reloadOnSearch: false}); 
  $routeProvider.when('/app/forms',         {templateUrl: 'app/forms.html', reloadOnSearch: false});
  $routeProvider.when('/app/dropdown',      {templateUrl: 'app/dropdown.html', reloadOnSearch: false});
  $routeProvider.when('/app/drag',          {templateUrl: 'app/drag.html', reloadOnSearch: false});
  $routeProvider.when('/app/carousel',      {templateUrl: 'app/carousel.html', reloadOnSearch: false});
  $routeProvider.when('/app/toggleLegacy',  {templateUrl: 'app/toggleLegacy.html', reloadOnSearch: false});

sidebar.html

  <a class="list-group-item" href="/app3/#/app">Home <i class="fa fa-chevron-right pull-right"></i></a>
  <a class="list-group-item" href="/app3/#/app/scroll">Scroll <i class="fa fa-chevron-right pull-right"></i></a>
  <a class="list-group-item" href="/app3/#/app/toggle">Toggle <i class="fa fa-chevron-right pull-right"></i></a>
  <a class="list-group-item" href="/app3/#/app/tabs">Tabs <i class="fa fa-chevron-right pull-right"></i></a>
  <a class="list-group-item" href="/app3/#/app/accordion">Accordion <i class="fa fa-chevron-right pull-right"></i></a>
  <a class="list-group-item" href="/app3/#/app/overlay">Overlay <i class="fa fa-chevron-right pull-right"></i></a>
  <a class="list-group-item" href="/app3/#/app/forms">Forms <i class="fa fa-chevron-right pull-right"></i></a>
  <a class="list-group-item" href="/app3/#/app/dropdown">Dropdown <i class="fa fa-chevron-right pull-right"></i></a>
  <a class="list-group-item" href="/app3/#/app/test/invoice">Invoice <i class="fa fa-chevron-right pull-right"></i></a>
  <a class="list-group-item" href="/app3/#/app/test">Test <i class="fa fa-chevron-right pull-right"></i></a>

Hopefully this can help someone who wants to combine mobile-angular-ui with Laravel!

Thanks to @Ohgodwhy for clarifying that the AngularJS templates need to be in the public/ directory.

Upvotes: 2

Ohgodwhy
Ohgodwhy

Reputation: 50787

So let's say you have this route:

Route::get('/app3', 'RouteController@serveAngular');

Then you have a controller

class RouteController extends BaseController{
    public function serveAngular(){
        return View::make('angular/index');
    }
}

Then you've got

-views
    -angular
        -index.blade.php

Then in your index.blade.php you just include your angular markup

<div ng-app="myApp">

You are not required to put the ng-app definition at the top of the HTML markup, just the top of the application container.

Of course, you'd also have to include your AngularJS so your primary template would contain something like:

@yield('scripts')
</head>

That way you can easily hook into it within your angular template

@section('scripts')
<script src="/path/to/my/AnguularJS.js"></script>
@stop

Hope this helps.

Upvotes: 1

Related Questions