I have strange problem when loading different templates using Codeigniter and AngularJS. When i click on other link, templates gets redirected on some /undefined link. Let me show you my code.
This is my app.js
var app = angular.module('app', ['ngRoute']);
app.config(function($routeProvider){
$routeProvider.
when('/', {controller:'homeCtrl', templateUrl:'app/templates/home.html'}).
when('/home', {controller:'homeCtrl', templateUrl:'app/templates/home.html'}).
when('/contact', {controller:'contactCtrl', templateUrl:'app/templates/contact.html'}).
otherwise({ redirectTo: '/home'});
});
controllers.js
var app = angular.module('app');
var controllers = {};
controllers.headerCtrl = function($scope, categoriesFactory){
//get available categories
categoriesFactory.getCategoriesList().success(function(data){
$scope.categories = data;
}).error(function(e){
console.log(e);
});
}
controllers.homeCtrl = function($scope, productsFactory){
productsFactory.getlatestProductsList(16).success(function(data){
$scope.products = data;
}).error(function(e){
console.log(e);
});
}
controllers.contactCtrl = function($scope, $http, $location){
//Send message
// creating a blank object to hold our form information.
//$scope will allow this to pass between controller and view
$scope.formData = {};
// submission message doesn't show when page loads
$scope.submission = false;
// Updated code thanks to Yotam
var param = function(data) {
var returnString = '';
for (d in data){
if (data.hasOwnProperty(d))
returnString += d + '=' + data[d] + '&';
}
// Remove last ampersand and return
return returnString.slice( 0, returnString.length - 1 );
};
$scope.submitForm = function(){
$scope.submissionMessage = '';
$http({
method : 'POST',
url : $location.protocol() + '://' + $location.host() + '/server/contact/send_message',
data : param($scope.formData), // pass in data as strings
// set the headers so angular passing info as form data (not request payload)
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function(data){
if(!data.success){
var name = document.getElementById('Name').value;
var email = document.getElementById('email').value;
var subject = document.getElementById('subject').value;
var message = document.getElementById('message').value;
if(name.length == '' && email.length == '' && subject.length == '' && message.length == ''){
$scope.submissionMessage = data.messageError;
}
// if not successful, bind errors to error variables
$scope.errorName = data.errors.name;
$scope.errorEmail = data.errors.email;
$scope.errorSubject = data.errors.subject;
$scope.errorTextarea = data.errors.message;
$scope.submission = true; //shows the error message
}else{
// if successful, bind success message to message
$scope.submissionMessage = data.messageSuccess;
$scope.formData = {}; // form fields are emptied with this line
$scope.submission = true; //shows the success message
$scope.errorName = '';
$scope.errorEmail = '';
$scope.errorSubject = '';
$scope.errorTextarea = '';
}
});
};
}
app.controller(controllers);
Factorys.js
var app = angular.module('app');
//Factory for categories
app.factory('categoriesFactory', ['$http', '$location', function($http, $location){
var factory = {};
factory.getCategoriesList = function(){
return $http.get($location.protocol() + '://' + $location.host() + '/server/api/categories');
}
return factory;
}]);
//Factory for products
app.factory('productsFactory', ['$http', '$location', function($http, $location){
var factory = {};
/*
factory.getProductsList = function(){
return $http.get($location.protocol() + '://' + $location.host() + '/server/api/products');
}
*/
factory.getlatestProductsList = function($n){
return $http.get($location.protocol() + '://' + $location.host() + '/server/api/products/latest/'+$n);
}
return factory;
}]);
My HTML index.html
<!DOCTYPE html>
<html ng-app="app">
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Trade inside europe</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="css/icomoon-social.css">
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700,600,800' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="css/leaflet.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="css/leaflet.ie.css" />
<![endif]-->
<link rel="stylesheet" href="css/main.css" />
<script src="js/modernizr-2.6.2-respond-1.1.0.min.js"></script>
</head>
<body>
<!-- Navigation & Logo-->
<div class="mainmenu-wrapper" ng-controller="headerCtrl">
<div class="container">
<nav id="mainmenu" class="mainmenu">
<ul>
<li class="logo-wrapper"><a ng-href="#/home" target="_self"><img src="img/mPurpose-logo.png" alt="Multipurpose Twitter Bootstrap Template"></a></li>
<li class="active">
<a ng-href="#/home" target="_self">Home</a>
</li>
<li class="has-submenu">
<a href="#">Trade +</a>
<div class="mainmenu-submenu">
<div class="mainmenu-submenu-inner">
<div ng-repeat="c in categories track by $index">
<h4 ng-if="c.parent == 0">{{c.category}}</h4>
<ul ng-repeat="sub_c in categories track by $index">
<li ng-if="sub_c.parent == c.id_category">
<a href="#">{{sub_c.category}}</a>
</li>
</ul>
</div>
</div><!-- /mainmenu-submenu-inner -->
</div><!-- /mainmenu-submenu -->
</li>
<li>
<a ng-href="#/contact">Contact</a>
</li>
</ul>
</nav>
</div>
</div>
<div ng-view></div>
<!-- Footer -->
<div class="footer">
<!-- Footer content -->
</div>
</div>
<!-- Javascripts -->
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>window.jQuery || document.write('<script src="http://code.jquery.com/jquery-2.1.4.min.js"><\/script>')</script>
<script src="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="js/jquery.fitvids.js"></script>
<script src="js/jquery.sequence-min.js"></script>
<script src="js/jquery.bxslider.js"></script>
<script src="js/main-menu.js"></script>
<script src="js/template.js"></script>
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://code.angularjs.org/1.4.8/angular-resource.js"></script>
<script src="https://code.angularjs.org/1.4.8/angular-route.js"></script>
<script src="app/app.js"></script>
<script src="app/controllers.js"></script>
<script src="app/factorys.js"></script>
</body>
</html>
home.html
<div class="section">
<div class="container">
<h2>Latest added</h2>
<div class="row">
<div class="col-md-3 col-sm-6" ng-repeat="p in products track by $index">
<div class="portfolio-item">
<div class="portfolio-image">
<a href="page-portfolio-item.html"><img src="#" alt="#"></a>
</div>
<div class="portfolio-info">
<ul>
<li class="portfolio-project-name">{{p.name}}</li>
<li>{{p.description | limitTo:100}}<span ng-if="p.description.length > 100 ">...</span></li>
<li class="read-more"><a href="page-portfolio-item.html" class="btn">Read more</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
Contact.html
<div class="section section-breadcrumbs">
<div class="container">
<div class="row">
<div class="col-md-6">
<h1>Contact Us</h1>
</div>
</div>
</div>
</div>
<div class="section">
<div class="container">
<div class="row">
<!-- contact content -->
</div>
</div>
</div>
main-menu.js
var mainMenu = (function() {
var $listItems = $( '#mainmenu > ul > li' ),
$menuItems = $listItems.children( 'a' ),
$body = $( 'body' ),
current = -1;
function init() {
$menuItems.on( 'click', open );
$listItems.on( 'click', function( event ) { event.stopPropagation(); } );
}
function open( event ) {
var $item = $( event.currentTarget ).parent( 'li.has-submenu' ),
idx = $item.index();
if($item.length != 0){
if( current !== -1 ) {
$listItems.eq( current ).removeClass( 'mainmenu-open' );
}
if( current === idx ) {
$item.removeClass( 'mainmenu-open' );
current = -1;
}
else {
$item.addClass( 'mainmenu-open' );
current = idx;
$body.off( 'click' ).on( 'click', close );
}
return false;
}
else window.location = $item.find('a').attr('href');
}
function close( event ) {
$listItems.eq( current ).removeClass( 'mainmenu-open' );
current = -1;
}
return { init : init };
})();
So what happens.
I go to my home_page (www.mypage.com) and page renders correctly with link www.mypage.com/#/.
Then i click on let say contact button in menu and i get redirected to http://mypage.com/undefined which provides 404 site.
If i press button back on browser i will be redirected to www.mypage.com/#/contact and page renders correctly
nginx.logs
==> /var/log/nginx/error.log <==
2016/01/06 12:24:46 [error] 11852#0: *142 open() "/var/www/html/testapp.com/public_html/undefined" failed (2: No such file or directory), client: 127.0.0.1, server: testapp.com, request: "GET /undefined HTTP/1.1", host: "testapp.com", referrer: "http://testapp.com/"
==> /var/log/nginx/access.log <==
127.0.0.1 - - [06/Jan/2016:12:24:46 +0100] "GET /undefined HTTP/1.1" 404 200 "http://testapp.com/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36"
Explained in images:
First step opening home page
Second step clicking on button contact
Third step pressing button back
Forth step clicking another button like home
What is happening?
If you need any additional info, please let me know and i will provide. Thank you in advance
I suspect your problem is main-menu.js.
...
else window.location = $item.find('a').attr('href');
...
Your 'Contact' link:
<li>
<a ng-href="#/contact">Contact</a>
</li>
The a
doesn't have a href
property, so it's gonna do:
window.location = 'undefined';
Try adding href="#/contact"
to your Contact link.
I think Angular is bootstrapped client-side when you press the 'back' button, which is why the behaviour isn't occurring when you press 'back' again.
TLDR; change <a ng-href="#/contact">Contact</a>
to <a ng-href="#/contact" href="#/contact">Contact</a>
.
If your Given Code is correct then you have to change this
controllers.contactCtrl = function($scope, $http, $location) {
/// your code as you have used three service $scope, $http, $location components
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With