I have an app which fetches data from a database on load.
Since the data in the database changes every few seconds, I would like to dynamically add the new data in the database into the table in the HTML page.
Any ideas on how to implement without reloading the controller?
The current code:
app.js
var app = angular.module('myApp', ['ui.bootstrap','countTo']);
app.filter('startFrom', function() {
return function(input, start) {
if(input) {
start = +start; //parse to int
return input.slice(start);
}
return [];
}
});
app.config(['$compileProvider', function($compileProvider) {
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|http?|file|data):/);
}]);
app.controller('customersCrtl', function ($scope, $http, $timeout) {
$scope.$emit('LOAD');
$scope.progressBar = { progress : 0 };
$http.get('ajax/getCustomers.php').success(function(data){
$scope.list = data;
$scope.currentPage = 1; //current page
$scope.entryLimit = 50; //max no of items to display in a page
$scope.filteredItems = $scope.list.length; //Initially for no filter
$scope.totalItems = $scope.list.length;
$scope.$emit('UNLOAD');
});
(function progress(){
if($scope.progressBar.progress < 100){
$timeout(function(){
$scope.progressBar.progress += 1;
progress();
},5);
}
})();
$scope.setPage = function(pageNo) {
$scope.currentPage = pageNo;
};
$scope.filter = function() {
$timeout(function() {
$scope.filteredItems = $scope.filtered.length;
}, 10);
};
$scope.sort_by = function(predicate) {
$scope.predicate = predicate;
$scope.reverse = !$scope.reverse;
};
});
app.controller('delayController',['$scope',function($scope){
$scope.$on('LOAD',function(){$scope.loading=true});
$scope.$on('UNLOAD',function(){$scope.loading=false});
}]);
app.controller("PostsCtrl", function($scope, $http, $timeout) {
$scope.progressBarScanned = { progressScanned : 0 };
(function tick() {
$http.get('ajax/scanStatus.php').
then(function(response) {
$scope.posts = response.data;
$scope.scanProgerss = $scope.posts[0].isScanning;
$scope.scanPercentage = $scope.posts[0].scanPercentage;
$scope.timeToFinish = $scope.posts[0].timeToFinish;
$scope.amountScanned = $scope.posts[0].amountScanned;
$scope.totalItemsToScan = $scope.posts[0].totalItemsToScan;
$scope.avgScanTimePerItem = $scope.posts[0].avgScanTimePerItem;
});
$timeout(tick, 1000);
})();
(function progressScanned(scanned){
if($scope.scanPercentage < 100){
$timeout(function(){
$scope.progressScanned.progress = 1;
progressScanned();
},5);
}
})();
});
//Modal
var ModalDemoCtrl = function ($scope, $modal) {
$scope.open = function (imageKey) {
$modal.open({
templateUrl: 'myModalContent.html',
backdrop: true,
windowClass: 'full',
controller: function ($scope, $modalInstance, data, imageKey) {
$scope.data='';
$scope.data = data;
$scope.getImage = function () {
return $scope.data[imageKey];
}
$scope.cancel = function () {
$modalInstance.dismiss('close');
};
},
resolve: {
data: function() {
// access outer controller scope by using $scope.$parent
return $scope.$parent.data;
},
imageKey: function() {
return imageKey;
}
}
});
}};
Related
Im trying to add another function to my controller but it keeps breaking the controller.
here is my code:
.controller('ClimbController', [
'$scope', '$stateParams', 'Climbs', function(
$scope, $stateParams, Climbs) {
var climb_id = $stateParams.climbId;
var areaId = $stateParams.areaId;
if (!isNaN(climb_id)) {
climb_id = parseInt(climb_id);
}
if (!isNaN(areaId)) {
areaId = parseInt(areaId);
}
$scope.selected_ = {};
$scope.items = [];
$scope.details = true;
// looping though all data and get particular product
$scope.selectClimb = function(areas){
areas.forEach(function(data) {
if(data._id == climb_id){
$scope.selected_ = data;
}
});
}
// get all posts // try some function to get a single produt from server
$scope.getPosts = function(){
Climbs.getPosts()
.success(function (data) {
// data = feed.json file
var climbs = [];
data.areas.map(function(area) {
if (area._id === areaId) {
climbs = area.climbs;
}
});
$scope.selectClimb(climbs);
})
.error(function (error) {
$scope.items = [];
});
}
$scope.getPosts();
}
])
And I ned to add this to it:
.controller('MyCtrl', function($scope, $ionicModal) {
$ionicModal.fromTemplateUrl('test-modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.openModal = function() {
$scope.modal.show();
};
$scope.closeModal = function() {
$scope.modal.hide();
};
//Cleanup the modal when we're done with it!
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
// Execute action on hide modal
$scope.$on('modal.hidden', function() {
// Execute action
});
// Execute action on remove modal
$scope.$on('modal.removed', function() {
// Execute action
});
});
When I try to add this to the code it breaks it. I nee to either add it as another function or whatever is needed to add it to the code.
Thanks so much
Assuming that you want to merge 'MyCtrl functions into ClimbController then
.controller('ClimbController', ['$scope', '$stateParams', 'Climbs','$ionicModal', function($scope, $stateParams, Climbs,$ionicModal) {
var climb_id = $stateParams.climbId;
var areaId = $stateParams.areaId;
if (!isNaN(climb_id)) {
climb_id = parseInt(climb_id);
}
if (!isNaN(areaId)) {
areaId = parseInt(areaId);
}
$scope.selected_ = {};
$scope.items = [];
$scope.details = true;
// looping though all data and get particular product
$scope.selectClimb = function(areas){
areas.forEach(function(data) {
if(data._id == climb_id){
$scope.selected_ = data;
}
});
}
// get all posts // try some function to get a single produt from server
$scope.getPosts = function(){
Climbs.getPosts()
.success(function (data) {
// data = feed.json file
var climbs = [];
data.areas.map(function(area) {
if (area._id === areaId) {
climbs = area.climbs;
}
});
$scope.selectClimb(climbs);
})
.error(function (error) {
$scope.items = [];
});
}
$scope.getPosts();
$ionicModal.fromTemplateUrl('test-modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.openModal = function() {
$scope.modal.show();
};
$scope.closeModal = function() {
$scope.modal.hide();
};
//Cleanup the modal when we're done with it!
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
// Execute action on hide modal
$scope.$on('modal.hidden', function() {
// Execute action
});
// Execute action on remove modal
$scope.$on('modal.removed', function() {
// Execute action
});
}])
I have an AngularJS 1.2 app. My app has a controller that looks like this:
myApp.controller('MyController', ['$scope', '$rootScope', '$http',
function ($scope, $rootScope, $http) {
$scope.newItem_Click = function () {
var modalInstance = $modal.open({
templateUrl: 'item-dialog.html',
size: 'md',
controller: function ($scope, $modalInstance) {
$scope.item = { typeId: 7, id: '-1' };
$scope.saveItem = function (did) {
if ($scope.item.description) {
if ($scope.item.description.trim().length > 0) {
$scope.item.departmentId = did;
$modalInstance.close($scope.item);
}
} else {
alert('Please enter your description.');
}
};
$scope.cancelItem = function () {
$modalInstance.dismiss('cancel');
};
$scope.getItems = function (departmentId) {
var url = '/api/items?departmentId=' + departmentId;
return $http.get(url).then(
function (response) {
var results = response.data;
results.reverse();
var items = [];
var i = 0;
angular.forEach(results, function (item, key) {
var local = results[i].CreatedUTC;
results[i].CreatedOn = new Date(local);
items.push(item);
i = i + 1;
});
console.log(items);
$scope.items = items;
}
);
};
$scope.$on('list-updated', function () {
$scope.getItems($scope.item.id);
});
}
});
modalInstance.result.then(
function (item) {
var apiUrl = '/api/items';
apiUrl = apiUrl + '?typeId=' + item.typeId;
if (item.departmentId!== '-1') {
apiUrl = apiUrl + '&departmentId=' + item.departmentId;
}
apiUrl = apiUrl + '&content=' + item.description;
apiUrl = encodeURI(apiUrl);
$http.post(apiUrl).then(
function () {
$rootScope.$broadcast('list-updated');
}
);
}
);
};
}]);
For some reason, I can successfully save an item. The console.log(items) statement displays all of the items as I would expect. However, my view is not being updated. What am I doing wrong? I suspect its because I'm assigning $scope.items inside of the HTTP response. Yet, I'm not sure how to get around it.
I know this is not recommended. However, I am in crunch mode.
I am trying to get the "make sure modalInstance.result.then is executed" test in my code to pass. Right now it says Expected [ undefined, 'http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com' ] to contain 'http://www.pressboardmedia.com' I believe this has something to do with the promise needing to be mocked so it passes along the campaignLink but I am unsure if this is the problem and cannot seem to get it to work regardless. please let know if you have any ideas.
Thanks!
Controller File
angular.module('pb.campaignLinks.controllers')
.controller('CampaignLinksController', ['$scope', '$timeout', '$modal', '$stateParams', 'global', 'campaignLinkService', function ($scope, $timeout, $modal, $stateParams, global, campaignLinkService) {
$scope.init = function (currentView) {
$scope.partialViews = {
campaignLinkList: "/app/campaignLinks/views/_list.html",
};
$scope.currentView = currentView;
$scope.getCampaignLinks(currentView, 10);
};
$scope.getCampaignLinks = function (currentView, length, continuationToken) {
// When loading list items, display loading image
if ($scope.campaignLinks) $scope.campaignLinks.loading = true;
var promiseObj = null;
if (currentView.campaignId && currentView.campaignId !== 0 && !currentView.buyRequestId) {
promiseObj = campaignLinkService.getCampaignLinks(global.activeOrganizationId, currentView.campaignId, length, continuationToken)
} else if (currentView.campaignId && currentView.buyRequestId && currentView.campaignId !== 0 && currentView.buyRequestId !== '') {
promiseObj = campaignLinkService.getCampaignBuyRequestLinks(global.activeOrganizationId, currentView.campaignId, currentView.buyRequestId, length, continuationToken);
} else if (currentView.webSiteId && currentView.buyRequestId && currentView.webSiteId !== 0 && currentView.buyRequestId !== '') {
promiseObj = campaignLinkService.getWebSiteBuyRequestLinks(global.activeOrganizationId, currentView.webSiteId, currentView.buyRequestId, length, continuationToken);
}
if (promiseObj) {
promiseObj.then(function (data) {
// If there are already some campaign links being displayed, add newly loaded list to the end
if ($scope.campaignLinks) {
$scope.campaignLinks.continuationToken = data.continuationToken;
$scope.campaignLinks.total += data.total;
$.each(data.items, function (index) {
$scope.campaignLinks.items.push(data.items[index]);
});
} else {
// Otherwise add loaded list to scope
$scope.campaignLinks = data;
}
// When done loading, hide loading image
$scope.campaignLinks.loading = false;
});
}
};
$scope.openAddCampaignLink = function (campaignId) {
var modalOptions = {
templateUrl: '/app/campaignLinks/views/_add.html',
controller: 'AddCampaignLinksModalController',
resolve: {
campaignId: function () {
return campaignId;
}
}
};
var modalInstance = $modal.open(modalOptions);
modalInstance.result.then(function (campaignLink) {
// Add new item to list, otherwise wait for it to be loaded manually.
$scope.campaignLinks.items.unshift(campaignLink);
$scope.campaignLinks.total += 1;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
$scope.openRemoveCampaignLink = function (campaignId, campaignLink, index) {
var modalOptions = {
templateUrl: '/app/campaignLinks/views/_delete.html',
controller: 'RemoveCampaignLinksModalController',
resolve: {
campaignId: function () {
return campaignId;
},
campaignLink: function () {
return campaignLink;
}
}
};
var modalInstance = $modal.open(modalOptions);
modalInstance.result.then(function () {
// Splice the deleted item from the list without reloading all
$scope.campaignLinks.items.splice(index, 1);
$scope.campaignLinks.total -= 1;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
// Once everything is loaded, initialize controller
// init();
}]);
Test file:
describe('CampaignLinksController', function () {
//make module avalible to tests
beforeEach(module('pb.campaignLinks.controllers'));
beforeEach(module('ui.router'));
beforeEach(module('ui.bootstrap'));
var $controller;
var mockPromiseObj;
var length = 200;
var mockModal = {};
var mockCampaignLinks = {
total: 3,
items: ['http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com']
};
var mockCurrentView = {};
var mockGlobal = { activeOrganizationId: 54 };
var continuationToken = {
nextRowKey: 'fdsf2',
nextPartitionKey: '5432gee'
};
var campaignDetails = {
campaignId: 453,
campaignLink: 'http://www.pressboardmedia.com',
index: 1
};
var mockCampaignLinkService = {
//move campaignDetails here
campaignLinks: {
total: 3,
//length here
items: ['http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com']
},
//all but delete must return a promiseObj
getCampaignLinks: jasmine.createSpy('mockCampaignLinkService.getCampaignLinks').and.returnValue(mockPromiseObj),
getCampaignBuyRequestLinks: jasmine.createSpy('mockCampaignLinkService.getCampaignBuyRequestLinks').and.returnValue(mockPromiseObj),
getWebSiteBuyRequestLinks: jasmine.createSpy('mockCampaignLinkService.getWebSiteBuyRequestLinks').and.returnValue(mockPromiseObj),
deleteCampaignLink: jasmine.createSpy('mockCampaignLinkService.deleteCampaignLinks')
};
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
beforeEach(inject(function ($rootScope) {
controller = $controller('CampaignLinksController',
{
$scope: scope,
$modal: mockModal,
//$stateParams: mockStateParams,
global: mockGlobal,
campaignLinks: mockCampaignLinks,
campaignLinkService: mockCampaignLinkService,
currentVeiw: mockCurrentView,
//promiseObj: mockPromiseObj
});
}));
describe('openAddCampaignLink()', function () {
var actualOptions;
var modalOptions = {
templateUrl: '/app/campaignLinks/views/_add.html',
controller: 'AddCampaignLinksModalController',
resolve: {
campaignId: jasmine.any(Function)
}
};
beforeEach(inject(function ($q) {
mockModal.open = function (options) {
actualOptions = options;
var defer = $q.defer();
defer.resolve();
return { result: defer.promise };
}
}));
it("make sure modalInstance.result.then is executed", function () {
scope.campaignLinks = mockCampaignLinkService.campaignLinks;
scope.openAddCampaignLink(campaignDetails.campaignId, campaignDetails.campaignLink, campaignDetails.index);
scope.$digest();
expect(scope.campaignLinks.total).toEqual(4);
expect(scope.campaignLinks.items).toContain(campaignDetails.campaignLink);
});
});
I think your problem is that the argument "campaignLink" that is supplied to your modalInstance.result.then function will always be undefined when you test this. The code that calls the modal close should be tested that it is supplying the campaignLink correctly. You only want to test that the proper code gets executed when the modal is closed. We do that by supplying a function that can be tested on it's own to the modalInstance.result.then call instead of doing an inline function so it can be tested easier.
Here's an example:
Here's the code that opens the modal:
$scope.editGradeClick = function () {
var modalInstance = $modal.open({
templateUrl: templateSrv.templateUrl('/Templates/App/Courses/CourseLessonGradeModal.html'),
controller: courseLessonGradeModalBootstrap,
backdrop: 'static',
keyboard: false,
resolve: {
data: $scope.editGradeModalResolve
}
});
modalInstance.result.then(
null,
$scope.editGradeModalDismissCallback
);
};
Notice how we supply a function $scope.editGradeModalDismissCallback instead of writting an inline function there for a modal dismiss. This allows us to test that logic in it's own test.
Now here is the test. We only care that the above function was called since we will be testing the specific function in it's own test. That happens at the last line in the test.
var $controllerConstructor, $scope, $q;
beforeEach(function () {
module('appModule');
inject(function ($controller, $rootScope, _$q_) {
$controllerConstructor = $controller;
$scope = $rootScope.$new();
$q = _$q_;
});
});
it('should execute $scope.editGradeModalDismissCallback when modal is dismissed', inject(function (templateSrv) {
var $modal = {};
$modal.open = function () {
var queryPromise = $q.defer();
queryPromise.reject();
return { result: queryPromise.promise };
};
$controllerConstructor('CourseLessonGradeListCtrl', { $scope: $scope, $modal: $modal, templateSrv: templateSrv});
spyOn($modal, "open").andCallThrough();
spyOn($scope, "editGradeModalDismissCallback");
$scope.editGradeClick();
$scope.$root.$digest();
expect($scope.editGradeModalDismissCallback).toHaveBeenCalled();
}));
I hope this helps you. In this example we are rejecting the promise because we are testing the modal dismiss not close, fyi...
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");
};
}]);
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'];