In the process of developing a CRM application with a single-page application structure, I am integrating BreezeJS and AngularJS. The implementation involves utilizing dynamically-generated tabs to display various modules. Each time a user clicks on a menu item, a new tab is created, loading an HTML template (referred to as a module) into the content area. While some modules, like a grid of Accounts, are designed to be opened once at a time, others such as the Account Editor can be opened multiple times concurrently. This setup allows users to edit numerous accounts within a single instance of the Accounts grid.
To handle the Account Editor module effectively, I have established a system where a primary Breeze EntityManager
is configured with essential parameters and then replicated when creating a new Account Editor using masterManager.createEmptyCopy()
. The code for this process can be found at .
var serviceName = "/breeze/accounts";
var ds = new breeze.DataService({
serviceName: serviceName,
hasServerMetadata: true
});
var masterManager = new breeze.EntityManager({
dataService: ds,
saveOptions: new breeze.SaveOptions({ allowConcurrentSaves: false })
});
function createManagerCopy() {
var sandboxManager = masterManager.createEmptyCopy();
return sandboxManager;
}
Subsequently, I execute an EntityQuery
by passing the copied EntityManager
and entity Id (key)
to retrieve the necessary Account information and populate each open editor seamlessly using Breeze functionalities.
function queryAccountByKey(mgr, key) {
var keyPredicate = breeze.Predicate.create('id', 'eq', key);
var query = new breeze.EntityQuery('AccountsBase')
.expand('ContactsBase')
.where(keyPredicate);
var promise = mgr.executeQuery(query)
.catch(queryFailed);
return promise;
function queryFailed(error) {
console.log('Query Account by Id Failed', error);
return $q.reject(error);
}
}
Although no conflicts arise among open editors and their respective entity managers as long as the copied EntityManager
remains in the Angular scope
of the module. Editing and saving become simplified and efficient.
However, a challenge arises when transitioning to another Angular route
like a login screen and returning to the home screen. Due to the intricacies of each tabbed module, any previously opened Account Editor modules must be reloaded from stored settings to avoid having multiple Breeze entity managers handling the same account. This situation leads to changes being committed multiple times for a single Account Editor.
The main issue revolves around accessing a specific EntityManager
instance upon revisiting the home layout when the original reference in the scope is lost. Is there a method to query or remove an instance from an EntityManager
collection to streamline this process? Insights on how to manage instances efficiently or suggestions for alternative approaches would be highly appreciated.
SOLUTION
After implementing PW Kad's suggestion, I solved the dilemma by reusing entity managers instead of recreating them every time. By storing them in an object collection on the $rootScope when initialized and assigning a unique ID to associate with each tab, I could easily access and manage these instances throughout the Angular app without cluttering the global namespace.
The updated code snippet showcases this improvement:
// Addition of 'entityManagers' object to the $rootScope
angular.module('app', [])
.run(['$rootScope', function($rootScope) {
$rootScope.entityManagers = {};
$rootScope.entityManagers.count = 0;
}]);
// Within the dataServices factory:
var serviceName = "/breeze/accounts";
var ds = new breeze.DataService({
serviceName: serviceName,
hasServerMetadata: true
});
var masterManager = new breeze.EntityManager({
dataService: ds,
saveOptions: new breeze.SaveOptions({ allowConcurrentSaves: false })
});
function createManager(instanceId) {
var sandboxManager = masterManager.createEmptyCopy();
// Storing the EntityManager instance in $rootScope
$rootScope.entityManagers['EM_' + instanceId] = sandboxManager;
$rootScope.entityManagers.count++;
return sandboxManager;
}
// To delete the EntityManager from $rootScope if needed
function deleteManager(instanceId) {
var manager = $rootScope.entityManagers['EM_' + instanceId];
manager.clear();
delete $rootScope.entityManagers['EM_' + instanceId];
$rootScope.entityManagers.count--;
}
// Integration within an Angular controller
$scope.instanceId = '1234';
$scope.init = function() {
var manager = $rootScope.entityManagers['EM_' + $scope.instanceId];
if (manager === undefined) {
$scope.entityManager =
entityManagerService.createManager($scope.instanceId);
} else {
$scope.entityManager = manager;
}
}
$scope.getEntityById = function(id){
//utilize $scope.entityManager here to query database via Breeze
}
While questions about the internal storage location of BreezeJS’s EntityManager
collection persist, this solution offers a practical workaround. Hopefully, this detailed explanation provides assistance to anyone encountering a similar scenario!