AngularJS $location directory - javascript

Main page URL: http://localhost:3000/
Current second page URL: http://localhost:3000/#/titleDetails.html
Expected second page URL: http://localhost:3000/titleDetails.html
Currently when I click on the title in my main page, the URL contains an extra /# which causes the page to be redirected to titleDetails.html.
The directory of titleDetails.html and index.html is in the same directory.
May I know how can I fix this?
Original Post: AngularJS Display 1 Post in New Page
app.js
(function () {
angular
.module("BlogApp", [])
.config(function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
})
.controller("BlogController", BlogController);
function BlogController($scope, $http, $rootScope, $location) {
$scope.createPost = createPost;
$scope.deletePost = deletePost;
$scope.editPost = editPost;
$scope.updatePost = updatePost;
$scope.titleDetails = titleDetails;
$scope.postDetail = null;
function init() {
getAllPosts();
}
init();
function titleDetails(post)
{
$scope.postDetail = post;
$location.path('/titleDetails.html');
}
function updatePost(post){
console.log(post);
$http
.put("/api/blogpost/"+post._id, post)
.success(getAllPosts);
}
function editPost(postId){
$http
.get("/api/blogpost/"+postId)
.success(function(post){
$scope.post = post;
});
}
function deletePost(postId){
$http
.delete("/api/blogpost/"+postId)
.success(getAllPosts);
}
function getAllPosts(){
$http
.get("/api/blogpost")
.success(function(posts) {
$scope.posts = posts;
});
}
function createPost(post) {
console.log(post);
$http
.post("/api/blogpost",post)
.success(getAllPosts);
}
}
})();
index.html
<!DOCTYPE html>
<html lang="en" ng-app="BlogApp">
<head>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="app.js"></script>
<title>Title</title>
</head>
<body>
<div class="container" ng-controller="BlogController">
<h1>Blog</h1>
<input ng-model="post.title" class="form-control" placeholder="title"/>
<textarea ng-model="post.body" class="form-control" placeholder="body"></textarea>
<button ng-click="createPost(post)" class="btn btn-primary btn-block">Post</button>
<button ng-click="updatePost(post)" class="btn btn-success btn-block">Update</button>
<div ng-repeat="post in posts">
<h2>
<a ng-click="titleDetails(post)">{{ post.title }} </a>
<a ng-click="editPost(post._id)" class="pull-right"><span class="glyphicon glyphicon-pencil"></span></a>
<a ng-click="deletePost(post._id)" class="pull-right"><span class = "glyphicon glyphicon-remove"></span></a>
</h2>
<em>{{post.posted}}</em>
<p>{{post.body}}</p>
</div>
</div>
</body>
</html>
titleDetails.html:
<!DOCTYPE html>
<html lang="en" ng-app="BlogApp">
<head>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="app.js"></script>
<title>Title</title>
</head>
<body>
<div class="container" ng-controller="BlogController">
<h1>Blog</h1>
<div>
<h2>
<a>{{ postDetail.title }} </a>
</h2>
<em>{{postDetail.posted}}</em>
<p>{{postDetail.body}}</p>
</div>
</div>
</body>
</html>
Console Error in index.html:
angular.js:13708 Error: [$location:nobase] http://errors.angularjs.org/1.5.7/$location/nobase
at angular.js:38
at sf.$get (angular.js:13384)
at Object.invoke (angular.js:4709)
at angular.js:4508
at d (angular.js:4655)
at e (angular.js:4679)
at Object.invoke (angular.js:4701)
at R.instance (angular.js:10234)
at m (angular.js:9147)
at g (angular.js:8510)

Angular has 3 routing operates:
Hashbang Mode
HTML5 Mode
Hashbang in HTML5 Mode
You can configure: $locationProvider.html5Mode(true).hashPrefix('!');
Check documentation

Related

UI-views: loading the url but not the content

