2013-07-14 19 views
1

這與我發佈的另一個問題here有關,但它仍然讓我難以置信。正確使用Backbone從視圖內listenTo;木偶區域未定義?

我有一個簡單的骨幹模型實例,名爲searchResult,我在我看來工作很好。

我基本上想做的事很簡單;隨着此模型更改,重置視圖中的內容區域。

出於某種原因,當我在裏面一看,這段代碼似乎並沒有正常工作,但它似乎應該:

查看代碼:

define [ 
     'backbone.marionette', 
     "jquery", 
     "underscore", 
     "backbone", 
     'text!globalTemplates/sidebar.html', 
     "global/models/sidebar", 
     "global/views/categories", 
     "global/collections/categories", 
     "global/views/stores", 
     "global/collections/stores", 
     'search/models/search-results' 
    ], (Marionette, $, _, Backbone, SidebarTemplate, SidebarModel, categoriesView, categoriesCollection, storesView, storesCollection, SearchResult) -> 
     class SidebarLayout extends Marionette.Layout 

     template:     _.template SidebarTemplate 
     id:      'sidebar' 
     className:    'js-sidebar marionette-layout' 
     tagName:     'aside' 

     regions: 
      form:     'form' 
      categoriesList:   '#categories-list' 
      storesList:    '#stores-list' 

     ui: 
      searchInput:   "input.search" 
      logo:     "strong#logo a" 
      lower:     ".lower" 
      top:     ".top" 

     events: 
      "click strong#logo a": "goHome" 
      "submit .top form":  "search" 
      "click button.submit": "search" 
      # "keyup input.search": "quickSearch" 

     initialize: (opts) -> 
      @router = opts.router 

      # event triggers 
      @on "sidebar:finished", @resize, @ 

      # override the categories display event 
      @categoriesList.open = (view) -> 
      this.$el.hide() 
      this.$el.html(view.el) 
      this.$el.slideDown(250, "easeOutExpo") 

      # override the stores display event 
      @storesList.open = (view) -> 
      this.$el.hide() 
      this.$el.html(view.el) 
      this.$el.slideDown(250, "easeOutExpo") 

      # override the categories remove event 
      @categoriesList.remove = (view) -> 
      this.$el.html(view.el) 
      this.$el.slideUp(250, "easeOutExpo", -> $(this).remove()) 

      # override the stores display event 
      @storesList.remove = (view) -> 
      console.log 'stores remove' 
      this.$el.slideUp(250, "easeOutExpo", -> $(this).remove()) 

     globalListeners: -> 

      # bind app vent and other global handlers 
      # app.vent.on "search:setParams", @setSearchInput 

      # SearchResult.on "change:params", @setSidebar, @ 

      # bind to changes to search params. 
      # SearchResult.listenTo @, "change:params", @setSidebar() 
      SearchResult.listenTo @, "change", @setSidebar() 
      # SearchResult.on "change:params", @render, @ 

     resize: => 
      sidebarHeight = @$el.height() 
      topHeight  = @ui.top.height() 
      @ui.lower.height(sidebarHeight - topHeight) 

     setSidebar: (input=true) => 
      # console.dir "SidebarLayout: setSidebarContent" 
      if input then @setSearchInput() 

      if SearchResult.get("params") 
      switch SearchResult.get("params").type 
       when "categories" 
        @setCategories() 
       when "text" 
        @setStores() 
        @setCategories() 

     setSearchInput: -> 
      if SearchResult.get("params")? 
      searchTerm = SearchResult.get("query") 
      @ui.searchInput.attr("value", searchTerm) 
      else 
      @ui.searchInput.attr("value", "") 

     setStores: -> 
      stores = new storesCollection() 
      stores.fetch 
      success: => 
       @storesView = new storesView 
       collection: stores 
       @storesList.show @storesView 
       @storesList.$el.prev("h3").show() 
       @trigger "sidebar:finished" 

     setCategories: -> 
      # console.log 'SidebarLayout: setCategories' 
      categories = new categoriesCollection() 
      categories.fetch 
      success: => 
       @categoriesView = new categoriesView 
       collection: categories 
       @categoriesList.show @categoriesView 
       @categoriesList.$el.prev("h3").show() 
       @trigger "sidebar:finished" 

     reset: => 
      @$el.css 
      "opacity": 0 
      "margin-left": "-500px" 

     slideSidebarIn: => 
      @$el 
      .animate 
      "opacity":1 
      "margin-left":0 
      , 500, -> app.reqres.setHandler "sidebar:visible", -> true 

     # CUSTOM EVENTS 

     goHome: (e) => 
      e.preventDefault() 
      # @router.navigate "/", trigger: true 
      # we're going to avoid using navigate, 
      # too complex to refactor at this point 
      window.location = "/" 

     quickSearch: => 
      # not working yet. 
      value = @ui.searchInput.val() 
      SearchResult.set("value", value) 

     search: (e) => 
      e.preventDefault() 
      value = @ui.searchInput.val() 
      app.router.navigate "search/#{value}?type=text", trigger: true 

     onBeforeRender: => 
      unless app.request("sidebar:visible") is true 
      @reset() 

     onRender: => 

      # console.dir 'SidebarLayout: render' 
      setTimeout => 
      @bindUIElements() 
      @globalListeners() 
      , 50 
      @$el.removeClass("hide") 
      if app.request("sidebar:visible") is false 
      @slideSidebarIn() 

的問題是這一行:

searchResult.on "change:params", @setSidebarContent, @

我得到這個錯誤:

Uncaught TypeError: Cannot call method 'show' of undefined

我假設這事做與不圍成的區域,或不被穿過一個相關背景。

因此,噸研究和大約5個小時的廢話後,我對文檔閱讀彌補listenTo似乎這個代碼應該工作:

@listenTo searchResult, "change:params", @setSidebarContent()

實際上,我是唯一的辦法能夠得到它的工作,然而,要做到這一點確切的代碼:

searchResult.listenTo @, "change:params", @setSidebarContent()

所以,我現在的工作,並beautif ully。我只是困惑,爲什麼我必須通過這種方式來傳遞它,爲什麼第一種方式似乎沒有工作?

+0

我不清楚什麼是'searchResult'。你能粘貼你的完整視圖代碼嗎? – Ingro

+0

@Ingro感謝您的幫助。我只是使用完整的視圖代碼更新了上面的帖子。 'searchResult'是一個簡單的骨幹模型。 –

+1

我不確定是否屬於這種情況,但您可以嘗試使用下劃線的綁定方法來設置正確的上下文: 'searchResult.on「change:params」,_.bind(@setSidebarContent,@) – Ingro

回答

4

刪除()@setSidebarContent - 這也得到了我過去。

@listenTo searchResult, "change:params", @setSidebarContent