javascript - Ember 绑定(bind) Controller 计算属性未更新

标签 javascript jquery ruby-on-rails ember.js coffeescript

我看到了这种使用 ember.js 拖放 UI/UX 的方式 http://jsfiddle.net/ud3323/5uX9H/ 这就像一个购物车。

我使用的是最新版本的 ember.js“1.5.0”,为了提供更多背景信息,我使用 Rails 作为这个 ember 应用程序的后端。

这里的问题是,每当我拖动产品时,SimpbroAdmin.ProductDropTarget View 都不会更新。似乎绑定(bind)的 Controller 属性“SimpbroAdmin.ProductsController.currentDragItem”(计算属性)没有得到更新,这是导致问题的原因。

fiddle 和我的实现之间的主要区别是我使用数据存储而不是 fiddle 的硬编码 JSON 内容数组。

这些是文件:

应用程序.js.咖啡

window.SimpbroAdmin = Ember.Application.create()

products.handlebars

<ul>                                                                             
  {{#each}}                                                                      
    <li>                                                                         
      {{#view SimpbroAdmin.ProductView contentBinding="this"}}                   
        {{name}}                                                                 
        {{description}}                                                          
        <span style="color:red">                                                 
        {{isAdded}}                                                              
        </span>                                                                  
      {{/view}}                                                                  
    </li>                                                                        
  {{/each}}                                                                      
</ul>                                                                    

{{#view SimpbroAdmin.ProductDropTarget dragContextBinding="SimpbroAdmin.ProductsController.currentDragItem"}}
  Shopping Cart                                                                  
  <div style="height: 20px">{{view.helpText}}</div>                              
{{/view}}

{{#each SimpbroAdmin.CartController.cartItems}}                                  
  {{#view SimpbroAdmin.ProductView contentBinding="this"}}                       
    {{view.name}}                                                                
  {{/view}}<br />                                                                
{{/each}}

products_controller.js.coffee

SimpbroAdmin.ProductsController = Ember.ArrayController.extend(                  
  actions:                                                                       
    addProduct: (name, description) ->                                           
      store = @store                                                             
      product = store.createRecord "product",                                    
        name: name                                                               
        description: description                                                 
      product.save()                                                             

  currentDragItem: Ember.computed((key, value) ->                                
    @findProperty "isDragging", true                                             
  ).property("@each.isDragging").cacheable()                                     

  productsInCart: Ember.computed((key, value) ->                                 
    @filterProperty "isAdded", true                                              
  ).property("@each.isAdded").cacheable()                                        
)

product_view.js.coffee

SimpbroAdmin.DragNDrop = Ember.Namespace.create()                                
SimpbroAdmin.DragNDrop.cancel = (event) ->                                       
  event.preventDefault()                                                         
  false                                                                          

SimpbroAdmin.DragNDrop.Draggable = Ember.Mixin.create(                           
  attributeBindings: "draggable"                                                 
  draggable: "true"                                                              
  dragStart: (event) ->                                                          
    dataTransfer = event.originalEvent.dataTransfer                              
    dataTransfer.setData "Text", @get("elementId")                               
    return                                                                       
)                                                                                

SimpbroAdmin.DragNDrop.Droppable = Ember.Mixin.create(                           
  dragEnter: SimpbroAdmin.DragNDrop.cancel                                       
  dragOver: SimpbroAdmin.DragNDrop.cancel                                        
  drop: (event) ->                                                               
    event.preventDefault()                                                       
    false                                                                        
)                                                                                

SimpbroAdmin.ProductView = Ember.View.extend(SimpbroAdmin.DragNDrop.Draggable,   
  tagName: "span"                                                                
  # .setDragImage (in #dragStart) requires an HTML element as the first argument 
  # so you must tell Ember to create the view and it's element and then get the  
  # HTML representation of that element.                                         
  dragIconElement: Ember.View.create(                                            
    attributeBindings: ["src"]                                                   
    tagName: "img"                                                               
    src: "http://twitter.com/api/users/profile_image/twitter"                    
  ).createElement().get("element")                                               

  dragStart: (event) ->                                                          
    @_super event                                                                
    # Let the controller know this view is dragging                              
    @set "isDragging", true                                                      
    console.log(@.content)                                                       
    # Set the drag image and location relative to the mouse/touch event          
    dataTransfer = event.originalEvent.dataTransfer                              
    dataTransfer.setDragImage @get("dragIconElement"), 24, 24                    

  dragEnd: (event) ->                                                            
    # Let the controller know this view is done dragging                         
    @set "isDragging", false                                                     
)              

SimpbroAdmin.ProductDropTarget = Ember.View.extend(SimpbroAdmin.DragNDrop.Droppable,
  tagName: "div"                                                                 
  classNames: ["dropTarget"]                                                     
  classNameBindings: ["cartAction"]                                              
  helpText: null                                                                 
  # This will determine which class (if any) you should add to                   
  # the view when you are in the process of dragging an item.                    
  cartAction: Ember.computed((key, value) ->                                     
    if Ember.isEmpty(@get("dragContext"))                                        
      @set "helpText", "(Drop Zone)"                                             
      console.log('empty')                                                       
      return null                                                                
    unless @getPath("dragContext.isAdded")                                       
      @set "helpText", "(Drop to Add)"                                           
      console.log('add')                                                         
      "cart-add"                                                                 
    else if @getPath("dragContext.isAdded")                                      
      @set "helpText", "(Drop to Remove)"                                        
      console.log('remove')                                                      
      "cart-remove"                                                              
    else                                                                         
      @set "helpText", "(Drop Zone)"                                             
      null                                                                       
  ).property("dragContext").cacheable()                                          
  drop: (event) ->                                                               
    viewId = event.originalEvent.dataTransfer.getData("Text")                    
    view = Ember.View.views[viewId]                                              
    # Set view properties                                                        
    # Must be within `Ember.run.next` to always work                             
    Ember.run.next this, ->                                                      
      view.set "content.isAdded", not view.get("content.isAdded")                

    @_super event                                                                
)

cart_controller.js.coffee

SimpbroAdmin.CartController = Ember.ArrayController.extend(                      
  # Sort desc by name                                                            
  content: Ember.computed((key, value) ->                                        
    cartItems = @get("cartItems")                                                
    unless Ember.empty(cartItems)                                                
      cartItems.sort (a, b) ->                                                   
        if (a.get("name").toLowerCase()) < (b.get("name").toLowerCase())         
          -1                                                                     
        else                                                                     
          1                                                                      

  ).property("cartItems").cacheable()                                            
  cartItemsBinding: "SimpbroAdmin.ProductsController.productsInCart"             
)

产品.js

SimpbroAdmin.Product = DS.Model.extend({                                         
  name: DS.attr('string'),                                                       
  description: DS.attr('string'),                                                
  photo: DS.attr('string'),                                                      
  in_sale: DS.attr('boolean'),                                                   
  in_stock: DS.attr('boolean')                                                              
});

最佳答案

该代码看起来基于 Ember 1.0 之前的版本。

有很多事情需要改进,我建议您阅读 Ember 指南。

这里有一些提示:

cacheable() 不再需要计算属性

您应该使用 get/set 而不是 getPath/setPath

你应该避免使用全局变量并尝试使用 ember 的路由器。

http://emberjs.jsbin.com/vugesoso/4/edit

关于javascript - Ember 绑定(bind) Controller 计算属性未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24468935/

相关文章:

javascript - 如何自定义谷歌地图标记的颜色、形状和大小

javascript - Visual Studio 2015 导航 MVC

javascript - 小的 JavaScript 数组错误

jquery - 如何通过 jQuery 中的另一个附加元素访问附加元素

javascript - 更改 "inner content"的最佳方法

javascript - 如何防止触发表单提交操作?

ruby-on-rails - 如何将字形添加到 Rails link_to 帮助程序 - Bootstrap 3

ruby-on-rails - 在 cucumber .feature 文件中传递数组值

javascript - 如何使用 insertAfter 方法和 fadeIn 效果插入 html,以便 html 淡入

ruby-on-rails - gmaps4Rails - json 被返回为空