Marco
Marco

Reputation: 49

breeze.config.MetadataHelper is not a constructor error with Durandal and Breeze

I am working on a SPA using Durandal v2.1 and Breeze v1.5. This is the first time I am using these libraries. I am creating the metadata for Breeze by hand, thus I'm using the Metadata-Helper plugin as explained in the documentation for Breeze. For this I am relying on examples found here. When I run the application I get the following error:

Error: Failed to load root module (viewmodels/shell). Details: breeze.config.MetadataHelper is not a constructor.

The error seems to occur in the metadataFactory.js file that I use to create the metadata with this line of code (see the metadataFactory.js file further down in the post):

helper = new breeze.config.MetadataHelper(namespace, keyGen);

All the examples I have seen clearly show that the above is a valid instruction, so I am not able to understand what the problem is.

This is my main.js:

requirejs.config({
    'paths': {
        'durandal': '../durandal',
        'plugins': '../durandal/plugins',
        'transitions': '../durandal/transitions',
        'text': '../durandal/amd/text',

        'jquery': '../../Scripts/jquery-2.1.3.min',
        'jqueryUI': '../../Scripts/jquery-ui-1.11.2.min',
        'knockout': '../../Scripts/knockout-3.2.0',
        'bootstrap': '../../Scripts/bootstrap.min',
        'breeze': '../../Scripts/breeze.min',
        'breezeMetadataHelper': '../../Scripts/breeze.metadata-helper',
        'Q': '../../Scripts/q.min',

        'toastr': '../../Scripts/toastr.min',
        'moment': '../../Scripts/moment',

        'logger': '../services/logger',
        'hubService': '../services/hubService',
        'datacontext': 'dataservices/datacontext',
        'metadataFactory': 'dataservices/metadataFactory',
        'constants': 'models/constants',
        'menu': '../shared/viewmodels/menu',
        'menuItem': '../shared/viewmodels/menuItem'
    },
    'shim': {
        'bootstrap': {
            'deps': ['jquery']
        },
        'select2': {
            deps: ['jquery', 'style!Content/select2-bootstrap'],
            exports: 'select2'
        },
        'breeze': {
            deps: ['knockout', 'jquery', 'Q']
        },
        'breezeMetadataHelper': {
            deps: ['breeze']
        }
    },
    urlArgs: 'bust=' + (new Date()).getTime()
});


define(['durandal/system', 'durandal/app', 'durandal/viewLocator', 'logger'], function (system, app, viewLocator, logger) {

    //>>excludeStart('build', true);
    system.debug(true);
    //>>excludeEnd('build');

    logger.log('Loading main module');

    app.title = 'ERWS';

    app.configurePlugins({
        router: true,
        dialog: true,
        widget: {
            kinds: ['grid'] // durandal-grid widget (https://github.com/tyrsius/durandal-grid)
        }
    });

    app.start().then(function () {
        viewLocator.useConvention();
        app.setRoot('viewmodels/shell', 'entrance');
    });
});

This is my shell.js file:

define(function (require) {
    'use strict';

    var logger = require('logger');
    logger.log('Loading shell module');

    var ko = require('knockout');
    var router = require('plugins/router');
    var app = require('durandal/app');
    var constants = require('constants');
    var model = require('models/userInfo');

    var entity = {
        contentBody: ko.observable(''),
        appName: constants.AppName,
        copyrightText: constants.CopyrightText,
        userName: ko.observable(''),
        userImage: ko.observable('')
    };

    var loadData = function () {
        var data = model.entity;

        if (data) {
            entity.userName(data.UserName);
            entity.userImage(data.UserImage);
        } else {
            logger.log('Error loading user info');
        }
    };

    return {
        dashboard: entity,
        activate: function () {
            loadData();
        }
    };
});

And this is the metadataFactory.js which I use to create the metadata, based on the example I have found here:

/* 
 * Creates BreezeJS Metadata
 *
 * Usage:
 *    // assume you include this service as 'metadataFactory'
 *
 *    // create a new EntityManager
 *    var manager = new breeze.EntityManager("your-service-endpoint");
 *
 *    // get the MetadataStore from the manager and fill it
 *    var store = manager.metadataStore;
 *    metadataFactory.fillMetadataStore(store);
 *   
 */