Here's my code:
controller.js
angular.module('myApp',['ui.router'])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
// route to show all the polls
.state('polls', {
url: '/polls',
templateUrl: 'views/polls.html',
controller: 'pollsController'
})
// show new polls
.state('new', {
url: '/polls/add',
templateUrl: 'views/newPoll.html',
controller: 'newController'
});
$urlRouterProvider.otherwise('/polls');
})
.controller('pollsController', function($scope,$http) {
$http.get('/polls').then(function(data, status, headers, config) {
$scope.result = data;
}).catch(function(data) {
$scope.result = data;
});
})
.controller('newController',function($scope,$http) {
$http.get('/polls/add').then(function(data,status,headers,config) {
$scope.result = data;
}).catch(function(data) {
$scope.result = data;
});
});
index.html
<!DOCTYPE>
<html>
<head>
<meta charset="utf-8">
<!-- <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootswatch/3.1.1/darkly/bootstrap.min.css"> -->
<link rel="stylesheet" type="text/css" href="views/css/style.css">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.min.js"></script>
<script type="text/javascript" src="controller.js"></script>
</head>
<body ng-app="myApp">
<div id="topheader">
<h1>myApp</h1>
</div>
<div class="topnav" id="topnavigation">
<a ui-sref-active="active" ui-sref="new">Add poll</a>
<a ui-sref-active="active" ui-sref="polls">All polls</a>
</div>
<div class="container">
<div ui-view></div>
</div>
</body>
</html>
polls.html
<div class="content">
<h2>View your polls!</h2>
<div class="allPolls" ng-repeat="item in result.data.polls">
<li> {{item.title}}
</li>
</div>
</div>
newPoll.html
<div class="content">
<form>
Title: <br><input type="text" name="title"><br>
Options (add line break between options): <br>
<textarea type="text" name="options">
</textarea>
<br>
<button type="button">Create new poll</button>
</form>
</div>
So now when I press the "Add poll"-button from the polls-page the page loads a page where is only the topnavigation-bar. When I press the "Add poll"-button again, the page loads the form from newPoll.html.
The url changes on the first click so everything should be working on the first click?

AngularJS Display 1 Post in New Page

I want to display only Test Post 1 in next html page titleDetails.html when user clicks Test Post 1 in index.html
1) titleDetails() in index.html:
<a ng-click="titleDetails(post)">{{ post.title }} </a>
2) controller variables and titleDetails() method:
function BlogController($scope, $http, $rootScope, $location) {
$scope.createPost = createPost;
$scope.deletePost = deletePost;
$scope.editPost = editPost;
$scope.updatePost = updatePost;
$scope.titleDetails = titleDetails;
$scope.postDetail = null;
function titleDetails(post)
{
$scope.postDetail = post;
$location.path('#/titleDetails');
}
3) body in titleDetails.html:
<body>
<div class="container" ng-controller="BlogController">
<h1>Blog</h1>
<div>
<h2>
<a>{{ postDetail.title }} </a>
</h2>
<em>{{postDetail.posted}}</em>
<p>{{postDetail.body}}</p>
</div>
</div>
</body>
FULL CODE:
app.js
(function () {
angular
.module("BlogApp", [])
.controller("BlogController", BlogController);
function BlogController($scope, $http, $rootScope, $location) {
$scope.createPost = createPost;
$scope.deletePost = deletePost;
$scope.editPost = editPost;
$scope.updatePost = updatePost;
$scope.titleDetails = titleDetails;
$scope.postDetail = null;
function init() {
getAllPosts();
}
init();
function titleDetails(post)
{
$scope.postDetail = post;
$location.path('#/titleDetails');
}
function updatePost(post){
console.log(post);
$http
.put("/api/blogpost/"+post._id, post)
.success(getAllPosts);
}
function editPost(postId){
$http
.get("/api/blogpost/"+postId)
.success(function(post){
$scope.post = post;
});
}
function deletePost(postId){
$http
.delete("/api/blogpost/"+postId)
.success(getAllPosts);
}
function getAllPosts(){
$http
.get("/api/blogpost")
.success(function(posts) {
$scope.posts = posts;
});
}
function createPost(post) {
console.log(post);
$http
.post("/api/blogpost",post)
.success(getAllPosts);
}
}
})();
index.html
<!DOCTYPE html>
<html lang="en" ng-app="BlogApp">
<head>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="app.js"></script>
<title>Title</title>
</head>
<body>
<div class="container" ng-controller="BlogController">
<h1>Blog</h1>
<input ng-model="post.title" class="form-control" placeholder="title"/>
<textarea ng-model="post.body" class="form-control" placeholder="body"></textarea>
<button ng-click="createPost(post)" class="btn btn-primary btn-block">Post</button>
<button ng-click="updatePost(post)" class="btn btn-success btn-block">Update</button>
<div ng-repeat="post in posts">
<h2>
<a ng-click="titleDetails(post)">{{ post.title }} </a>
<a ng-click="editPost(post._id)" class="pull-right"><span class="glyphicon glyphicon-pencil"></span></a>
<a ng-click="deletePost(post._id)" class="pull-right"><span class = "glyphicon glyphicon-remove"></span></a>
</h2>
<em>{{post.posted}}</em>
<p>{{post.body}}</p>
</div>
</div>
</body>
</html>
titleDetails.html:
<!DOCTYPE html>
<html lang="en" ng-app="BlogApp">
<head>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="app.js"></script>
<title>Title</title>
</head>
<body>
<div class="container" ng-controller="BlogController">
<h1>Blog</h1>
<div>
<h2>
<a>{{ postDetail.title }} </a>
</h2>
<em>{{postDetail.posted}}</em>
<p>{{postDetail.body}}</p>
</div>
</div>
</body>
</html>
Hope this following steps work for you
Pass post object to titleDetail() function.
In index.html
<a ng-click="titleDetails(post)">{{ post.title }} </a>
In function assign post to $rootScope variable
$scope.titleDetails = function(post) {
$rootScope.postDetail = post;
}
Now your titleDetail.html page controller:
$scope.post = $rootScope.postDetail;
a new scope variable in BlogController
$scope.postDetail = null;
and method titleDetails() be like
$scope.titleDetails = function(post) {
$scope.postDetail = post;
}
and also make change in index.html
<a ng-click="titleDetails(post)">{{ post.title }} </a>

