How to avoid code duplication when using controllers with similar methods? - angularjs

Say I have following controllers:
controller("MyCtrl1", ["$scope", "$sce", "myService", "$location",
function ($scope, $sce, myService, $location) {
$scope.Resources = window.MyGlobalResorcesObject;
$scope.trustedHtml = function (input) {
return $sce.trustAsHtml(input);
};
$scope.startProcessing = function () {
$scope.processingRequest = true;
};
$scope.endProcessing = function () {
$scope.processingRequest = false;
$scope.$apply();
};
//some MyCtrl1-specific code goes here
}]).
controller("MyCtrl2", ["$scope", "$sce", "myService", "$location",
function ($scope, $sce, myService, $location) {
$scope.Resources = window.MyGlobalResorcesObject;
$scope.trustedHtml = function (input) {
return $sce.trustAsHtml(input);
};
$scope.startProcessing = function () {
$scope.processingRequest = true;
};
$scope.endProcessing = function () {
$scope.processingRequest = false;
$scope.$apply();
};
//some MyCtrl2-specific code goes here
}]);
You see, code is duplicated.I want to reuse common code.
What is the common practice to achieve this?

Use a common service:
module.factory('processing', function($sce) {
function initialize($scope) {
$scope.Resources = window.MyGlobalResorcesObject;
$scope.trustedHtml = function(input) {
return $sce.trustAsHtml(input);
};
$scope.startProcessing = function() {
$scope.processingRequest = true;
};
$scope.endProcessing = function () {
$scope.processingRequest = false;
$scope.$apply();
};
}
return {
initialize: initialize;
}
});
And then in your controllers:
controller("MyCtrl1", function($scope, processing) {
processing.initialize($scope);
}

Related

Angularjs watch ng-model change in different controllers

i try to share data between two different controllers using a service and watch changes but i don't find how to do this. Here is my code
month-select.component.js:
'use strict'
angular
.module('myApp.monthSelect')
.component('myApp.monthSelect', {
templateUrl: 'monthSelect/month-select.template.html',
controller: 'MonthSelectCtrl',
css: 'monthSelect/month-select.style.css'
})
.controller('MonthSelectCtrl', ['$scope', 'selectedMonthSvc', function ($scope, selectedMonthSvc) {
selectedMonthSvc.setDate($scope.dt)
}])
weeks-list.component.js:
'use strict'
angular
.module('myApp.weeksList')
.component('myApp.weeksList', {
templateUrl: 'weeksList/weeks-list.template.html',
controller: 'WeeksListCtrl',
css: 'weeksList/weeks-list.style.css'
})
.controller('WeeksListCtrl', ['$scope', 'selectedMonthSvc', function ($scope, selectedMonthSvc) {
$scope.getDate = selectedMonthSvc.getDate
}])
get-select-month.service.js
angular.module('myApp.svc', [])
.factory('selectedMonthSvc', function () {
var self = this
var date = ''
self.setDate = function (value) {
return date = value
}
self.getDate = function () {
return date
}
return self
})
It works at init i get the date in my WeeksList controllers, but if i change the date in my MonthSelectCtrl, the value don't update in WeekList.
I'm trying to watch it with $watch but it don't work and have no idea where it goes wrong.
Thank you very much for your help.
1st off change factory to service:
.service('selectedMonthSvc', function () {/**/}
Further
You can write watcher to listen on changes.
So instead:
$scope.getDate = selectedMonthSvc.getDate
try:
$scope.getDate = selectedMonthSvc.getDate;
$scope.$watch('getDate', function() {
// here you get new value
});
This is simple demo that demonstrates your case
When second controller updates date, 1st controller listens and reflects on changes:
angular.module('myApp', [])
.controller('Ctrl1', function ($scope, App) {
$scope.status = App.getDate();
$scope.$watch(function(){
return App.getDate();
}, function() {
$scope.status = App.getDate();
});
})
.controller('Ctrl2', function ($scope, App) {
$scope.status = App.getDate();
$scope.$watch('status', function() {
App.setDate($scope.status);
});
})
.service('App', function () {
this.data = {};
this.data.date = 'someDate';
var self = this;
var date = ''
self.setDate = function (value) {
this.data.date = value
}
self.getDate = function () {
return this.data.date;
}
});
Try this:
// selectedMonthSvc service:
angular.module('myApp.svc', [])
.factory('selectedMonthSvc', function () {
var date = '';
var self = this
self.setDate = setDate;
self.getDate = getDate;
return self;
function setDate(value) {
date = value;
}
function getDate() {
return date;
}
})
// WeeksListCtrl controller
.controller('WeeksListCtrl', ['$scope', 'selectedMonthSvc', function ($scope, selectedMonthSvc) {
$scope.getDate = getDate;
function getDate() {
return selectedMonthSvc.getDate();
}
}])
var app = angular.module('app', []);
app.controller('firstController', ['$scope','selectedMonthSvc', function($scope, selectedMonthSvc) {
$scope.date = new Date();
$scope.changeDate = function() {
selectedMonthSvc.setDate(new Date())
}
}]);
app.controller('secondController', ['$scope','selectedMonthSvc', function($scope, selectedMonthSvc) {
$scope.date = '';
$scope.selectedMonthSvc = selectedMonthSvc;
$scope.$watch(function() {
return $scope.selectedMonthSvc.getDate();
}, function(newVal) {
$scope.date = newVal;
}, true);
}]);
app.factory('selectedMonthSvc', [function() {
var date = '';
return {
getDate: function () {
return date;
},
setDate: function(d) {
date = d;
}
}
}])
Here is the working plunker https://plnkr.co/edit/w3Y1AyhcGhGCzon8xAsV?p=preview

how to call the application titles and other static messages from a service?

here is the code i have tried so far
angular.module('app')
.factory('PostMeetUpService', function () {
var myMtpData = {title: "Post MeetUp",error: "*Required"};
return {
getMyMtpData: function () {
return myMtpData;
}
}
});
and in Controller as follows:
$scope.Mtp_Data = PostMeetUpService.getMyMtpData();
{{Mtp_Data.title}} is the expression am using in HTML ,
but unable to display the data . i have also injected the service in the function .
var serviceModule = angular.module('abc');
serviceModule.factory('PostMeetUpService', function () {
var myMtpData = {title: "Post MeetUp",error: "*Required"};
return {
getMyMtpData: function () {
return myMtpData;
}
}
});
var controllerModule = angular.module('xyz', ['abc']);
controllerModule.controller('postCtrl', post);
post.$inject = ['$scope', '$state', 'PostMeetUpService', '$stateParams', 'Event', 'Terminal', 'PostService', 'Auth', 'Profession', 'growl', '$ionicPopup', '$filter', '$ionicModal'];
function post($scope, $state, PostMeetUpService, $stateParams, Event, Terminal, PostService, Auth, Profession, growl, $ionicPopup, $filter, $ionicModal) {
var dateType = '';
var timeType = '';
$scope.Mtp_Data = PostMeetUpService.getMyMtpData();
}
Try this
Modify the factory as:
.factory('PostMeetUpService', function () {
var PostMeetUpServiceFactory = {};
var _myMtpData = {title: "Post MeetUp",error: "*Required"};
var _getMyMtpData = function() {
return _myMtpData;
}
PostMeetUpServiceFactory.getMyMtpData = _getMyMtpData ;
return PostMeetUpServiceFactory;
});
Then in controller:
.controller('myController', ['$scope', 'PostMeetUpService', function($scope, PostMeetUpService) {
$scope.Mtp_Data = PostMeetUpService.getMyMtpData();
}]);

Angular service which is a require js module, is not getting the injected dependencies

I have a module 'global.services' in which I registered a service "Restservices"
(function(define, angular) {
"use strict";
define(["global/services/restServices"],
function(RestServices) {
var moduleName = "global.services";
angular.module(moduleName, [])
.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('http://localhost:8888/src/app/data/');
RestangularProvider.setRequestSuffix('.json');
})
.factory('RestServices', RestServices);
return moduleName;
});
}(define, angular));
and my "RestService" is also a module
(function(define, angular) {
"use strict";
define(function() {
var restService = function($rootScope, Restangular) {
// body...
return {
getData: function(arg) {
// body...
$rootScope.$broadcast('gettingData');
return Restangular.oneUrl('listPanel');
}
}
};
return restService;
});
}(define, angular));
In the above service both $rootScope and Restangular are undefined.
Please tell me how to inject dependencies in this respect.
I found the reason of $rootScope and Restangular being undefined.
Factory registration is perfect but when I am trying to use it in a different module's controller I am injecting "global/services/restServices" instead of "global/services/services" which is the actual services module.
Previous code:
(function(define, angular) {
define(['global/services/restServices'], function(RestServices) {
var HeaderController = function($scope, $rootScope, $translate, $location, $document, RestServices) {
var user_modules = window.SESSION.getModules(),
modules = [];
angular.forEach(user_modules, function(moduleName) {
modules.push(window.CONFIG.MODULES[moduleName]);
});
RestServices.getData('webAppsData.json').get().then(function(d) {
if (d) {
if (d.response) {
$scope.webApps = d.response;
} else {
$scope.webApps = [];
}
} else {
$scope.webApps = [];
}
});
$scope.title = "Tumbler";
$scope.modules = modules;
};
return ["$scope", "$rootScope", "$translate", "$location", "$document", "RestServices", HeaderController];
})
}(define, angular));
Present code(working):
(function(define, angular) {
define(['global/services/services'], function() {
var HeaderController = function($scope, $rootScope, $translate, $location, $document, RestServices) {
var user_modules = window.SESSION.getModules(),
modules = [];
angular.forEach(user_modules, function(moduleName) {
modules.push(window.CONFIG.MODULES[moduleName]);
});
RestServices.getData('webAppsData.json').get().then(function(d) {
if (d) {
if (d.response) {
$scope.webApps = d.response;
} else {
$scope.webApps = [];
}
} else {
$scope.webApps = [];
}
});
$scope.title = "Tumbler";
$scope.modules = modules;
};
return ["$scope", "$rootScope", "$translate", "$location", "$document", "RestServices", HeaderController];
})
}(define, angular));
So, just inject the module and use its services.

