Context: I just got started with AngularJS, starting from a clean generator-angular-fullstack build. As part of the install I went with UI router.
I've set up server API endpoints and tested them in the browser. They all check out.
I'm trying to do a minimal http.post request to call those API endpoints. Via Yeoman I've pre-generated a new route 'signIn' in client/app/signIn (which includes signIn.html, signIn.js, signIn.controller.js, signIn.controller.spec.js, signIn.scss).
Here is what I'm working from:
signIn.html
<script>
var MainCtrl = function($scope, $http) {
$http.post('/api/auth/signin', {auth_token: '5'}).success(function(response) {
$scope.response = response;
});
};
</script>
<body ng-controller="MainCtrl">
<section ui-view>Response: {{response}}</section>
</body>
For completeness (still untouched:)
signIn.js
'use strict';
angular.module('orbitApp')
.config(function ($stateProvider) {
$stateProvider
.state('signIn', {
url: '/signIn',
template: '<sign-in></sign-in>'
});
});
signIn.controller.js
'use strict';
(function(){
class SignInComponent {
constructor() {
this.message = 'Hello';
}
}
angular.module('orbitApp')
.component('signIn', {
templateUrl: 'app/signIn/signIn.html',
controller: SignInComponent
});
})();
I've tried a number of variations on the signIn.html script, no luck so far. I'd like to find the 'native' way to do it, so I'd rather not use jquery. Any advice would be appreciated!
I don't understand exactly what you're trying to do but I hope this code will help you :
signIn.html
<body>
<section ui-view>Response: {{response}}</section>
<a class="btn btn-info" href="#" ng-click="callingPostFct()" role="button">Trigger http post using button as example</a>
</body>
signIn.js
'use strict';
angular.module('orbitApp')
.config(function ($stateProvider) {
$stateProvider
.state('signIn', {
url: '/signIn',
template: '<sign-in></sign-in>'
});
});
signIn.controller.js
'use strict';
(function(){
class SignInComponent {
constructor($scope, $http) {
$scope.callingPostFct = function() {
$http.post('/api/auth/signin', {
//do anything you want with your api endpoint here :
auth_token: '5'
}).success(function(response) {
console.log('post successfully worked !');
$scope.response = response;
});
};
}
}
angular.module('orbitApp')
.component('signIn', {
templateUrl: 'app/signIn/signIn.html',
controller: SignInComponent
});
})();
Note :
Don't put ng-controller="" in your html files because they are already called by the generator and they will be called twice or even more which could produce some trouble in your app and reduce performance also.
In most of case, when you're trying to use <script> tag, you can do it in the controller.
Related
Hi iam using Angular with Require.
Require is managing my dependency sequence. Using lazy loading for loading controller and i was able to load my first home controller but when i wanted to navigate to dashboard controller then iam getting error dashboard controller is not found. hereis code
main.html
<body ng-app >
<div id="ViewPort" ng-view> </div>
</body>
shell.js
define(['mngRoute', 'mngSanitize'], function (ngRoute, ngSantize) {
var CMSapp = angular.module('CMS', ['ngRoute', 'ngSanitize']);
CMSapp.config(function ($routeProvider, $httpProvider) {
console.log($httpProvider);
$routeProvider
// route for the home page
.when('/', { templateUrl: 'App/Partials/home.html', resolve: loader(['Home']) })
.when('/Dashboard', { templateUrl: 'App/Partials/Dashboard.html', resolve: loader(['Dashboard']) })
});
CMSapp.run(function () {
console.log('shell loaded');
console.log(CMSapp);
});
return CMSapp;
Home Controller.js
define(function () {
angular.module('CMS').controller('HomeController', ["$scope", "$http", 'MainService', function ($scope, $http, mainService) {
$scope.message = 'Homess';
$scope.InitializeController = function ()
{
console.log(mainService);
mainService.initializeApplication($scope.initializeApplicationComplete, $scope.initializeApplicationError);
}
$scope.initializeApplicationComplete = function (response) {
console.log('in default initializeApplicationComplete');
}
$scope.initializeApplicationError = function (response) {
console.log('in default intialize error');
}
}]);
});
Home.html
<div data-ng-controller="HomeController" ng-init="InitializeController()">
<span>{{message}}</span>
Dashboardcontroller and dashboard.html are same only difference is the name
define(function () {
angular.module('CMS').controller('DashboardController', ["$scope", "$http", 'MainService', function ($scope, $http, mainService) {
$scope.message = 'Dashboard';
$scope.InitializeController = function ()
{
console.log(mainService);
}
}]);
});
Dasboard html
<div data-ng-controller="DashboardController" ng-init="InitializeController()">
<span>{{message}}</span>
i was able to load home and able to bind with model, but this not in dashboard when i entered localhost:8999/Main.html#/Dashboard in url it gives error.
See the chrome console Full console
Angular, Route, Dasboardcontroller.js homecontroller.js shell.js are loaded successfuly no error in console only error is Dasboard controller is not a function, got defined
When you use ng-app, Angular will search for a module called app. If you want to specify a custom module, you need to tell it: ng-app="CMS"
I hope this works! :)
<body ng-app >
should be
<body ng-app="CMS">
because in your code you declare your module as so.
angular.module('CMS'
Chrome console image console2
You can see my app is loaded bootstrapped and controllers are registered as well
I want to load controllers on the fly when needed rather than loading them in one go. So, for the I've implemented dynamic approach which works fine without any error. It also works well with Ui-Router.
But the problem is in Index.html page. I want to put global (super parent) controller name "appCtrl". As this appCtrl should be initialized when I run my app. For that I need to write like ng-controller="appCtrl" or ng-controller="appCtrl as vm" at body tag.
But when I do it, it gives error that appCtrl is a function, got undefined. I tried sever ways but still unable to identify exact error. I have working on this issue since two to three days but still not able to identify it.
I have made this plunker.
look at body tag of index.html.
main.js
require.config({
paths: {
"angular": "//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.0-rc.1/angular",
"ui-router": "//rawgit.com/angular-ui/ui-router/0.2.15/release/angular-ui-router"
},
shim: {
"angular": {
exports: 'angular'
},
"ui-router": {
deps: ['angular']
}
}
});
define(
['angular',
'app',
'controllers/appCtrl'],
function (angluar, app) {
angular.bootstrap(document, ['MyApp'])
});
app.js
define([
'angular',
'ui-router'
], function (angular) {
var app = angular.module('MyApp', ['ui.router']);
function lazy () {
var self = this;
this.resolve = function (controller) {
return {
ctrl: ['$q', function ($q) {
var defer = $q.defer();
require(['controllers/' + controller], function (ctrl) {
app.register.controller(controller, ctrl);
defer.resolve();
});
return defer.promise;
}]
};
};
this.$get = function (){
return self;
};
}
function config ($stateProvider, $urlRouterProvider,
$controllerProvider, $compileProvider,
$filterProvider, $provide, lazyProvider) {
$stateProvider
.state("home", {
url: "/",
controller: 'homeCtrl',
controllerAs: 'vm',
templateUrl: 'views/homeView.html',
resolve: lazyProvider.resolve('homeCtrl')
});
app.register = {
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service,
constant: $provide.constant
};
}
app.provider('lazy', lazy);
app.config(config);
return app;
});
Index.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.17/require.js" data-main="main.js"></script>
</head>
<body ng-controller="appCtrl as vm"> // I want this to work correctly but it is not getting loaded dynamically. I don't know why. Help me to resolve it.
<a ui-sref="home">go home</a>
<ui-view></ui-view>
{{vm.appVar}}
</body>
</html>
You are actually missing the controller statement in your controller code.
Use the following code
define(['app'], function (app){ //Updated Line
console.log('app controller loaded');
app.controller('appCtrl',ctrl); //New Line added
ctrl.$inject = ['$http'];
function ctrl ($http) {
this.appVar = 'hi from appCtrl';
};
return ctrl;
});
See the plunker
I have tried to lazy load a controller in angularjs app, but got stuck with some problems i.e. view loads after the controller but in console throws exception controller not found.
Here i have attched the sample code.
index.html:
Click here
<div data-ng-view>
</div>
<script src="js/angular.min.js"></script>
<script src="js/angular-route.min.js"></script>
<script src="js/ocLazyLoad.min.js"></script>
<script src="js/app.js"></script>
<script src="js/cofig.js"></script>
</body>
</html>
app.js:
var testapp = angular.module('test',['ngRoute','oc.lazyLoad']);
config.js:
testapp.config(['$routeProvider',function($routeProvider){
$routeProvider.when('/test1',{
templateUrl: 'partials/test.html',
controller: 'testController',
resolve: {
lazy: ['$ocLazyLoad',function($ocLazyLoad) {
$ocLazyLoad.load([{
name: 'test',
files: ['js/testController.js']
}]);
}]
}
})
}]);
console.log error:-
enter code here`Error: [ng:areq] http://errors.angularjs.org/1.3.7/ng/areq?p0=testController&p1=not%20aNaNunction%2C%20got%20undefined
This issue is because of you are loading the controllers lazily. When you load the controller lazily, this will not be available to the main module. So you have to register those controllers.
By attaching the controller provider and provide to the main module, we can use it later to register controller.
In app config,
SampleApp.registerController = $controllerProvider.register;
SampleApp.$register = $provide;
To register controller:
var SampleApp = angular.module('SampleApp');
SampleApp.$register.factory('landingService', ['$http', '$rootScope', function ($http, $rootScope) {
debugger
return {
GetQuestions: function () {
return $http({
url: ""
});
}
}
}]);
SampleApp.registerController('landingController',
['$scope', '$http', 'landingService', function (scope, http, landingService) {
scope.GetQuestions = function () {
landingService.GetQuestions().success(function (data) {
}).
error(function (data) {
});
}
}]);
The following tutorial will help you to implement the Angular Lazy Loading using RequireJS with OcLazyLoad.
Angular Lazy Load implementation
You should add the lazyLoad service to your config injection:
testapp.config(['$routeProvider', '$ocLazyLoad', function($routeProvider, $ocLazyLoad){
$routeProvider.when('/test1',{
templateUrl: 'partials/test.html',
controller: 'testController',
resolve: {
lazy: ['$ocLazyLoad',function($ocLazyLoad) {
$ocLazyLoad.load([{
name: 'test',
files: ['js/testController.js']
}]);
.......
[UPDATED]
I guess you defined your test controller in the js file and want to lazy load the controller. But your code is not correct. Try this:
testapp.config(['$routeProvider', '$ocLazyLoad', function($routeProvider, $ocLazyLoad){
$routeProvider.when('/test1',{
templateUrl: 'partials/test.html',
controller: 'testController',
resolve: {
lazyTestCtrl: ['$ocLazyLoad',function($ocLazyLoad) {
return $ocLazyLoad.load('js/testController.js');
}]
}
You can get the doc from official site.
I'm trying to get to work angular.js, ui-router, and require.js and feel quite confused. I tried to follow this tutorial http://ify.io/lazy-loading-in-angularjs/. First, let me show you my code:
app.js =>
var app = angular.module('myApp', []);
app.config(function ($stateProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
$stateProvider.state('home',
{
templateUrl: 'tmpl/home-template.html',
url: '/',
controller: 'registration'
resolve: {
deps: function ($q, $rootScope) {
var deferred = $q.defer(),
dependencies = ["registration"];
require(dependencies, function () {
$rootScope.$apply(function () {
deferred.resolve();
});
})
return deferred.$promise;
}
}
}
);
app.lazy = {
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
});
Now in my registration.js I have following code:
define(["app"], function (app) {
app.lazy.controller("registration" , ["$scope", function ($scope) {
// The code here never runs
$scope.message = "hello world!";
}]);
});
everything works well, even the code in registration.js is run. but the problem is code inside controller function is never run and I get the error
Error: [ng:areq] http://errors.angularjs.org/1.2.23/ng/areq?p0=registration&p1=not a function, got undefined
Which seems my code does not register controller function successfully. Any Ideas?
P.s. In ui-router docs it is said "If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $routeChangeSuccess event is fired." But if I put the deferred.resolve(); from mentioned code inside a timeOut and run it after say 5 seconds, my controller code is run and my view is rendered before resolve, Strange.
Seems like I ran into the exact same problem, following the exact same tutorial that you did, but using ui-router. The solution for me was to:
Make sure the app.controllerProvider was available to lazy controller script. It looked like you did this using app.lazy {...}, which a really nice touch BTW :)
Make sure the lazy ctrl script uses define() and not require() I couldn't tell from your code if you had done this.
Here is my ui-router setup with the public app.controllerProvider method:
app.config(function ($stateProvider, $controllerProvider, $filterProvider, $provide, $urlRouterProvider) {
app.lazy = {
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
$urlRouterProvider.otherwise('/');
$stateProvider
.state('app', {
url:'/',
})
.state('app.view-a', {
views: {
'page#': {
templateUrl: 'view-a.tmpl.html',
controller: 'ViewACtrl',
resolve: {
deps: function ($q, $rootScope) {
var deferred = $q.defer();
var dependencies = [
'view-a.ctrl',
];
require(dependencies, function() {
$rootScope.$apply(function() {
deferred.resolve();
});
});
return deferred.promise;
}
}
}
}
});
});
Then in my lazy loaded controller I noticed that I had to use require(['app']), like this:
define(['app'], function (app) {
return app.lazy.controller('ViewACtrl', function($scope){
$scope.somethingcool = 'Cool!';
});
});
Source on GitHub: https://github.com/F1LT3R/angular-lazy-load
Demo on Plunker: http://plnkr.co/edit/XU7MIXGAnU3kd6CITWE7
Changing you're state's url to '' should do the trick. '' is root example.com/, '/' is example.com/#/.
I came to give my 2 cents. I saw you already resolved it, I just want to add a comment if someone else have a similar problem.
I was having a very similar issue, but I had part of my code waiting for the DOM to load, so I just called it directly (not using the "$(document).ready") and it worked.
$(document).ready(function() { /*function was being called here*/ });
And that solved my issue. Probably a different situation tho but I was having the same error.
I have a question I would like to ask the community, but am having trouble setting up the required JSFiddle to make it easier to demonstrate the issue. I want to create a fiddle with three views side by side using Angular's ui-router. Seems simple, but for some reason I can't get the views' controller's to initialize. The main app loads, as evidenced by console messages, but I'm stumped.
The Fiddle is here, and for completeness sake, the html and js are here:
HTML:
<div ui-view="top" class="top">
<br />
$scope.testmsg = {{testmsg}}
<br />
$scope.statename = {{statename}}
<br />
top!
</div>
<div ui-view="middle" class="middle">middle!</div>
<div ui-view="bottom" class="bottom">bottom!</div>
JS:
/* myApp module */
var myApp = angular.module('myApp', ['ui.router'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('home', {
url: "/",
views: {
'top': {
url: "",
template: '<div>top! {{topmsg}}</div>',
controller: function ($scope) {
$scope.topmsg = "loaded top!";
console.log("top ctrl!"); // this does NOT show in console
}
},
'middle': {
url: "",
template: '<div>middle! {{middlemsg}}</div>',
controller: function ($scope) {
$scope.middlemsg = "loaded middle!";
console.log("middle ctrl!"); // this does NOT show in console
}
},
'bottom': {
url: "",
templateUrl: '<div>bottom! {{bottommsg}}</div>',
controller: function ($scope) {
$scope.bottommsg = "loaded bottom!";
console.log("bottom ctrl!"); // this does NOT show in console
}
}
},
onEnter: function () {
console.log("entered home state"); // this does NOT show in console
}
});
}])
.controller('MyAppCtrl', function ($scope, $state/*, $stateParams*/) {
$scope.statename = $state.current.name;
$scope.testmsg = "app scope working!";
console.log("MyAppCtrl initialized!"); // this shows in console
$state.go("home");
});
My body tag has the correct (I believe) references to my app and controller: <body ng-app="myApp" ng-controller="MyAppCtrl"></body>... I'm stuck. Any help would be great.
Thanks in advance!
I think your only mistake is in the configuration for the 'bottom' view. You have templateUrl instead of template. After I made this change in your fiddle, all the controllers initialize correctly.
Here's an updated fiddle. But like I said, changing templateUrl to template is the only change. Hope this helps!