Getting Django to play nice with Angular routing - javascript

I have an existing Django project and am adding a new app which consists of an API (using the rest-framework) and an angular app. This app contains one Django template, which simply serves as a way for Angular to hook in, and then work with it's own partials:
{% extends "base.html" %}
{% block content %}
<div ui-view></div>
{% endblock %}
From here, I would like for angular to take over the routing of the application:
$resourceProvider.defaults.stripTrailingSlashes = false;
// Routing
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
$stateProvider
.state('list', {
url: '/routines',
templateUrl: 'static/partials/routine/routine_list.html',
controller: 'RoutineListController',
})
.state('add', {
url: '/routines/add',
templateUrl: 'static/partials/routine/routine_add_edit.html',
controller: 'RoutineAddController',
});
$urlRouterProvider.otherwise('/routines');
This works fine for the first page the app loads, however attempting to navigate to any subsequent page results in Django displaying a 404 error message
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/routines/add
Based on my current (limited) knowledge of both systems, I attempted to specify a url in my Django config that would apply to all routine/* urls and not load a template, allowing angular to request the partial it requires so it can continue running the SPA uninterrupted. However, I was unable to find any information on specifying a URL without a template, leading me to believe that this is not the correct solution.
urlpatterns = [
url(r'^$', views.routineView, name='routine'),
url(r'^/.*$', views.routineView, name='angular'),
Summary:
I would like to use Angular and a Django rest API app to create a web application. However, I would like to keep the rest of my existing Django site and simply add this on (an embedded SPA in my current Django base.html template). How do I set up the routing (on both Angular and Django) so that Django allows Angular to run interrupted once a certain page has been requested (in this case site.com/routines).

As far as I understood, you simply want to use AngularJS with Django Rest API along with Django templates for some routes. I did this before using this https://github.com/mgonto/restangular. All you need to create a service that represent the resource. Here is a sample code for the service in AngularJS:
(function() {
function Course(Restangular) {
var service = Restangular.all("course");
//studentStats refers to the corresponding JS function that will call the API (note API URL is configured in app.js)
//student_stats refers to the corresponding url in Django API
service.addRestangularMethod("studentStats", "get", "student_statuses");
return service;
}
angular.module("YOUR-APP")
.service("Course", ["Restangular", Course]);
}).call(null);

Related

How do frameworks such as AngularJS route requests

Many web frameworks such as AngularJS support "routing" whereby the user can visit the website, and have a template displayed to them based on their request URL. But these frameworks are entirely frontend JS, just simply a 'script src' import, so how does it manage to capture all requests to the website, and then redirect to a js file for processing, etc.
Any response is appreciated, since I have been trying to work out how exactly these frameworks execute the 'capturing' part of routing for some time, but with no luck.
Let me give you a simple model for it.
We can grab the current URL. We can then break that string and we can get different parts separated by '/' Based on which we can put condition which page and what data to show. And when we have decided that we can load our desired page using ajax.
For example my current url is https://www.example.com/module I can get "module" out of this url and then I can load inside the body of my page
$('body').load('module.html');
The following code is from my current work. See how different urls are captured and routed to my specified document. I also get the data from url to use into my ajax requests etc.
app.config(function($routeProvider) {
$routeProvider.when("/", {
templateUrl : "home.html"
}).when("/logout", {
templateUrl : "logout.html"
}).when("/course/:id", {
templateUrl : "course.html"
}).when("/course/:courseId/assignment/:assignmentId", {
templateUrl : "assignment.html"
});
});

How to properly routing for SPA using Angular 1.5?

I'm new to angular. I create a blog for showing my profile.
In my website, I have several component and my app.module has a configuration for the routing, as shown:
app.config(function($locationProvider, $routeProvider){
$locationProvider.html5Mode({
enabled:true,
requireBase: false
})
$routeProvider.
when("/", {
template: "<research-overview></research-overview>"
}).
when("/research-interests", {
template: "<research-interests></research-interests>"
}).
otherwise({
redirectTo: "/"
})
});
Here is an example of my component:
angular.module('researchOverview', [])
.component('researchOverview', {
templateUrl: '/templates/research-overview.html',
});
I tried to locally run the server using python -m SimpleHttpServer
so that I can access my local website using browser to localhost:8000, When I click a link from my homepage, the page is correctly loaded. However, when I initially access my website using different urls (e.g. localhost:8000/testing) Angular route doesn't seem to work properly.
I get this error instead,
How do I set the router so that those urls can be redirected to my homepage?
Given you have enabled html5 mode I think you may need to set your server up so that regardless of the path it will return your index.html file.
For example, when your server receives a request for a resource at localhost:8000/testing it will return index.html.
From the AngularJS documentation:
Using this mode requires URL rewriting on server side, basically you
have to rewrite all your links to entry point of your application
(e.g. index.html). Requiring a tag is also important for this
case, as it allows Angular to differentiate between the part of the
url that is the application base and the path that should be handled
by the application.

Sails.js Single Page Application (SPA) — redirect all missing/unused routes to a single controller action

I'm developing a single page application (SPA) using Sails.js as a backend. All I want is to redirect all routes to a single controller action.
However, when I do the following:
// config/routes.js
module.exports.routes = {
'GET *': 'MainController.application'
};
All requests are getting redirected to my application route, even for static files like CSS/JavaScript, etc. Is there an easy way to fallback to my application route when there is no other means to handle it?
I want:
All static files to be served directly (JS, CSS, HTML partials)
All specific routes to be handled as is
In other case redirect to a single entry-point controller
After thorough re-reading of the docs I've found a skipAssets route parameter.
Here's my new configuration:
// config/routes.js
module.exports.routes = {
'GET *': {
controller: 'MainController',
action: 'application',
skipAssets: true
}
};
Looks like it's working as required.

AngularJS $routeProvider can't load directly to partial

At the minute I'm currently using the $routeProvider to dynamically load sections of the page like so:
$routeProvider
.when('/', {
templateUrl: '/pages/home.html',
controller: 'mainController'
})
.when('/our-business', {
templateUrl: '/pages/our-business.html',
controller: 'businessController',
css: 'css/_business.css'
})
.when('/solutions', {
templateUrl: '/pages/solutions.html',
controller: 'solutionsController'
});
Currently, if I go directly to the index (localhost) and then select 'Our Business' from the navigation menu then Angular handles the location request and the page loads fine, with the URL changing to localhost/our-business. If I then reload, or open this URL directly I get a 404 error - presumably because Apache is trying to open our-business.html which doesn't exist. If I open localhost/#/our-business then the index is loaded and Angular then handles the request. The issue I've got is that this is designed to be a public facing website, so if a user were to copy and paste the URL or share it via email, they'll get a 404 error.
Is there any way to have Apache rewrite URLs to parse them via the index and AngularJS so that we can keep the non-hash style but still have functional URLs?
As said Kailash you can set the locationProvider to html5 mode
$locationProvider.html5Mode(true)
when you bootstrap your angular application.
Then you have to tell your Apache server to send the index.html (entry point of you single page app) for any requested url.
The angular router will then handle the proper route
Nope. Changing the url without the hash reloads the entire page.
The entire point of this $routeProvider is to build single-page app with multiple views.
Basically, having the # in the url is the only way to do that. Changes to a url's hash don't result in a page reload, and allow Angular to load the relevant views.

Makes Angular JS works offline

I am developing a single page application, with help of AngularJS and I'm new to it
I asked the same question before but haven't got any answer so I am rephrasing my question and ask it again
THE QUESTION:
What I need to do is to make my web app enabled to work offline for this purpose the html files which are rendered as view (for example home.html) should be included somehow in the index.html, So when clicking on the some links there should be no need to have access to a html file instead a part of the same page for example a dive will be rendered, what modifications should I make to project to get this done
at the moment I made different html files and use them as templates when rendering views,
the structure of app is like this :
- index.html
- pages
----- home.html
----- profile.html
here is the code for config the routes and controllers and views
var formApp = angular.module('formApp', ['ngRoute']);
formApp.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'main',
controller : 'mainController'
})
.when('/profile', {
templateUrl : 'profile',
controller : 'profileController'
})
});
And and my main.html file for example is like this :
<div class="jumbotron text-center">
<h1>Main Page</h1>
<p>{{ message }}</p>
</div>
َand somewhere in the index.html I have
<div ng-view>
{{ message }}
</div>
The code works properly and everything is fine at the moment
To make your application work offline, you have to cache every file with the html5 cache manifest. Even the .html files, images, css, everything...
The native "old" caching won't work here, because it still requires to communicate with the server to have the "304 Not Modified" http code.
The manifest removes this step and doesn't even ask the server for the resources.
An example manifest:
CACHE MANIFEST
/angular.js
/index.html
/page/home.html
/page/profile.html
NETWORK:
*
How to include and use cache manifest check: http://www.w3schools.com/html/html5_app_cache.asp
For debugging:
Clearing a app cache under chrome enter url "chrome://appcache-internals/"
EDIT: Due to comment and off the topic
Instead of placing the html code in many own html files, you can include them in index.html like this:
<script type="text/ng-template" id="one.html">
<div>This is first template</div>
</script>
Then your templateURL is "one.html" without subpath.
Check docs: https://docs.angularjs.org/api/ng/directive/script
Hint:
You dont need to place any paths there. During rendering phase, angularjs will store every html file in the $templateCache under it's id placed in those script elements.
This might not be 100% applicable to you. Depending on the solution & or platform you're using... But I've got a prototype application that I'm working on currently, built in Angular and Node.
Although this was also my fist attempt at something like this... EG caching all the pages upfront. This seems to work quite well.
All my pages get converted to a cache friendly format during the build phase. But in my solution, they are still regular html pages.
home.tpl.html
<div class="well home-menu">
HOME
</div>
templates.js
angular.module('templates', ['home.tpl.html']);
angular.module("home.tpl.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("home.tpl.html",
"<div class=\"well home-menu\">\n" +
"HOME\n"+
"</div>");
}]);
controller
angular.module('myApp.home', ['templates'])
.config(function ($stateProvider) {
$stateProvider
.state('app.home', {
url: '/home',
templateUrl: 'home.tpl.html',
controller: 'HomeController'
});
})
.controller('HomeController', function ($scope) {
//do something
});
All this magic courtesy of html2js
grunt.loadNpmTasks('grunt-html2js');
...I do believe its possible to achieve this effect in various other ways that doesn't require grunt. For example manually creating the templates in the js file... but I wouldn't dream of recommending that route, as it could turn into a nightmare quickly

Categories

Resources