Ui-sref not generating clickable links/not working - angularjs

I used ng-route for this before and it worked fine, but with UI Router, the links are not clickable anymore, or at least most of the time they aren't. When they are, which is very random, they don't display the html templates I'm using.
HTML:
<head>
<title>Tutorial</title>
<script src="lib/angular/angular.js"></script>
<script src="lib/angular/angular-ui-router.min.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
</head>
<body>
<ng-view></ng-view>
<ul class="menu">
<li><a ui-sref="view1">view1</a></li>
<li><a ui-sref="view2">view2</a></li>
</ul>
.js
angular.module('myApp', [
'myApp.controllers',
'ui.router'
]);
angular.module('myApp').config(function($stateProvider, $urlRouterProvider) {
$stateProvider.state('view1',{
url: '/view1',
controller:'Controller1',
templateUrl:'/view1.html'
}).state('view2', {
url: '/view2/:firstname/:lastname',
controller: 'Controller2',
resolve: {
names: function() {
return ['Misko', 'Vojta', 'Brad'];
}
},
templateUrl: '/view2.html'
});
$urlRouterProvider.otherwise('/view1');
});
angular.module('myApp.controllers', []).controller('Controller1', function($scope, $location, $state) {
$scope.loadView2=function() {
$state.go('view2', {
firstname: $scope.firstname,
lastname: $scope.lastname
});
};
}).controller('Controller2', function($scope, $stateParams, names) {
$scope.firstname = $stateParams.firstname;
$scope.lastname = $stateParams.lastname;
$scope.names = names;
});
I'm following the instructions in the SitePoint ebook on AngularJS, so I'm not really sure what I'm doing wrong or what I missed.
http://plnkr.co/edit/amh3nZmyB7lC2IQi3DIn

I don't see a ui-view anywhere in your markup, so your states' views are most likely not being rendered and injected.
You should not need ng-view. A single ui-view should exist in your main HTML file. Your top level states will be rendered and injected there. States can have substates, and each template of a state which has a substate should have a ui-view of its own where its rendered substates will be injected.
Look through ui-router's readme for the basics of getting it working. Also, they have a good demo app, the source of which really helped me understand what this state routing engine is about and how to use it.

Helpful info, hopefully...
Although the answers above are correct (missing ui-view, referencing ui.router, etc.), I have run into situations where other problems with the load of a view will cause links to not be generated. For example, this morning I forgot to reference the module angular-cache and was running into a problem with CacheFactory not loading (completely unrelated to ui.router). Until the references were resolved, ui.router was dead in the water.

Related

Angular js controller not working after modularizing app

I'm new to angularjs and followed the tutorial here from w3schools to create my first simple Angularjs app and it worked fine. After going through the official angularjs tutorial I decided to modularize my app but now its not working. Currently I m getting the error
"The controller with the name 'redController' is not registered."
I want to display a message in component 'red' using its controller. I tried altering many parts of the code only to get new errors and it seems I have messed up modularizing :|
I'm using v1.6.9
Here is my directory structure
app/
scripts/
angular.min.js
angular-route.js
blue/
blue.template.html
red/
red.template.html
red.module.js
red.component.js
app.config.js
app.module.js
index.html
and source files :
app.config.js
angular
.module("myApp", [ 'red','ngRoute' ])
.config(function($routeProvider) {
$routeProvider
.when("/red", {
templateUrl : "red/red.template.html",
controller: "redController"
})
.when("/blue", {
templateUrl : "blue/blue.template.html"
});
});
app.module.js
angular.module('myApp', [
'red',
'ngRoute'
]);
index.html
<!DOCTYPE html>
<html>
<script src="scripts/angular.min.js"></script>
<script src="scripts/angular-route.js"></script>
<script src="app.module.js"></script>
<script src="app.config.js"></script>
<script src="red/red.module.js"></script>
<script src="red/red.component.js"></script>
<body ng-app="myApp">
Red
Blue
<div ng-view></div>
<p>Click on the links to navigate "</p>
</body>
</html>
red.template.html
<h1>red</h1>
<p>{{msg}}</p>hell
red.module.js
angular.module('red', [ 'ngRoute' ]);
red.component.js
angular.module('red').component('red',{
templateUrl: 'red/red.template.html',
controller: function redController() {
this.msg = "this is red";
console.log("Hi");
}
});
You are delcaring the module again and again in each .js files, declare only in one .js file and use it in rest of the fields.
change your red.module.js as,
angular.module('red', []);
your app.config.js should be as,
angular
.module("myApp")
.config(function($routeProvider) {
$routeProvider
.when("/red", {
templateUrl : "red/red.template.html",
controller: "redController"
})
.when("/blue", {
templateUrl : "blue/blue.template.html"
});
});
and change the order as follows,
<script src="red/red.module.js"></script>
<script src="app.module.js"></script>
<script src="app.config.js"></script>
<script src="red/red.component.js"></script>
Change red.component.js as follows
angular.module('red')
.component('red',{
templateUrl:
'red/red.template.html',
})
.controller("redController",function($scope)
{
$scope.msg ="This is red";
});
First of all, as #Sajeetharan you're defining the myApp module twice. Inside your app.config.js and also in app.module.js. If you use angular.module with 2 parameters angular.module('app', []) you're setting the module, if you use angular.module('app') it'll work as a getter. So, in your app.config.js you should use the getter to configure your app.
Once you did that, you can configure your route to something like this:
angular.module('myApp').config(function($routeProvider){
$routeProvider.when('/red', { template: '<red></red>'});
})
I would use this approach since you defined the component in another module.
If you still want to use the approach you've implemented to set both the templateUrl and controller in the $routeProvider, you'll have to change your red component declaration to something like this:
angular.module('red')
.component('red', { templateUrl: 'red/red.template.html'})
.controller('redController', function(){
this.msg = 'This is red.';
});
I'vent tested this second approach as for me the first makes more sense.

