Ionic/Angularjs change controller to a global Variable - javascript

Here is my controller:
(function () {
var app= angular.module('app');
app.controller('recommendedJobsCtrl', ['$scope', function(dataShare,$q,$scope, $ionicSideMenuDelegate,$window,$http,$timeout) {
// passes contents to jobDetails to be rendered and displayed
window.post = function($event, res){
console.log(angular.element($event.target).parent());
dataShare.sendData(res)
}
/**
* handles pagination
*loads first 3 pages
**/
var i=1;
window.result=[];
window.noMoreItemsAvailable=false;
window.loadMore = function()
{
console.log('here')
if(i<4)
{
$http.get( "http://test.website.com/api/search/"+i).success(function(response)
{
i++;
$scope.result=$scope.result.push(response);
console.log(response);
$timeout(function ()
{
$scope.result = response
});
$scope.$broadcast('scroll.infiniteScrollComplete');
});
}else
{
$scope.noMoreItemsAvailable=true;
}
}
]);
}());
I read that my controller was under 'user strict' so it can't access the variables or functions. So I placed the word 'window' to make it global. But now it doesn't access the function because the console won't print. How do I fix this?

Dependency Injection is incorrect:
app.controller('recommendedJobsCtrl', [
'dataShare',
'$q',
'$scope',
'$ionicSideMenuDelegate',
'$window',
'$http',
'$timeout',
function(
dataShare,
$q,
$scope,
$ionicSideMenuDelegate,
$window,
$http,
$timeout) {
// Your code ...
}]);
Your code should be specific to the controller. You should create function and variables either on $scope as in $scope.<functionName> = function() {} and $scope.noMoreItemsAvailable or private to the controller as in function <functionName>() {} or var noMoreItemsAvailable.
In case intention behind using window object is to use same code across controllers, you may put this code in a factory.

Related

How to pass value between controller and config in angularjs

I am trying to pass variable to angular js config,
This is my js app:
var app = angular.module('myApp', ['ngMaterial', 'sasrio.angular-material-sidenav', 'ui.router']);
app.controller('baseController', function ($scope, $mdDialog, $mdMedia, $http, $rootScope, $timeout, $mdToast, $mdSidenav, ssSideNav) {
$scope.menu = ssSideNav;
$scope.getRequirment = function () {
$http.get("site/requirment",
{params: {dir: $scope.currentPath}})
.then(function (response) {
return response.data;
});
};
$scope.getRequirment();
});
app.config(['$mdThemingProvider', '$locationProvider', 'ssSideNavSectionsProvider', '$stateProvider',
function ($mdThemingProvider, $locationProvider, ssSideNavSectionsProvider, $stateProvider) {
$mdThemingProvider.theme('default')
.primaryPalette('deep-orange')
.accentPalette('deep-orange');
ssSideNavSectionsProvider.initWithTheme($mdThemingProvider);
ssSideNavSectionsProvider.initWithSections("Get getRequirment function in controller");
}]);
How can I call a function in the controller from config?
I mean this line:
ssSideNavSectionsProvider.initWithSections("Get getRequirment function in controller");
There is a durty way to do this:
you can put this in your config
$rootScope.$watch("variable", function(n, o) {
// assign n value
})
and in your controller just set the
$rootScope.variable
It's impossible, controller executes in run phase, config in config phase.
I investigate source code a little, sections available as a service variable, you could try to add them from controller:
ssSideNavSections.sections.push(yourSection);
You can set constant in configuration block and then access that constant via injecting it into controller.
Source: https://www.agiliq.com/blog/2017/04/what-when-and-how-angularjs-configuration-blocks/

Undefined variable passing data using service

I have declared my app and have one controller (for demonstration purposes):
var module = angular.module("app", [])
module.controller("modalCtrl", ["$scope", function ($scope, dataService) {
$scope.printEntity = function () {
console.log(dataService.getEntityArray());
}
}]);
And a service:
module.factory("dataService", function () {
var entityArrayService = [1,2];
return {
getEntityArray: function () {
return entityArrayService;
}
};
});
When I call $scope.printEntity from my view, I'm always told dataService.getEntityArray() is undefined.
I've loaded the service as a dependency and declared my entityArrayService array outside of my return statement. I've looked high and low for an answer but to no avail. My goal is to share a piece of data between two controllers, but at the minute I can't even use one controller to retrieve data.
The service isn't loaded as a dependency. Change this line:
module.controller("modalCtrl", ["$scope", function ($scope, dataService) {
to this:
module.controller("modalCtrl", ["$scope", "dataService", function ($scope, dataService) {
You are using strict syntax for dependencies declaration. So if you add a parameter to your controller, you must add its declaration too.
module.controller("modalCtrl", ["$scope", "dataService", function ($scope, dataService) {
...
}
You didn't inject dataService in your controller. Try with:
module.controller("modalCtrl", ["$scope", "dataService", function ($scope, dataService) {
// ...
});
The injection of the service in the controller is missing:
please correct to:
...
module.controller("modalCtrl", ["$scope", "dataService", function ($scope, dataService) {
...
The other code is correct.

Angular watch factory value

Say i have the following factory:
app.factory("categoryFactory", function (api, $http, $q) {
var selected = null;
var categoryList = [];
return {
getList: function () {
var d = $q.defer();
if(categoryList.length <= 0){
$http.get(api.getUrl('categoryStructure', null))
.success(function (response) {
categoryList = response;
d.resolve(categoryList);
});
}
else
{
d.resolve(categoryList)
}
return d.promise;
},
setSelected: function (category) {
selected = category;
},
getSelected: function () {
return selected;
}
}
});
now i have two controllers using this factory at the same time. Because of this both controllers has to be notified when updated for this i attempted the following:
app.controller('DashboardController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api','categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, categoryFactory) {
$scope.selectedCategory = categoryFactory.getSelected();
}]);
While my other controller looks like this:
app.controller('NavController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'FileUploader', 'categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, FileUploader, categoryFactory) {
$scope.categories = [];
categoryFactory.getList().then(function (response) {
$scope.categories = response;
});
$scope.selectCategory = function (category) {
categoryFactory.setSelected(category);
}
}]);
how ever when the NavController changed the value it was not changed in the DashboardController
My question is how can i either watch or in another way get notified when the value changes?
You can use an observer pattern, like so:
app.factory("categoryFactory", function (api, $http, $q) {
// the list of callbacks to call when something changes
var observerCallbacks = [];
// ...
function notifyObservers() {
angular.forEach(observerCallbacks, function(callback) {
callback();
});
}
return {
setSelected: function (category) {
selected = category;
// notify the observers after you change the value
notifyObservers();
},
registerObserver: function(callback) {
observerCallbacks.push(callback);
}
}
});
And then in your controllers:
app.controller('NavController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'FileUploader', 'categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, FileUploader, categoryFactory) {
// ...
// init
(function() {
categoryFactory.registerObserver(function() {
categoryFactory.getList().then(function (response) {
$scope.categories = response;
});
});
})();
}]);
This way, any time setSelected is called, it calls each callback that you've registered in observerCallbacks. You can register these from any controller since factories are singletons and they will always be in the know.
Edit: just want to add that I may have put the notifyObservers() call in the wrong area (currently in setSelected) and that I may be putting the wrong update call in the controller (currently getList) but the architecture remains the same. In the registerObserver, put whatever you want to do when the values are updated and wherever you make changes that you want observers to know about call notifyObservers()
You could follow dot rule here so that prototypal inheritance will get followed.
Basically you need to have one object inside your service that will have selected variable, And will get rid of getSelected method.
Factory
app.factory("categoryFactory", function(api, $http, $q) {
var categoryFactory = {};
categoryFactory.getList = function() {
var d = $q.defer();
if (categoryList.length <= 0) {
$http.get(api.getUrl('categoryStructure', null))
.success(function(response) {
categoryList = response;
d.resolve(categoryList);
});
} else {
d.resolve(categoryList)
}
return d.promise;
}
categoryFactory.setSelected = function(category) {
categoryFactory.data.selected = category;
}
categoryFactory.data = {
selected: null
}
return categoryFactory;
});
Controller
app.controller('DashboardController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'categoryFactory',
function($http, $scope, $sessionStorage, $log, Session, api, categoryFactory) {
//this will provide you binding without watcher
$scope.selection = categoryFactory.data;
}
]);
And then use {{selection.selected}} on html part will update a value when changes will occur in selection.

AngularJS: '$scope is not defined'

I keep getting '$scope is not defined' console errors for this controller code in AngularJS:
angular.module('articles').controller('ArticlesController', ['$scope', '$routeParams', '$location', 'Authentication', 'Articles',
function($scope, $routeParams, $location, Authentication, Articles){
$scope.authentication = Authentication;
}
]);
$scope.create = function() { // THROWS ERROR ON THIS INSTANCE OF $SCOPE
var article = new Articles({
title: this.title,
content: this.content
});
article.$save(function(response) {
$location.path('articles/' + response._id);
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
Where in my AngularJS MVC files should I be looking at to find problems with the $scope not being defined properly?
For others who land here from Google, you'll get this error if you forget the quotes around $scope when you're annotating the function for minification.
Error
app.controller('myCtrl', [$scope, function($scope) {
...
}]);
Happy Angular
app.controller('myCtrl', ['$scope', function($scope) {
...
}]);
Place that code inside controller:-
angular.module('articles').controller('ArticlesController', ['$scope', '$routeParams', '$location', 'Authentication', 'Articles',
function($scope, $routeParams, $location, Authentication, Articles){
$scope.authentication = Authentication;
$scope.create = function() { // THROWS ERROR ON THIS INSTANCE OF $SCOPE
var article = new Articles({
title: this.title,
content: this.content
});
article.$save(function(response) {
$location.path('articles/' + response._id);
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
}
]);
Just put you $scope.create function inside your controller. Not outside !
$scope is only defined in controllers, each controller have its own. So write $scope outside your controller can't work.
Check scope variable declared after controller defined.
Eg:
var app = angular.module('myApp','');
app.controller('customersCtrl', function($scope, $http) {
//define scope variable here.
});
Check defined range of controller in view page.
Eg:
<div ng-controller="mycontroller">
//scope variable used inside these blocks
<div>

How to inject service from external file using AngularJS and RequireJS?

I'm injecting controller from external file and I want to do the same thing for the service from external file. It should be registered in factory statement.
Injecting of the controller working
controllers
'use strict';
define(['angular', 'services'], function (angular) {
return angular.module('vcApp.controllers', ['vcApp.services'])
.controller('AuthCtrl', ['$scope', '$injector','AuthService', function($scope, $injector, AuthService) {
require(['auth/authCtrl'], function(authCtrl) {
$injector.invoke(authCtrl, this, {'$scope': $scope, 'AuthService':AuthService});
});
}]);
});
authCtrl
define([], function() {
return ['$scope', '$routeParams', '$location', '$http', 'AuthService', function($scope, $routeParams, $location, $http, authService) {
$scope.signIn = function() {
...
}
$scope.$apply();
}];
});
And now I want to inject service
services
'use strict';
define(['angular'], function (angular) {
angular.module('vcApp.services', [])
.factory('AuthService', ['$http', '$injector', function($http, $injector) {
require(['auth/authService'], function(authService) {
$injector.invoke(authService, this, {'$http': $http});
});
}]);
});
authService
define([], function() {
return ['$http', function ($http) {
return {
login: login
};
function login(username, password) {
var request = $http(...);
return(request);
}
}]
});
When authController calls authService.login(...), it throws error Error: [$injector:undef] Provider 'AuthService' must return a value from $get factory method..
This code was inspired by angular-requirejs-seed project.
As it says, Angular's factory() is expected to return the service object. You may have luck with something like:
define(['angular'], function (angular) {
angular.module('vcApp.services', [])
.factory('AuthService', ['$http', '$injector', function($http, $injector) {
var stub = {};
require(['auth/authService'], function(authService) {
angular.extend(stub, $injector.invoke(authService, this, {'$http': $http}));
});
return stub;
}]);
});
Here you define a stub for the service and extend it, when the service is actually lazy-loaded.
(By the way I think the last 2 arguments of $injector.invoke() are redundant in this case.)
If you want another idea about mixing RequireJS and Angular, that plays well with lazy loading and the r.js optimizer, you may take a look at angular-require-lazy.

Categories