I am trying to create a seed application using Angular JS,RequireJS & Framework 7. I have so far created the following folder structure.
My main folder looks like below:
and my scripts folder looks like this :
and my libraries are :
I was able to the view -> controller flow working properly. But when I try to inject a service object to the controller I get the following error.
I am sure I must be missing something. I have given my code below:
require-main:
(function() {
require.config({
baseUrl: "scripts",
// alias libraries paths
paths: {
'angular': '../libs/angular',
'angular-route': '../libs/angular-route',
'angular-animate':'../libs/angular-animate',
'angularAMD': '../libs/angularAMD.min',
'Framework7':'../libs/framework7',
'UserController':'controller/UserCtrl',
'WebCallManager':'services/WebCallManager'
},
// Add angular modules that does not support AMD out of the box, put it in a shim
shim: {
'angularAMD': ['angular'],
'angular-route': ['angular'],
'angular-animate':['angular'],
'Framework7':{exports: 'Framework7'}
},
//kick start application
deps: ['app']
});
require(['Framework7'], function(Framework7) {
f7 = new Framework7({
modalTitle: 'Seed App',
swipePanel: 'left',
animateNavBackIcon: true
});
return {
f7: f7
};
});
})();
app.js :
define(['angularAMD', 'angular-route','angular-animate'], function (angularAMD) {
var app = angular.module("app", ['ngRoute','ngAnimate']);
app.config(function ($routeProvider) {
$routeProvider.when("/", angularAMD.route({ templateUrl: '../pages/login.html',controller: 'UserController'}));
$routeProvider.when("/login", angularAMD.route({ templateUrl: '../pages/home.html', controller: 'UserController'}));
});
angularAMD.bootstrap(app);
return app;
});
UserController :
define(['app'], function (app) {
app.register.controller('UserController', function ($scope,$location,webcallService) {
$scope.loginUser = function(){
console.log("Login User Called...");
$location.path('/login').replace();
console.log("View Navigated...");
};
$scope.slidePanel = function(){
f7.openPanel('left');
};
$scope.doWebCall = function(){
console.log("Doing the Web Call...");
webcallService.sendGetRequest();
};
});
});
WebCallManager.js (Service)
define(['app'], function (app) {
app.service('webcallService', function() {
var self = this;
self.sendGetRequest = function() {
console.log("Sending HTTP Get Request");
}
self.sendPostRequest = function() {
console.log("Sending HTTP Post Request");
}
});
});
And my pages :
index.html:
<!DOCTYPE html>
<html>
<head>
<script data-main="scripts/main" src="libs/require.js"></script>
</head>
<body>
<div>
<div class="slide-animation page-content" ng-view ></div>
</div>
</body>
</html>
login.html:
<div class="content-block login-input-content">
<div class="store-data list-block">
<div>
<input type="text" class="login-name" placeholder="Username">
</div>
<div>
<input type="password" class="password" placeholder="Password">
</div>
<a class="multi-language" href="#"><i class="icon ios7-world-outline"></i><span>english</span></a>
</div>
</div>
<div class="content-block login-btn-content">
<button ng-click="loginUser()" class="button button-big button-submit login-submit">Login</button>
</div>
Home.html:
<div>
<h3>Welcome to Mobility In Angular-JS</h3>
<div class="content-block login-btn-content">
<button ng-click="doWebCall()" class="button button-big button-submit login-submit">Send Get</button>
<br/><br/>
<button ng-click="doWebCall()" class="button button-big button-submit login-submit">Send Post</button>
</div>
Could Anyone help me out ??. YOu can also download and run the entire project here.
You are registering the service as webcallService:
app.service('webcallService', function() {
But inject the $webcallService in the controller:
app.register.controller('UserController', function ($scope, $location, $webcallService) {
Choose one, the one without $ is recommend though, so declare your controller with webcallService:
app.register.controller('UserController', function ($scope, $location, webcallService) {
EDIT: Found one more problem, after reading the angularAMD documentation, it seems you have to add the requirejs module WebCallManager that contain the webcallService angularjs service as a dependency in define() as well.
Therefore, it should be like this:
define(['app', 'WebCallManager'], function (app) {
app.register.controller('UserController', function ($scope,$location,webcallService) {
Otherwise, the module WebCallManager will not be loaded on-demand.
EDIT: Found the third problem, you register the controller via app.register, but register the service directly via app.. You need to be consistent here, but the app.register has been deprecated (See this thread).
Therefore the best would be removing the app.register like this:
app.controller('UserController', ..
And in app.js change from:
angularAMD.bootstrap(app);
return app;
to
return angularAMD.bootstrap(app);
Hope this helps.
Related
I already tried to copy/paste the example code on the webpage: https://weihanchen.github.io/angular-screenshot/
The thing is they are using a whole controller for it, and I have my controllers separated by views. This is how I add them to my "main" js:
.state("main.pallet", {
url: "/palletize",
templateUrl: "app/views/pallet.html",
data: {pageTitle: 'Entarimado.'},
controller: "Pallet",
resolve: {
deps: ['$ocLazyLoad', function($ocLazyLoad) {
return $ocLazyLoad.load({
name: 'TepaPrime',
insertBefore: '#ng_load_plugins_before', // load the above css files before '#ng_load_plugins_before'
files: [
'app/js/filters/filters.js',
'app/js/directives/numericFormat.js',
'app/js/directives/trimText.js',
'app/js/directives/nextOnEnter.js',
'app/js/factories/crud.factory.js',
'app/js/controllers/modals/palletContent.js',
'app/js/controllers/pallet.js',
'app/js/services/printDocument.js'
]
});
}]
}
})
This is my printDocument.js where I pasted the code from the example (and modified it to get it to work):
'use strict';
function appController($scope) {
var self = this;
self.fullScreenApi;
self.downloadFull = downloadFull;
this.downloadFull = function() {
if (self.fullScreenApi) self.fullScreenApi.downloadFull();
}
return downloadFull;
}
angular
.module('TepaPrime')
.service('printDocument', appController);
Then I inject it in my view's controller by doing this:
function Pallet($rootScope, $scope, $state, $timeout, $uibModal, $http, $filter, crud, sessionService, printDocument) {
...
}
The problem is it doesn't work and it crashes the whole page and throws this error:
Error: [$injector:unpr] http://errors.angularjs.org/1.5.0/$injector/unpr?p0=copeProvider%20%3C-%20%24scope%20%3C-%20printDocument
I'd really appretiate some help, as I've been stuck with this for a long time now and don't seem able to get closer to a solution.
After a quite long struggle, I was able to fix it by changing the html from
<button class="btn btn-info" ng-if="appCtrl.isFullOpen" ng-click="appCtrl.downloadFull()">
<i class="material-icons">Descargar tabla</i>
</button>
To:
<button class="btn btn-info" ng-if="appCtrl.isFullOpen" ng-click="appCtrl.fullScreenApi.downloadFull()">
<i class="material-icons">Descargar tabla</i>
</button>
The problem is that the downloadFull() function was inside fullscreenApi.
For some reason my controller doesn't seem to be registered and I'm honestly not sure why...
I've been following along an AngularJS and Django development course on PluralSight. The only difference between the instructor's stack and mine is that I'm using Angular 1.6.4 and he is using 1.5.0. I've previously hit some errors (like routing syntax), but it's overall been fine.
EDIT:
I should mention that I'm simply following the instructor's instructions and writing the same code as him.
Right now, however, I'm simply stuck. I've got this routing in scrumboard.config.js:
(function () {
"use strict";
angular.module('scrumboard.demo', ["ngRoute"])
.config(["$routeProvider", config])
.run(["$http", run]);
function config($routeProvider) {
$routeProvider
.when('/', {
templateUrl: "/static/html/scrumboard.html",
controller: "ScrumboardController",
})
.when('/login', {
templateUrl: "/static/html/login.html",
controller: "LoginController",
})
.otherwise('/');
}
function run($http) {
$http.defaults.xsrfHeaderName = 'X-CSRFToken';
$http.defaults.xsrfCookieName = 'csrftoken';
}
})();
And this controller for login.html:
(function() {
"use strict";
angular.module("scrumboard.demo", [])
.controller("LoginController",
["$scope", "$http", "$location", LoginController]);
function LoginController($scope, $http, $location) {
$scope.login = function () {
$http.post('/auth_api/login/', $scope.user)
.then(function (response){
$location.url("/");
},
function(error) {
//failure
$scope.login_error = "Invalid username or password";
});
};
};
})();
When navigating to localhost:8000/#!/login I can see my form:
<form ng-submit="login()">
<div style="...">{{ login_error }}</div>
<div>
<label>Username</label>
<input type="text" ng-model="user.username"/>
</div>
<div>
<label>Password</label>
<input type="password" ng-model="user.password"/>
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
But for some strange reason my console keeps telling me that my LoginController isn't registered.
Could anyone please help me in the right direction?
Sorry if I'm missing any sort of files, but I'm very new to Angular, so I don't really know what to add.
If you need any additional information, please tell me!
remove [] from your controller's defination for login.html.
angular.module("scrumboard.demo")
.controller("LoginController",
["$scope", "$http", "$location", LoginController]);
You are declaring the module scrumboard.demo twice.
Remove the [] in
angular.module("scrumboard.demo")
.controller("LoginController",
["$scope", "$http", "$location", LoginController]);
Without the second argument of angular.module() it is a getter, otherwise it is a setter
In the entry point html, the script tag for file scrumboard.config.js should precede the file controller file. Also as #charlietfl said declaring twice should be removed.
Like this,
<script src="your_path/scrumboard.config.js"></script>
<script src="your_path/scrumboard.controller.js"></script>
Hope this would rectify the problem.
I'm working with a Play framwork project using angular-seed project as a basis. It creates an array of controllers and passes them into the angularjs instance I guess, somewhat different to other tutorials I've seen. When I try to link a div to the controller the controller function isn't found:
angular.js:13920 Error: [ng:areq] Argument 'menuCtrl' is not a function, got undefined
Here's how I link in the controller:
<div id="wrapper" class="row row-offcanvas row-offcanvas-left" ng-controller="menuCtrl" uib-collapse="showMenu" horizontal>
<div id="sidebar-wrapper" class="col-xs-6 col-sm-3 sidebar-offcanvas" ng-show="menuOpen" role="navigation">
<ul class="nav nav-pills nav-stacked">
<li>view1</li>
<li>view2</li>
</ul>
</div>
<div id="page-content-wrapper" class="col-xs-12 col-sm-9">
<div ng-view></div>
<div>Angular seed app: v<span app-version></span></div>
</div>
</div>
Here's the main.js:
/*global require, requirejs */
'use strict';
requirejs.config({
paths: {
'angular': ['../lib/angularjs/angular'],
'angular-route': ['../lib/angularjs/angular-route'],
'ui-bootstrap':['../lib/angular-ui-bootstrap/ui-bootstrap']
},
shim: {
'angular': {
exports : 'angular'
},
'angular-route': {
deps: ['angular'],
exports : 'angular'
},
'ui-bootstrap': {
deps: ['angular'],
exports: 'ui-bootstrap'
}
}
});
require(['angular', './controllers', './directives', './filters', './services', 'angular-route', "ui-bootstrap"],
function(angular, controllers) {
// Declare app level module which depends on filters, and services
angular.module('eprogram2', ['eprogram2.filters', 'eprogram2.services', 'eprogram2.directives', 'ngRoute']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {templateUrl: 'partials/partial1.html', controller: controllers.MyCtrl1});
$routeProvider.when('/view2', {templateUrl: 'partials/partial2.html', controller: controllers.MyCtrl2});
$routeProvider.otherwise({redirectTo: '/view1'});
}]);
angular.module('eprogram2', ['ui.bootstrap']);
angular.bootstrap(document, ['eprogram2']);
});
and the controller.js:
'use strict';
define(function() {
/* Controllers */
var controllers = {};
controllers.MyCtrl1 = function() {}
controllers.MyCtrl1.$inject = [];
controllers.MyCtrl2 = function() {}
controllers.MyCtrl2.$inject = [];
controllers.menuCtrl = function($scope, $window) {
$scope.menuOpen = false;
console.log("MenuCtrl");
// Detect if mobile portrait screen size
$scope.is_mobile = ($window.innerWidth <= 480);
if ($scope.isMobile) {
$scope.menuOpen = false;
console.log("mobile detected - close menu")
} else {
$scope.menuOpen = true;
console.log("not mobile - open menu")
}
}
controllers.menuCtrl.$inject = ['$scope', '$window'];
return controllers;
});
I've tried using the template project's controllers and mine but no go. The routing instructions find their controllers no problem in main.js, but the controllers don't seem to be exposed to the HTML page. I've tried:
eprogram2.controllers.menuCtrl
controllers.menuCtrl
eprogram2.menuCtrl
formats as well, but all return the same not a function, got undefined message. Any suggestions about what my boneheaded mistake is?
You have 2 declarations for module('eprogram2') .
You can only declare a module once.
Remove:
angular.module('eprogram2', ['ui.bootstrap']);
and add 'ui.bootstrap' dependency to the initial declaration.
On a side note it looks like the seed you are using is fairly old. I would suggest following John Papa's style guide and the rule of 1 and have one component per file. You will appreciate it in the long run.
The idea of grouping controllers into controller modules and directives into directive modules has long been superseded with grouping features into modules. They become a lot more portable that way
I am getting an unknown provider error. My structure is set up with two different files, a controller file and a service file. For some reason the angular app cannot find the service? If I put the service within the same file it works fine?
controller file:
(function() {
'use strict'
angular
.module('poke', ['ngResource'])
.controller("appController", appController)
appController.$inject = ['$scope', 'user']
function appController($scope, user){
$scope.saveUser = saveUser;
// getProducts();
//
function saveUser(user_email) {
return user.save({user_email}, function(data) {
$scope.email = []
});
}
}
})()
service file
(function() {
angular
.module('poke')
.factory("user", user)
user.$inject = ['$resource']
function user($resource) {
return $resource("/users",{}, {})
}
})();
html
<body ng-app="poke" ng-controller="appController" ng-cloak>
<div class="page-header">
<h1>Pokemon Go!</h1>
</div>
<form ng-submit="saveUser(email)" style="margin-top:30px;">
<h3>Please enter your email address to receive news about Pokemon Go in your city!</h3>
<input type="text" class="form-control" placeholder="example#email.com" ng-model="email"></input>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</body>
Keep your main Module independently by injecting the global Dependencies. So you no need to refer this dependency in all files.
angular.module('myModule', ['ngResource']);
angular
.module('poke')
.controller("appController", appController)
then you can use $resource dependency across your angular components
Hope this helps
I'm trying to setup a simple angularjs app using ui.router, ocLazyLoad, Foundation and angular-foundation.
The app is a multi-view app with it's components lazy loaded using ocLazyLoad. I have no problem setting up the views and associated controllers. However, I am having an issue when trying to display a Foundation alert. When I try to view my alerts (route1), I get empty alerts. And the stack trace below.
Why is angular applying the alert directive twice? A plunker is available here: http://goo.gl/lhtD0c
Error: [$compile:multidir] Multiple directives [alert, alert] asking for transclusion on:
<div class="alert-box" ng-class="(type || "")" ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">
http://errors.angularjs.org/1.2.22/$compile/multidir?p0=alert&p1=alert&p2=t…lerts%22%20type%3D%22alert.type%22%20close%3D%22closeAlert(%24index)%22%3E
at https://code.angularjs.org/1.2.22/angular.js:78:12
at assertNoDuplicate (https://code.angularjs.org/1.2.22/angular.js:6933:15)
at applyDirectivesToNode (https://code.angularjs.org/1.2.22/angular.js:6353:13)
at https://code.angularjs.org/1.2.22/angular.js:6858:37
at https://code.angularjs.org/1.2.22/angular.js:8091:11
at wrappedCallback (https://code.angularjs.org/1.2.22/angular.js:11546:81)
at wrappedCallback (https://code.angularjs.org/1.2.22/angular.js:11546:81)
at https://code.angularjs.org/1.2.22/angular.js:11632:26
at Scope.$eval (https://code.angularjs.org/1.2.22/angular.js:12658:28)
at Scope.$digest (https://code.angularjs.org/1.2.22/angular.js:12470:31)
The body of my index is below:
<body>
<div>
<a class="button" ui-sref="route1">Route 1</a>
<a class="button" ui-sref="route2">Route 2</a>
</div>
<div ui-view></div>
</body>
The javascript associated with this page is:
var myapp = angular.module('myapp', ['ui.router', 'oc.lazyLoad', 'mm.foundation'])
myapp.config(function($stateProvider, $urlRouterProvider){
// For any unmatched url, send to /route2
$urlRouterProvider.otherwise('/route2')
$stateProvider
.state('route1', {
url: "/route1",
controller: 'Route1',
templateUrl: "route1.html",
resolve: {
loadCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
return $ocLazyLoad.load({
name: 'myapp',
files: ['route1.js']
})
}]
}
})
.state('route2', {
url: "/route2",
templateUrl: "route2.html"
})
});
$(function() {
Foundation.global.namespace = '';
$(document).foundation();
})
The problems are associated with route1. Here is the route1 template.
<div ng-controller="Route1">
Route 1 - {{ message }}
<br/>
<alert ng-repeat="alert in alerts"
type="alert.type"
close="closeAlert($index)">{{alert.msg}}</alert>
</div>
and finally the route1.js -
angular.module('myapp').controller('Route1', ['$scope', function($scope) {
$scope.message = 'Hello, world!'
$scope.alerts = [
{ type: 'danger', msg: 'Oh snap! Change a few things up and try submitting again.' },
{ type: 'success round', msg: 'Well done! You successfully read this important alert message.' }
];
}]);
The problem is that it's reloading your "myapp" module dependencies.
Just config ocLazyLoad not to reload foundation like this:
$ocLazyLoadProvider.config({
loadedModules: ['mm.foundation']
});
It will be something like that:
var myapp = angular.module('myapp', ['ui.router', 'oc.lazyLoad', 'mm.foundation'])
myapp.config(function($stateProvider, $urlRouterProvider, $ocLazyLoadProvider){
// For any unmatched url, send to /route2
$urlRouterProvider.otherwise('/route2')
$ocLazyLoadProvider.config({
loadedModules: ['mm.foundation']
});
$stateProvider
.state('route1', {
url: "/route1",
controller: 'Route1',
templateUrl: "route1.html",
resolve: {
loadCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
return $ocLazyLoad.load({
name: 'myapp',
files: ['route1.js']
})
}]
}
})
.state('route2', {
url: "/route2",
templateUrl: "route2.html"
})
});
$(function() {
Foundation.global.namespace = '';
$(document).foundation();
})
Replace this code
<alert ng-repeat="alert in alerts"
type="alert.type"
close="closeAlert($index)">{{alert.msg}}</alert>
by
<div ng-repeat="alert in alerts">
<alert type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert>
</div>
I finally managed to make this work. The problem was that ocLazyLoad was reloading the 'myapp' module. This caused the dependencies to reload. One of the dependencies was mm.foundation which reprocessed all the directives creating a clone of each pair.
To prevent this,I did not tie the second controller to myapp. Instead I created a new app 'route1app'. You can see the updated plunker here: http://goo.gl/lhtD0c