Angularjs routing

I am learning Angularjs and having problem with routing. I write up a very simple slim demo example which uses out of the box MVC5. The home page display fine but when I click on the About link it doesn't show the About page and AboutController break point is not hit. And got the following error in Console
Error: [$compile:tpload] Failed to load template: templates/indexView.html (HTTP status: 404 Not Found).
If I swap the two route, then my About page is displayed but got the error when clicking Home link so I am sure the html can be loaded. What do I need to do in order to get the routing to work?
Below is the index.cshtml
#{
ViewBag.Title = "Home Page";
ViewBag.InitModule = "homeIndex";
}
#section Scripts {
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/js/home-index.js"></script>
}
<div data-ng-view=""></div>
Below is the About.cshtml
#{
ViewBag.Title = "About Page";
ViewBag.InitModule = "homeIndex";
}
#section Scripts {
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/js/home-index.js"></script>
}
<div data-ng-view=""></div>
below is the home-index.js
// home-index.js
var module = angular.module("homeIndex", ["ngRoute"]);
var angularFormsApp = angular.module('homeIndex', ["ngRoute"]);
angularFormsApp.config(["$routeProvider",
function ($routeProvider) {
$routeProvider
.when("/", {
templateUrl: "templates/indexView.html",
controller: "HomeController"
})
.when("/About", {
templateUrl: "templates/aboutView.html",
controller: "AboutController"
});
}]);
angularFormsApp.controller("HomeController",
["$scope",
function ($scope) {
var x = 1;
}]);
angularFormsApp.controller("AboutController",
["$scope",
function ($scope) {
var x = 1;
}]);
The var x=1 has no meaning just for me to set a break point.
Below is indexView.html
<h3>Arrived at Index Page</h3>
aboutView.html
<h3>About Page</h3>
I also have the below in the _Layout.cshtml html tag to hook in angular
data-ng-app="#ViewBag.InitModule"
The problem seems to be that MVC is handling the routing that you expect to be handled by Angular.
Have a look at this question for some more information about having Both AngularJS and MVC in the same project:
Should I be using both AngularJS and ASP.NET MVC?
Here is a nice guide to getting started using the two together, it specifically touches on the routing as well:
Getting started with AngularJS and ASP.NET MVC
I hope that helps, please let us know if you need more information, or if something is not clear.

Gulp, browser sync does not work with angularjs ng-view

I am trying to set up a project using gulp and browser sync with angularjs. I cannot get browser sync to work correctly when I use the ng-view tag in my index.html file. This is the error I get in my browser console when I run browser sync:
Uncaught TypeError: Cannot read property 'data1457531805746' of null
coming from browser-sync-client.2.11.1.js:204 It works as expected, page loads fine, when ng-view/ngRoute is not used.
These are my files:
./gulpfile.js
// Spin up a server
gulp.task('browserSync', function() {
browserSync.use(spa({
selector: "[ng-app]" //Only needed for angular apps
}));
browserSync.init({
port: 8080,
server: {
baseDir: path.src
}
})
});
// Watch for changes in files
gulp.task('watch', ['browserSync'], function() {
// Watch .js files -- removed for brevity
});
// Default Task
gulp.task('default', ['watch']);
./app/controllers/controllers.js
'use strict';
/* Controllers */
var dc4SearchControllers = angular.module('dc4SearchControllers', []);
dc4SearchControllers.controller('CompanySearchCtrl', ['$scope', '$http',
function($scope, $http){
$scope.test = 'Hello, world!';
}]);
./app/index.html
<html ng-app="dc4SearchApp">
<head>
<link href="/bower_components/webui-core/dist/webui-core.min.css" rel="stylesheet">
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/angular-route/angular-route.min.js"> </script>
<script src="/bower_components/lodash/lodash.min.js"></script>
<script src="/bower_components/webui-core/dist/webui-core.min.js"></script>
<script src="app.js"></script>
<script src="controllers/controllers.js"></script>
</head>
<body ng-view>
</body>
</html>
./app/app.js
'use strict';
/* App Module */
var dc4SearchApp = angular.module('dc4SearchApp', [
'ngRoute',
'dc4SearchControllers'
]);
dc4SearchApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/company-search', {
templateUrl: 'views/company-search.html',
controller: 'CompanySearchCtrl'
}).
otherwise({
redirectTo: '/company-search'
});
}]);
./app/views/company-search.html
<div ng-controller="CompanySearchCtrl">
{{test}}
<div class="spinner spin"> </div>
</div>
I am hoping this is just something silly and easy that I am over looking and haven't tried yet! Thanks in advance.
"Browsersync works by injecting an asynchronous script tag right after the body tag during initial request. In order for this to work properly the body tag must be present. Alternatively you can provide a custom rule for the snippet using snippetOptions"
https://www.npmjs.com/package/browser-sync
It seems Browsersync is reloading the body tag. Have you tried moving the ng-view to another child div ?

