简体   繁体   中英

Breeze 1-m-1 in HotTowel Angular with local storage

I've had a requirement recently to implement a UI for managing a many-many relationship. Ward Bell kindly provided this plunker showing how to implement using 1-m-1 with Angular and Breeze.

My app's design is based largely (especially the datacontext and the local storage) is based largely on John Papa's recent Pluralsight courses.

In my app, BusUnit = Hero and Dimension = Power (in reference to Ward's example.

Everything seems to be working well when I force the app to fetch data from the server, in that my updates to a business unit's dimensions reflect correctly. The problem I'm facing now is when I navigate away from the page and back again (which gets data from local storage). In this case:

  • if I previously added a new dimension to a business unit, everything is ok, but
  • if i previously marked a business unit's dimension for deletion and the save, the dimension still appears for the business unit in question.

this is the controller code that initially gets business units and their dimensions:

function getdboardStructure() {
        var busUnitsPromise = datacontextSvc.busUnits.getByDboardConfigId(vm.dboardConfig.id);
        var dimensionsPromise = datacontextSvc.dimensions.getByDboardConfigId(vm.dboardConfig.id);

        $q.all([busUnitsPromise, dimensionsPromise])
            .then(function (values) {
                vm.busUnits = values[0];
                vm.dims = values[1];
                createBusUnitVms();
                //vm.currentBusUnitVm = vm.busUnitVms[0]; // not required as using accordion instead of drop-down
                vm.hasChanges = false;
            });
    }

this is the code in my controller that prepares for the save:

function applyBusUnitDimensionSelections(busUnitVm) {
        var busUnit = busUnitVm.busUnit;
        var mapVms = busUnitVm.dimensionMapVms;
        var dimensionHash = createBusUnitDimensionHash(busUnit);

        mapVms.forEach(function (mapVm) {
            var map = dimensionHash[mapVm.dimension.id];

            if (mapVm.selected) {
                if (!map) {
                    datacontextSvc.busUnits.addBusUnitDimension(busUnit, mapVm.dimension)
                    .then(function () {
                    });
                }
            } else {
                if (map) {
                    datacontextSvc.markDeleted(map);
                }
            }
        });
    }

this is the code in my controller that executes the save:

function save() {
        if (!canSave()) {
            return $q.when(null);
        }

        vm.isSaving = true;
        vm.busUnitVms.forEach(applyBusUnitDimensionSelections);
        return datacontextSvc.save().then(function (saveResult) {
            vm.isSaving = false;
            trapSavedDboardConfigId(saveResult); // not relevant to use case
        }, function (error) {
            vm.isSaving = false;
        });
    }

this is the code in my repository that add a new busUnitDimension entity:

function addBusUnitDimension(busUnit, dimension) {
        var newBusUnitDimension = this.em.createEntity(busUnitDimension);
        newBusUnitDimension.busUnitId = busUnit.id;
        newBusUnitDimension.dimensionId = dimension.id;
        return this.$q.when(newBusUnitDimension);
    }

this is my datacontext code for marking an item deleted:

function markDeleted(entity) {
        return entity.entityAspect.setDeleted();
    } 

and finally this is the repository code to get business units and their join table entities:

function getByDboardConfigId(dboardConfigId, forceRefresh) {
        var self = this;
        var predicate = pred.create('dboardConfigId', '==', dboardConfigId);
        var busUnits;

        if (self.zStorage.areItemsLoaded('busUnits') && !forceRefresh) {
            busUnits = self._getAllLocal(entityName, orderBy, predicate);
            return self.$q.when(busUnits);
        }

        return eq.from('BusUnits')
            .expand('BusUnitDimensions')
            .where(predicate)
            .orderBy(orderBy)
            .using(self.em).execute()
            .to$q(succeeded, self._failed);

        function succeeded(data) {
            busUnits = data.results;
            self.zStorage.areItemsLoaded('busUnits', true);

            self.zStorage.save();
            //self.logSuccess('Retrieved ' + busUnits.length + ' business units from server', busUnits.length, true);
            return busUnits;
        }
    }

My departure from John's course examples is that I'm using expand in the function I use to get Business Units from the server, and my hypothesis is that this has something to do with the fact that breeze is going to the server everytime I refresh the page (without clearing cache) instead, and that this also has something to do with the error i'm receiving if I navigate away and then back to the page.

Can anyone offer and suggestions?

Appreciate this was a long time ago and you have probably solved it or moved on but I came up against the same problem recently that took me ages to resolve. The answer I found is that you have to edit JP's angular.breeze.storagewip.js file. I contains the names of the entities hard-coded into the file and you will need to change these to match your own entities.

There are two functions where you need to do this, examples below show the changes with the four entities I am using:

function zStorageCore($rootScope, zStorageConfig) {
    var storeConfig = zStorageConfig.config;
    var storeMeta = {
        breezeVersion: breeze.version,
        appVersion: storeConfig.version,
        isLoaded: {
          elementAssets : false,
          surveyors : false,
          elements : false,
          assets : false
        }
    };

and...

    function checkStoreImportVersionAndParseData(importedData) {
        if (!importedData) {
            return importedData;
        }
        try {
            var data = JSON.parse(importedData);
            var importMeta = data[0];
            if (importMeta.breezeVersion === storeMeta.breezeVersion &&
                importMeta.appVersion === storeMeta.appVersion) {
              if (importMeta.isLoaded) {
                storeMeta.isLoaded.assets = storeMeta.isLoaded.assets || importMeta.isLoaded.assets;
                storeMeta.isLoaded.elements = storeMeta.isLoaded.elements || importMeta.isLoaded.elements;
                storeMeta.isLoaded.surveyors = storeMeta.isLoaded.surveyors || importMeta.isLoaded.surveyors;
                storeMeta.isLoaded.elementAssets = storeMeta.isLoaded.elementAssets || importMeta.isLoaded.elementAssets;
              }
                return data[1];
            } else {
                _broadcast(storeConfig.events.error,
                    'Did not load from storage because mismatched versions',
                    { current: storeMeta, storage: importMeta });
            }
        } catch (ex) {
            _broadcast(storeConfig.events.error, 'Exception during load from storage: ' + ex.message, ex);
        }
        return null; // failed
    }

I solved this by comparing JP's Style Guide course files with his SPA/Angular/Breeze course.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM