2016-11-15 4 views
0

Я уже проверял ответы от людей, у которых есть, по-видимому, одна и та же проблема, но я еще не смог исправить свою проблему.Магистральная коллекция не является конструктором

У меня есть мнение (teacher.profile.js), который звонит коллекцию (levels.js), который имеет коллекцию (subject.js), но когда я загрузить страницу коллекция предмет всегда undefined и сказал, чтобы не быть конструктором.

После обновления столько раз, иногда второй, есть коллекция subject и работает.

Может ли кто-нибудь сказать мне, что не так, пожалуйста?

Благодаря

subject.js

define(["GB"], function(GB) { 

     var subjectModel = GB.Model.extend({ 
     idAttribute:"subjectId", 
     defaults: { 
      subjectId: '', 
      name: '', 
      levelId: '', 
      selected: false 
     } 
     }); 

     return subjectModel; 
    }); 

subjects.js

define([ 
     "GB", 
     "modules/register/teacher/models/subject"], 
     function (GB, SubjectModel) { 

     var subjectCollection = GB.Collection.extend({ 
     model: SubjectModel, 
     url: "webapi/api/Administration/Subject" 
     }); 

     return subjectCollection; 
    }); 

level.js

define(['GB', 'modules/register/teacher/models/subjects'], function (GB, SubjectCollection) { 

     var levelModel = GB.Model.extend({ 
     defaults: { 
      levelId: '', 
      name: '', 
      iconClass: '', 
      subjects: '' 
     }, 
     parse: function(attrs) { 
      **attrs.subjects = new SubjectCollection(attrs.subjects);** //Here is where the error is thrown. SubjectCollection is not a constructor. 
      return attrs; 
     } 
     }); 

     return levelModel; 
    }); 

levels.js

define(["GB", "modules/register/teacher/models/level"], function (GB, LevelModel) { 

     var levelCollection = GB.Collection.extend({ 
     model: LevelModel, 
     url: "webapi/api/Administration/Level" 
     }); 

     return levelCollection; 
    }); 

teacher.profile.js вид

define([ 
     "GB", 
     "tpl!modules/register/teacher/teacherProfile", "modules/register/teacher/subject.level" 
    ], function(GB, Template, SubjectLevelView) { 
     var view = GB.Views.Item.extend({ 
     template: Template, 
     ui: { 
      subjects: "#subject-list", 
      levels: "#level-list", 
      infoTitle: "#info-title", 
      subjectsLevels: "#subjects-levels" 
     }, 
     initialize: function() { 
      this.userLevels = []; 
     }, 
     onRender: function() { 
      var self = this; 
      this.ui.infoTitle.text(GB.Localise("teacher-data-title")); 
      var levelsPromise = this.collection.fetch(); 
      $.when(levelsPromise) 
      .then(function() { 
       var levelsSubjects = _.map(self.collection.models, function(item) { 
       if (item.get("subjects").length > 0) { 
        var view = new SubjectLevelView({ model: item }); 
        self.userLevels.push(item); 
        return view.render().el; 
       } 
       }); 
       self.ui.subjectsLevels.append(levelsSubjects); 
      }); 
     } 
     }); 
     return view; 
    }); 

main.js

require.config({ 
     map: { 
      '*': { 
       'css': 'plugins/require-css/css', 
       'tpl': 'plugins/require.lodash.template', //this is our templating helper tpl!.html, its brings the template in already underscored, this is faster slightly than text! & subsequent template 
       'lodash': 'underscore' 
      } 
     }, 
     paths: { 
      'plugins': '../plugins', 
      'styles':'../css', 
      'localisation':'core/localisation', 
      'jquery': '../lib/jquery-2.1.4', 
      'jquery.browser': '../plugins/jquery.browser', 
      'jquery.video': '../plugins/vide/jquery.vide', 
      'waypoints': '../plugins/waypoints/jquery.waypoints', 
      'backbone': '../lib/backbone', 
      'marionette': '../lib/backbone.marionette', 
      'text': '../lib/text', 
      'underscore': '../lib/lodash.underscore', //yes underscore is now lodash - its a better performer + extra features + no downside :) 
      'lodash': '../lib/lodash.underscore', 
      'bootstrap': '../lib/bootstrap', 
      'bootstrap-dialog': '../plugins/bootstrap-dialog/js/bootstrap-dialog', 
      'modernizr': '../lib/modernizr-2.8.3', 
      'backbone.validation': '../plugins/backbone-validation', 
      'themepunch.tools': '../plugins/rs-plugin/js/jquery.themepunch.tools.min', 
      'themepunch.rev': '../plugins/rs-plugin/js/jquery.themepunch.revolution.min', 
      'smoothscroll': '../plugins/SmoothScroll', 
      'json': '../plugins/requirejs-plugins/json', 
      'cldr': '../plugins/localisation/cldrjs/cldr', 
      'cldr-data': '../plugins/localisation/cldr-data', 
      'globalize': '../plugins/localisation/globalize/globalize', 
      'localise':'localisation/localise', 
      'GB': 'app' 
     }, 
     shim: { 
      'marionette': { 
       deps: ['backbone'], 
       exports: 'Marionette' 
      }, 
      'backbone': { 
       deps: ['underscore', 'jquery'], 
       exports: 'Backbone' 
      }, 
      'underscore': { 
       exports: '_' 
      }, 
      'backbone.validation': { 
       deps: ['backbone', 'underscore'] 
      }, 
      'bootstrap': { 
       deps: ['jquery'], 
      }, 
      'bootstrap-dialog': { 
       deps: ['bootstrap'], 
      }, 
      'smoothscroll': { 
       deps: ['jquery.browser'] 
      }, 
      'themepunch.tools': { 
       deps: ['jquery'] 
      }, 
      'themepunch.rev': { 
       deps: ['themepunch.tools'] 
      }, 
      'jquery.browser': { 
       deps: ['jquery'] 
      }, 
      'waypoints': { 
       deps: ['jquery'] 
      }, 
      'jquery.video': { 
       deps: ['jquery'] 
      }, 
      'globalize': { 
       deps: ['cldr'] 
      }, 
      'json': { 
       deps: ['text'] 
      } 
     } 
    }); 
    require([ 
     "GB", 
     "routes/application.router", 
     "bootstrap", 
     "core/validation"], 
     function (GB, AppRouter) { 
      GB.routers.application = new AppRouter(); 
      GB.start(); 
     }); 