AngularJS Empty Result in Second URL

Expected Result: Opens up Title and Comment in titleDetails.html when Title is clicked in index.html.
Problem: URL changes to http://localhost:3000/titleDetails.html when Title is clicked.
But content remains the same. Page displays 0 post when I refreshed the URL.
Screenshot: (index.html) & (titleDetails.html after clicking a title in index.html)
Screenshot: (after refreshing titleDetails.html when content remains the same after redirecting from index.html)
Code:
1) index.html
<!DOCTYPE html>
<html lang="en" ng-app="BlogApp">
<head>
<base href="/" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="app.js"></script>
<title>Title</title>
</head>
<body>
<div class="container" ng-controller="BlogController">
<h1>Blog</h1>
<input ng-model="post.title" class="form-control" placeholder="title"/>
<textarea ng-model="post.body" class="form-control" placeholder="body"></textarea>
<button ng-click="createPost(post)" class="btn btn-primary btn-block">Post</button>
<button ng-click="updatePost(post)" class="btn btn-success btn-block">Update</button>
<div ng-repeat="post in posts">
<h2>
<a ng-click="titleDetails(post)">{{ post.title }} </a>
<a ng-click="editPost(post._id)" class="pull-right"><span class="glyphicon glyphicon-pencil"></span></a>
<a ng-click="deletePost(post._id)" class="pull-right"><span class = "glyphicon glyphicon-remove"></span></a>
</h2>
<em>{{post.posted}}</em>
<p>{{post.body}}</p>
</div>
</div>
</body>
</html>
2) titleDetails.html
<!DOCTYPE html>
<html lang="en" ng-app="BlogApp">
<head>
<base href="/" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="app.js"></script>
<title>Title</title>
</head>
<body>
<div class="container" ng-controller="BlogController">
<h1>Blog</h1>
<div>
<h2>
<a>{{ postDetail.title }} </a>
</h2>
<em>{{postDetail.posted}}</em>
<p>{{postDetail.body}}</p>
</div>
</div>
</body>
</html>
3) app.js
(function () {
angular
.module("BlogApp", [])
.config(function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
})
.controller("BlogController", BlogController);
function BlogController($scope, $http, $rootScope, $location) {
$scope.createPost = createPost;
$scope.deletePost = deletePost;
$scope.editPost = editPost;
$scope.updatePost = updatePost;
$scope.titleDetails = titleDetails;
$scope.postDetail = null;
function init() {
getAllPosts();
}
init();
function titleDetails(post)
{
$scope.postDetail = post;
$location.path('/titleDetails.html');
}
function updatePost(post){
console.log(post);
$http
.put("/api/blogpost/"+post._id, post)
.success(getAllPosts);
}
function editPost(postId){
$http
.get("/api/blogpost/"+postId)
.success(function(post){
$scope.post = post;
});
}
function deletePost(postId){
$http
.delete("/api/blogpost/"+postId)
.success(getAllPosts);
}
function getAllPosts(){
$http
.get("/api/blogpost")
.success(function(posts) {
$scope.posts = posts;
});
}
function createPost(post) {
console.log(post);
$http
.post("/api/blogpost",post)
.success(getAllPosts);
}
}
})();
AngularJS is a SPA (single page application) oriented. Your links are still tied to the classic multiple page navigation. You will have to re-work your app since $location and $http.get are not the correct services for loading templates and navigation in your scenario.
AngularJS can load the template and update the address bar accordingly as long you use the $routeProvider. Scoth.io made a simple tutorial on how to setup routing.
But you basically have to include ngRoute to your application:
angular.module('ngRouteExample', ['ngRoute'])
Then configure your routes:
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'blogPosts.html',
controller: 'BlogController'
})
.when('/post/:id', {
templateUrl: 'titleDetails.html',
controller: 'TitleController'
});
}
Since the answer can get very long, the following Plunker demonstrates a simple routing implementation for you to learn:
https://plnkr.co/edit/twmbG0G9XjOqF82JtyMC?p=preview

TypeError: undefined is not a function when triggering AJAX requests in ASP.NET

I followed tutorial on this LINK to create AJAX requests on my angularJS appliction (CRUD operations). After I finished coding I tried to perform AJAX request (get all data from database) but when I lunch my application I got this error:
TypeError: undefined is not a function
at new <anonymous> (http://localhost:49510/Scripts/application/controllers.js:4:15)
Does someone knows where's the problem and how to fix it?
Here is code:
controller:
app.controller('ContactsController', [
'$scope', '$http', '$location', 'contactsService',
function ($scope, $location, $http, contactsService) {
$http.get('/contacts/').success(function (data) { //triggers error
alert(data);
$scope.contact = data;
$scope.loading = false;
})
.error(function () {
alert ("An Error has occured while loading contacts!");
// $scope.loading = false;
});
$scope.editContact = function (id) {
$location.path('/edit-contact/' + id);
};
$scope.displayContact = function (id) {
$location.path('/display-contact/' + id);
};
$scope.showDetails = function (id) {
var el = angular.element(document.getElementById('#ct-details-' + id));
el.toggleClass('details-hidden');
}
}
]);
and here is contacts.html template:
<div class="container view">
<header>
<h3>Contacts</h3>
</header>
<div>
<a class="nav-pills hover" href="#/add-contact">Add Contact</a>
</div>
<br /><br />
<div class="row">
<ul class="span5" >
<li class="nav-pills nav-stacked contact-row" data-ng-repeat="contact in contacts | orderBy:'firstName'">
<span id="ct-details-{{contact.id}}" data-ng-click="displayContact(contact.id)" style="cursor:pointer;" class="contact-data details-hidden" href="" >
<span class="span3 contact-name" >{{contact.firstName + ' ' + contact.lastName}}
{{contact.emailAddress}}</span>
</span>
<button class="btn editContact" data-ng-click="deleteContact(contact.id)">Delete</button>
<button class="btn editContact" data-ng-click="editContact(contact.id)">Edit</button>
</li>
</ul>
</div>
</div>
and here is index.cshtml file:
<!DOCTYPE html>
<html ng-app="contactsManager">
<head>
<title>Contacts</title>
</head>
<body>
<div class="navbar navbar-top">
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/custom.css" rel="stylesheet" />
<div class="navbar-inner">
<div class="container">
<h2>Contacts</h2>
</div>
</div>
</div>
<div ng-view class="example-animate-container"
ng-animate="{enter: 'example-enter', leave: 'example-leave'}"></div>
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/Scripts/application/application.js"></script>
<script src="~/Scripts/application/controllers.js"></script>
<script src="~/Scripts/application/contactsService.js"></script>
</body>
</html>
The order of arguments in the controller function has to match the order in the parameter array.
You have mixed the order of $http and $location.
So change your function signature to
app.controller('ContactsController', [
'$scope', '$http', '$location', 'contactsService',
function ($scope, $http, $location, contactsService) {

angularjs view not getting updated

Here is a small self-contained html todo application using routes...
It has two views - list.html and add.html
list.html:
<div>
Add Task
<br />
<br />
<div class="container" id="tasks">
<ul>
<li ng-repeat="task in tasks">
<button ng-show="!task.done" ng-click="markTaskAsDone(task)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-ok-circle"></span></button>
<button ng-show="task.done" ng-click="markTaskAsNotDone(task)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pushpin"></span></button>
<button ng-click="removeTask(task)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-remove-circle"></span></button>
<s ng-show="task.done">{{task.desc}}</s>
<span ng-show="!task.done">{{task.desc}}</span>
</li>
</ul>
<p ng-show="tasks.length == 0">Add few tasks</p>
</div>
</div>
add.html:
<div>
<span class="glyphicon glyphicon-arrow-left"></span> Back
<h2>Add a task</h2>
<div class="form-inline">
<input type="text" data-ng-model="newTask.desc" placeholder="Enter Task..." class="form-control" />
Add
</div>
</div>
I only have one controller.
controllers = {
ToDoController: function ($scope, $timeout, $location) {
//two items in by default...
$scope.tasks = [
{ desc: 'Buy milk', done: false },
{ desc: 'Collect newspaper', done: false }
];
$scope.newTask = { desc: '', done: false };
$scope.addNewTask = function () {
$location.path('/');
console.log('a');
$scope.tasks.push($scope.newTask);
}
$scope.markTaskAsDone = function (task) {
task.done = true;
console.log($scope.tasks);
}
$scope.markTaskAsNotDone = function (task) {
task.done = false;
};
$scope.removeTask = function (task) {
$scope.tasks.splice($scope.tasks.indexOf(task), 1);
};
//called to set newTask
$scope.setNewTask = function () {
$scope.newTask = { desc: '', done: false };
};
}
};
My shell page looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ToDo List</title>
<!-- Bootstrap -->
<link href="Content/bootstrap.min.css" rel="stylesheet">
<link href="Content/bootstrap-theme.min.css" rel="stylesheet">
<style>
#tasks ul {
margin: 0px;
padding: 0px;
list-style: none;
font-size: large;
}
</style>
</head>
<body>
<h1>TODO App</h1>
<div data-ng-app="todoApp">
<div data-ng-view=""></div>
</div>
<script src="Scripts/jquery-1.9.0.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/angular-route.min.js"></script>
<script src="Scripts/todo.js"></script>
<script>
var app = angular.module('todoApp', ['ngRoute']);
app.controller(controllers);
app.config(function ($routeProvider) {
$routeProvider
.when('/list', {
controller: 'ToDoController',
templateUrl: 'partials/list.html'
})
.when('/add', {
controller: 'ToDoController',
templateUrl: 'partials/add.html'
})
.otherwise({ redirectTo: '/list' });
});
</script>
</body>
</html>
Issue:
When I load index.html its shows the list.html. The two default items I've put shows up. I click on Add and navigate to the second view (add.html), enter details and click on the Add button in that page...I navigate to the list.html view, but its still showing the old list...not the updated list...
Surely missing some api call to do the update to the view...else this page is coming from some cache. What is the correct way to do this?
ToDoController is instantiated twice and separately for your two views. To maintain 1 instance of the controller to control both views, don't declare it in your routing, but declare it on a parent tag of the views.
For instance, like this:
<div data-ng-app="todoApp" data-ng-controller="ToDoController">
<div data-ng-view></div>
</div>
Even better is to write separate controllers for each view to put the view-specific logic into, and have 1 parent controller to store values that both controllers should have access to.
Another way to share scope among isolated controllers is using $rootScope, but you should normally try to avoid using that (like you would try to avoid using global variables in any programming language).

Categories

Resources