using angular-ui-router with express/node, file structure

I am following this tutorial, and I have an app structure like this. I've tried to show only the relevant bits as it is sort of a lot of code.
/app
/views
index.ejs
/config
express.js
/public
/external_libs
angular.js
angular-ui-router.js
/js
app.js
controllers.js
/partials
home.html
server.js
Inside my express.js (relevant bit)
app.use(express.static('./public');
I am able to set up my angular controllers, so I know this directory is being hit. For example, my index.ejs
<html ng-app="myapp">
<head>
<script src="external_libs/angular.js"></script>
<script src="external_libs/angular-ui-router.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"</script>
</head>
<body ng-controller= "MainCtrl"> <!-- an alert in my controller fires, so I know the public directory is accessible, at least the js folder-->
<div ui-view></div>
</body>
</html>
In my app.js
var app = angular.module('myapp', ['ui.router']);
app.config([
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'partials/home.html'
});
}
]);
In controllers.js
var app = angular.module('myapp', []);
app.controller('MainCtrl', [
'$scope', function($scope) {
alert("This alert is indeed alerted");
}
]);
home.html
<h1> This is a test to see if the view on index.ejs is being populated </h1>
I have tried many different combinations for the "templateUrl" inside app.js, including
"partials/home.html"
"/partials/home.html"
"../partials/home.html"
None of these result in home.html being placed inside the div ui-view element on my index.ejs page. I realize I have posted a somewhat limited amount of code, but the fact that I am able to hit my controllers and see an alert message leads me to believe that I am almost there. I am using server side routing to render the initial index.ejs, but other than that I want to handle things client side. Does anyone know how to make angular-ui-router locate my partial with this set up?
The problem is with your controller declaration. Rather than referencing the module you recreate it (and override the existing module) by including the square brackets.
If you rewrite your controller as below it should work:
var app = angular.module('myapp');
app.controller('MainCtrl', [
'$scope',
function($scope) {
alert("This alert is indeed alerted");
}
]);
For more info, check out "Creation versus Retrieval" at https://docs.angularjs.org/guide/module

Angular Scope Directives

Angular Structural Question
I am new to angular.js and am just wondering how to go about performing a certain situation.
So basically, what I have got is a container:
<div ng-controller="ContainerController">
<container></container>
</div>
And the container controller and directives.
<script type="text/javascript" src="ContainerController.js"></script>
<script type="text/javascript" src="ContainerDirectives.js"></script>
Now the directives replaces the <container> tag with an example html: <example>{{ data }}</example>
Now within the scope of the ContainerController I have defined data as a string. (This is all example purposes). However when the directive accesses replaces it, it is unable to find the variable, due to scope.
The reason that this happens is because the ContainerDirective script's scope is not within the ContainerController scope. Meaning it is unable to access the variable.
Im just not sure on structure practices for these kinds of situations. Where do I put everything so the ContainerDirective can access the ContainerController scope.
I hope i have explained everything good enough
EDIT:
Test.js
(function(){
angular.module('test', []);
})();
TestController.js
(function(){
angular
.module('test')
.controller('TestController', [
'$scope',
TestController
]);
function TestController($scope) {
$scope.test = 'test';
}
})();
TestDirective.js
(function(){
angular.module('test').directive('test', function () {
return {
replace: true,
templateUrl: 'src/test/view/test.html',
link: function (scope, element, attrs) {
}
};
});
})();
test.html
<example>ClickMe</example>
index.html - body
<body ng-app="App" layout="row" ng-controller="TestController as page">
<test></test>
<script src="src/test/Test.js"></script>
<script src="src/test/TestController.js"></script>
<script src="src/test/TestDirective.js"></script>
<script type="text/javascript">
angular
.module('App', ['test']);
</script>
</body>
For reasons I have renamed certain variables and deleted a lot of data, but this is the core, and I am struggling to see anything wrong with this.
Error: [$interpolate:noconcat] Error while interpolating: abc/{{test}}
Strict Contextual Escaping disallows interpolations that concatenate multiple expressions when a trusted value is required.
So I figured out what was wrong in the end. Basically angular wont allow iframe of another location to be printed unless you first:
Give them the full url.
Then allow external url as a trusted website.
TO do this I had to basically add:
in the Test.js
angular.module('test', []).config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist($sceDelegateProvider.resourceUrlWhitelist().concat([
'http://www.test.com/**'
]));
});
This basically took my whitelist and concatinated the new url to it.
Then inside test.html:
<example><iframe ng-src={{src}}></iframe></example>

Resources