define(function (require) {
    'use strict';

    var logger = require('logger');
    logger.log('Loading metadataFactory module');

    var breeze = require('breeze');

    var addType, date, dt, bool, helper, id, identity;

    function addCommunityInfo() {
        addType({
            name: 'CommunityInfo',
            defaultResourceName: 'CommunityInfos',
            autoGeneratedKeyType: identity,
            dataProperties: {
                id: { type: id },
                groupsTotal: { max: 3, nullOk: false },
                regionsTotal: { max: 3, nullOk: false },
                landExtensionTotal: { max: 7, nullOk: false },
                parcelsTotal: { max: 4, nullOk: false }
            }
        });
    }

    function addDevicesInfo() {
        addType({
            name: 'DevicesInfo',
            defaultResourceName: 'DevicesInfos',
            autoGeneratedKeyType: identity,
            dataProperties: {
                id: { type: id },
                deviceServers: { max: 3, nullOk: false },
                deviceAdBoards: { max: 3, nullOk: false },
                deviceControllers: { max: 3, nullOk: false },
                deviceTotalUnits: { max: 3, nullOk: false }
            }
        });
    }

    function addGroupInfo() {
        addType({
            name: 'GroupInfo',
            defaultResourceName: 'GroupInfos',
            autoGeneratedKeyType: identity,
            dataProperties: {
                id: { type: id },
                groupName: { max: 50, nullOk: false },
                acronym: { max: 5, nullOk: false },
                dateOfAffiliation: { type: date, nullOk: false },
                inworldDescription: { max: 50, nullOk: false },
                webDescription: { max: 50, nullOk: false },
                yourRoleValue: { max: 50, nullOk: false },
                landOwnedSize: { type: id },
                landOwnedValue: { max: 50, nullOk: false },
                numberOfRentals: { max: 50, nullOk: false },
                presentInRegions: { max: 50, nullOk: false },
                numberOfParcels: { max: 50, nullOk: false },
                numberOfDevices: { max: 50, nullOk: false },
                userRole: { max: 50, nullOk: false },
                inWorldKey: { max: 50, nullOk: false },
                created: { type: date, nullOk: false },
                updated: { type: date, nullOk: true }
            },

            navigationProperties: {
                regions: { type: 'Region', hasMany: true },
                devices: { type: 'Device', hasMany: true },
                rentals: { type: 'Rental', hasMany: true }
            }
        });
    }

    // shorten for brevity....

    // Initialize the metdataFactory with convenience fns and variables 
    function init(metadataStore, serviceName) {

        var store = metadataStore; // the metadataStore that we'll be filling
        store.namingConvention = breeze.NamingConvention.camelCase;

        // namespace of the corresponding classes on the server
        var namespace = 'FieryRed.ErcApplication.Core.ViewModel.Admin';

        // 'Identity' is the default key generation strategy for this app
        var keyGen = breeze.AutoGeneratedKeyType.Identity;

        // Breeze Labs: breeze.metadata-helper.js
        // https://github.com/Breeze/breeze.js.labs/blob/master/breeze.metadata-helper.js
        // The helper reduces data entry by applying common conventions
        // and converting common abbreviations (e.g., 'type' -> 'dataType')
        helper = new breeze.config.MetadataHelper(namespace, keyGen);      <===================== My problem seems to be caused by this line of code
        helper.addDataService(store, serviceName);

        // addType - make it easy to add the type to the store using the helper
        addType = function (type) {
            return helper.addTypeToStore(store, type);
        };

        // DataTypes we'll be using
        dt = breeze.DataType;
        date = dt.DateTime;
        id = dt.Int32;
        bool = dt.Boolean;

        identity = breeze.AutoGeneratedKeyType.Identity;
    }

    /*** Implementation ***/
    function fillMetadataStore(metadataStore, serviceName) {
        init(metadataStore, serviceName);

        addCommunityInfo();
        addDevicesInfo();
        addGroupInfo();
        // etc.
    }

    // The metadata definition service
    return {
        fillMetadataStore: fillMetadataStore
    };
});

Upvotes: 0

Views: 270

Answers (1)

Ward
Ward

Reputation: 17863

My guess is that you did not call require for "breeze.metadataHelper". You can confirm that it was (or wasn't) loaded by setting a breakpoint in your metadataFactory.js and seeing if it is present on breeze.config. If it isn't, then you didn't load it.

You might require it explicitly at the top of metadataFactory.js if that's the only place you use it. Or make metadataFactory.js depend upon it. Either should work although I haven't checked myself.

p.s.: You may find that you're over thinking your require configuration. Defaults could trim this substantially. Also "breeze.metadataHelper" already tells require that it depends upon breeze.

Upvotes: 1

Related Questions