AngularJS (Restangular CRUD , Simplify / DRY Controllers?)

Below a small example of what I want to simplify. I have the same structure set up for a few other models, and was wondering if I could prevent typing out the same functionality but with just different messages/model.
Is it possible to reuse a controller & pass parameters? (In this case, the name of the model + the messages that need to be shown...). Ideally, I just want the basic CRUD controller to be reused, but allow custom methods, just in case.
angular.module('employees.controllers', ["templates.app", "ui.bootstrap"])
.controller("EmployeeListController", ["$scope", "$modal", "Restangular", function ($scope, $modal, Restangular) {
var Employee = Restangular.all("employees");
Employee.getList().then(function (employees) {
$scope.employees = employees;
})
$scope.createEmployee = function () {
$modal.open({
templateUrl: 'employees/partials/employees.manage.modal.tpl.html',
controller: 'EmployeeCreateController'
}).result.then(function (employee) {
Employee.post(employee).then(function (newEmployee) {
$scope.messageService.addMessage("success", "Employee was successfully created!");
$scope.employees.push(newEmployee);
});
});
};
$scope.deleteEmployee = function (employee) {
employee.remove().then(function () {
$scope.messageService.addMessage("success", "Employee was successfully deleted!");
$scope.employees = _.without($scope.employees, employee);
});
};
$scope.editEmployee = function (originalEmployee) {
$modal.open({
templateUrl: 'employees/partials/employees.manage.modal.tpl.html',
controller: 'EmployeeUpdateController',
resolve: {
employee: function () {
return Restangular.copy(originalEmployee);
}
}
}).result.then(function (employee) {
employee.put().then(function (updated_employee) {
$scope.messageService.addMessage("success", "Employee was successfully updated!");
var originalIndex = _.indexOf($scope.employees, originalEmployee);
$scope.employees[originalIndex] = updated_employee;
});
});
};
}]).controller("EmployeeCreateController", ["$scope", "$modalInstance", "$timeout", function ($scope, $modalInstance, $timeout) {
$scope.createMode = true;
$scope.form = {};
$scope.employee = {};
$scope.datepicker = {};
$scope.ok = function () {
if ($scope.form.createResource.$valid) {
$modalInstance.close($scope.employee);
}
};
$scope.open = function () {
$timeout(function () {
$scope.datepicker.opened = true;
});
};
$scope.cancel = function () {
$modalInstance.dismiss("cancel");
};
}]).controller("EmployeeUpdateController", ["$scope", "$modalInstance", "employee", function ($scope, $modalInstance, employee) {
$scope.createMode = false;
$scope.form = {};
$scope.employee = employee;
$scope.ok = function () {
if ($scope.form.createResource.$valid) {
$modalInstance.close($scope.employee);
}
};
$scope.cancel = function () {
$modalInstance.dismiss("cancel");
};
}]);

AngularJS: How to access child scope object from parent scope?

function ParentCtrl($scope) {
//some function check whether data object in child scope is still null
}
function ChildCtrl($scope) {
$scope.data={};
$scope.func = function(){
$scope.data.x = 1;
};
};
jsFiddle: http://jsfiddle.net/JHwxP/74/
You can use a system of events like you can see here : http://jsfiddle.net/patxy/RAVFM/
If you have 2 controllers with a shared service, you can do it that way :
var myModule = angular.module('myModule', []);
myModule.factory('mySharedService', function($rootScope) {
var sharedService = {};
sharedService.message = '';
sharedService.prepForBroadcast = function(msg) {
this.message = msg;
this.broadcastItem();
};
sharedService.broadcastItem = function() {
$rootScope.$broadcast('handleBroadcast');
};
return sharedService;
});
function ControllerZero($scope, sharedService) {
$scope.handleClick = function(msg) {
sharedService.prepForBroadcast(msg);
};
$scope.$on('handleBroadcast', function() {
$scope.message = sharedService.message;
});
}
function ControllerOne($scope, sharedService) {
$scope.$on('handleBroadcast', function() {
$scope.message = 'ONE: ' + sharedService.message;
});
}
function ControllerTwo($scope, sharedService) {
$scope.$on('handleBroadcast', function() {
$scope.message = 'TWO: ' + sharedService.message;
});
}
ControllerZero.$inject = ['$scope', 'mySharedService'];
ControllerOne.$inject = ['$scope', 'mySharedService'];
ControllerTwo.$inject = ['$scope', 'mySharedService'];

Resources