I'm rendering template using ngRoute - $routeProvider and I'm trying to render respective controller along with the template. $routeProvider is pointing to that controller and so it gives me an error controller is undefined because I think the App is trying to call the controller before it receives the template.
The templateCtr definition is in the separate JS file.
app.js
...
$routeProvider
.when('/template', {
templateUrl: '/template.html',
controller: 'templateCtr'
})
;
template.html
...
<script src="templateCtr.js"></script>
templateCtr.js
var myApp = angular.module('myApp'); //Getting module reference
myApp.controller('templateCtr', ['$scope', function($scope){
...
}]);
I also came across resolve property using which can load data to be used in controller before view is generated but for that too controller has to present in the memory.
Someone please point me to the correct direction. Thanks!
Related
Question Background:
I am using AngulaJS's UI Router for the first time to create two views within my app.
The Issue:
Plunker link: https://plnkr.co/edit/2XAKa6mDCUyzyOPz2CNK
I feel I'm missing something simple here but I cannot get any route to render the specified html templates set in the app.js.
Eventually I want the Update.html template to render when the submit fucntion of the home.html (search()) is clicked but first off I need to be able to actually render a single view which I currently cannot.
I would expect on-load for the route to render up the home.html page but it wont:
Any help sorting this will be much appreciated.
app.js:
angular
.module('app', [
'ui.router'
])
.config(['$urlRouterProvider', '$stateProvider', function($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'home.html',
controller: 'HomeController'
})
.state('update', {
url: '/update',
templateUrl: 'Update.html',
controller: 'UpdateController'
})
}])
Looking at your plunker briefly, it looks like your controller files are creating new angular apps with the same name. They were overriding each other so the .config() block didn't exist in the final app. I have updated the controller files in this plunker and it seems to be rendering the first ui view fine:
https://plnkr.co/edit/cdpWWOaBJWL3dONtIXzv?p=preview
Notice in the controller files, the angular.module('app') no longer has the second argument ['ui-bootstrap'] which was causing a new angular app to be created for each controller file. Check it out here in the angular docs.
Beware that using angular.module('myModule', []) will create the module myModule and overwrite any existing module named myModule. Use angular.module('myModule') to retrieve an existing module.
Hope this helps!
For some reason im not sure about my ngRoute here is not working properly. Please help me thankyou. Here is my cloud9 file where you can see live preiview and edit code. And here is my script.js:
var app = angular.module('ChattApp', ["firebase", "ngRoute"])
app.config(["$routeProvider", function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'HtmlFiles/login.html',
controller : 'LoginController.js'
})
.otherwise({
redirectTo: '/'
})
//Talk In Chat/Group Chat. I have to go to school now..
}]
)
app.factory("Auth", ["$firebaseAuth",
function($firebaseAuth) {
var ref = new Firebase("https://uniquecoders.firebaseio.com/");
return $firebaseAuth(ref);
}
]);
Remove app definition in all controller files.. as app is already defined in another script.. the cause is that the variable is being redefined for each loaded controller file..
please check http://www.w3schools.com/js/js_scope.asp for variable scope lifetimes
Controller inside the object for the ".when" method takes controller name which is registered via angular not a 'js' file containing the controller's code.
When you register the controller you use the method Controller(name, constructor). Then name you place as the first argument is the "name" of the controller that you are registering with angular.
controller : 'LoginController.js'
Should be:
controller : 'LoginController'
References: Route Docs, Controller Docs
Search for "Route" on this page and then look at the controller object properties.
I am kind of new to the AngularJS framework and I am trying to migrate my test project using the standard router to use the UI-router, but I get the following error:
Error: [ng:areq] Argument 'mainCtrl' is not a function, got undefined
What I have done so far is:
Controller:
// mainCtrl.js
angular.module("sm-web")
.controller('mainCtrl',['$scope',
function($scope) {
...
}]);
Router:
angular.module('sm-web', ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function( $stateProvider, $urlRouterProvider ) {
$urlRouterProvider.otherwise('root');
$stateProvider
.state('root', {
url: '',
templateUrl: path + 'ng/sm/view/main.html',
controller: 'mainCtrl'
});
}]);
Index:
<body ng-controller="mainCtrl">
<main-menu></main-menu>
<div class="container">
<div ui-view></div>
</div>
</body>
This works when I use the standard router, but not with the UI-router. Does anyone have any idea of what I am doing wrong?
It seems you have an issue w/the order you declare things. For you to declare the module "sm-web" you need to do this:
angular.module('sm-web', ['ui.router']);
Note that the presence of that 2nd array argument is what tells Angular that you're declaring the module (eg. creating a new module). When you leave that 2nd argument out, you're retrieving the module you previously declared.
So with that in mind, look at how it all is coming together in your code:
To declare the controller, you retrieve the module "sm-web" (by leaving off the 2nd array arg).
When configuring the router states, you declare a new module "sm-web". But note that immediately after you declare this new module, you try to register a state with the controller named "mainCtrl" -- but that doesn't exist yet.
You need to create the module somewhere before doing all of the above. After creating the module, then register the controller on the module. Finally, with the controller defined, then you can register the state that uses the controller.
There's too many ways to solve this ordering problem, so I'm not going to suggest anything further. It depends on what files the code lives in and the order you load those files in index.html.
In order to avoid your problem change your code by the following code:
// mainCtrl.js
angular.module("sm-web")
.controller('mainCtrl',['$scope',
function($scope) {
...
}]);
This is my index.js file
'use strict';
angular.module('wildenglish', ['ngAnimate', 'ngTouch', 'restangular', 'ngRoute', 'ui.bootstrap'])
.config(function ($routeProvider, RestangularProvider) {
RestangularProvider.setBaseUrl('https://www.googleapis.com/calendar/v3/calendars/googleCalendarID');
$routeProvider
.when('/', {
templateUrl: 'app/main/main.html',
controller: 'MainCtrl',
resolve: {
calendarEvents: function(Restangular){
return Restangular.one('eventsAUTHKEY').get();
}
}
})
.otherwise({
redirectTo: '/'
});
})
And my main controller.js
'use strict';
angular.module('wildenglish')
.controller('MainCtrl', function(Restangular, calendarEvents) {
var self = this,
events = calendarEvents,
items = events.items;
});
The Error I'm receiving when I try to use in the HTML is:
Error: [$injector:unpr] Unknown provider: calendarEventsProvider <- calendarEvents <- MainCtrl
So I am trying to figure out how I can utilize the information that I am getting back from that Promise which I can log in the console to be accessible to the HTML via the controller
Do I need a service or factory? and where would that go?
Thank you in advance for your help
Assign the events returned by the resolved promise to your controller scope. You'll need to change the depencies your injecting into your controller. You can leave out Restangular since you are resolving your promise in your route but you do need $scope:
angular.module('wildenglish').controller('MainCtrl', function($scope, calendarEvents) {
// i'm assuming the following logs your events to your console
// if not you're having a problem with your Restangular request
console.log(calendarEvents);
// Assign calendarEvents to your $scope
$scope.events = calendarEvents;
});
Now you can use the events in your HTML template (assuming each event has a property called 'name'):
<ul>
<li ng-repeat="event in events">{{event.name}}</li>
</ul>
Sorry, I missed the answer above which is already the correct answer.
There was a similar problem here:
AngularJS, resolve and unknown provider
Basically if you are using the routeProvider to assign your controller in your script file you cannot use ng-controller in your template.
I'm a beginner in the AngularJS environmnent. In the interest of my company, I would like to combine the power of the Angular framework with the Dustjs templating engine.
The problem is : Dustsjs is compiling files to .js files (I have a Grunt task which is doing that for me in my public folder), not in .html. And, in the documentation of $routeProvider, the 'templateUrl' or 'template' parameters are looking for .html templates.
My app.js :
var app = angular.module('myApp', []);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {
template: 'views/myView.js',
controller: 'HomeController'
});
}]);
As you can imagine, I have a weird result since my .js is injected without being parsed.
http://i.stack.imgur.com/5JkRx.jpg
So, my two questions are :
- Am I doing it right to put the .js file path inside the template of routeProvider, or is there another way to get and correctly display the view? In short, what did I do wrong?
- Are there any best practices for combining these two technologies?
Am I doing it right to put the .js file path inside the template of routeProvider, or is there another way to get and correctly display
the view? In short, what did I do wrong?
No you are not right in putting the .js file path. Angular expects it to a HTML markup.
template: '<div>content</div>',
and
templateUrl : 'views/myview.html'
would be acceptable values.
Are there any best practices for combining these two technologies?
One of the ways to go would be to use dust templates as the outer template and let angular routeProvider take care of rendering the dynamic content to be parsed by angular. For example,
home.dust
<html>
<head>
<title>{page_title}</title>
</head>
<body ng-app="myApp">
{>header/}
<div ng-view></div>
{>footer/}
</body>
</html>
header.dust
<div id="menu">Menu</div>
footer.dust
<div id="copyright">Footer</div>
view/myView.html
<div id="content">Hi ((username))</div>
app.js
var app = angular.module('myApp', []);
app.config(['$routeProvider', '$interpolateProvider', function ($routeProvider, $interpolateProvider) {
//This is required as dust templates also '{' and '}' for interpolation
$interpolateProvider.startSymbol('((').endSymbol('))');
$routeProvider.when('/', {
templateUrl: 'views/myView.html',
controller: 'HomeController'
});
}])
.controller('HomeController', function($scope){
$scope.username = "John Doe";
});