app.js

define([ 
     "marionette", 
     "core/GB.ini", 
     "globalize", 
     "localisation/localise", 
     "bootstrap-dialog", 
     "json!cldr-data/supplemental/likelySubtags.json", 
     "json!cldr-data/supplemental/plurals.json", 
     "json!cldr-data/supplemental/timeData.json", 
     "json!cldr-data/supplemental/weekData.json", 
     "json!localisation/messages/es.json", 
     "globalize/number", 
     "globalize/message", 
     "globalize/plural", 
     "modernizr", 
     "smoothscroll", 
    ], 
     function (Marionette, AppIni, Globalize, Localise, Dialog, LikeSubtags, Plurals, TimeData, WeekData, Messages) { 
      var GB = window.GB = new Marionette.Application(); 
      GB.User = {}; 
      GB.routers = {}; 

      Globalize.load(
       LikeSubtags, 
       Plurals, 
       TimeData, 
       WeekData 
      ); 
      Globalize.loadMessages(Messages); 
      Globalize.locale("es"); 

      GB.Globalize = Globalize; 
      GB.Localise = Localise; 
      GB.Dialog = Dialog; 

      GB.Model = Backbone.Model.extend({}); 
      GB.Collection = Backbone.Collection.extend({}); 

      GB.Views = { 
       //if we do expand on these views they should probably get their own file. 
       Item: Marionette.ItemView.extend({}), //for a single model 
       Collection: Marionette.CollectionView.extend({}), //for a collection 
       Composite: Marionette.CompositeView.extend({}), //for a combination of a model and a collection 
       Layout: Marionette.LayoutView.extend({}) 
      }; 

      GB.session = new GB.Model(); 

      GB.getUrl = function() { 
       return Backbone.history.location.origin + Backbone.history.location.pathname; 
      } 

      GB.getCurrentRoute = function() { 
       return Backbone.history.fragment; 
      }; 



      GB.on("before:start", function() { 
       var RegionContainer = Marionette.LayoutView.extend({ 
        el: "#app-container", 

        regions: { 
         header: "#header-wrapper", 
         main: "#main-region", 
         footer: "#footer-region", 
         dialog: "#dialog-region" 
        } 
       }); 

       GB.regions = new RegionContainer(); 

      }); 

      GB.on("start", function() { 
       require(["modules/header/header.module"], function() { 
        GB.Header.Controllers.Overview.show(); 
       }); 
       require(["modules/footer/footer.module"], function() { 
        GB.Footer.Controllers.Overview.show(); 
       }); 
       AppIni.start(); 
       Backbone.history.start(); 
       if (GB.getCurrentRoute() === "") 
        Backbone.history.navigate("#home", { trigger: true }); 
      }); 

      return GB; 
     }); 

Foder структура

enter image description here

+0

Можете ли вы показать пример извлеченного 'json'? – oak

+0

Здесь вы идете, его в представлении teacher.profile. GB.session.Levels = new LevelCollection(); var levelsPromise = GB.session.Levels.fetch(); –

+0

Это не выбранный 'json'. –

ответ

0

Ok моя первая догадка, что parse метод на levelModel никогда не вызывается. Но его всегда следует называть fetched. Более того, я перечитал ваш вопрос и увидел, что иногда это работает для вас.

Так что моя вторая догадка теперь race condition с requirejs. i.e: иногда внутри levels.js SubjectCollection является реальным Backbone Collection и иногда не определено.

Одной из причин такого race может быть Circular Dependencies. Можете ли вы поделиться полным источником? или убедитесь, что у вас нет такого circulation?

+0

Спасибо за ответ. Мне не нужно называть метод parse, он называется, когда я собирал коллекцию. В представлении file.profile js файл, где я вызываю выборку коллекции Levels. Посмотрите рендер моего представления. Я уже проверил круговую ссылку, которую я прочитал из другого сообщения, но представление вызывает сборники уровней и набор уровней, создающих коллекцию предметов. –

+0

Любая идея, что происходит? У меня все еще есть ошибка и проверьте все, что вы мне сказали. Вам нужно, чтобы я делил больше кода? Thx –

+0

Эй, если вы можете поделиться кодом онлайн/офлайн, чтобы его можно было отлаживать, он может с уверенностью помочь. – oak

Смежные вопросы