Вычисляемое свойство привязанного контроллера Ember не обновляется

#javascript #jquery #ruby-on-rails #ember.js #coffeescript

#javascript #jquery #ruby-on-rails #ember.js #coffeescript

Вопрос:

Я видел этот способ выполнения перетаскивания пользовательского интерфейса / UX с помощью ember.js http://jsfiddle.net/ud3323/5uX9H / Это похоже на корзину для покупок.

Я использую последнюю версию ember.js «1.5.0» и чтобы дать больше информации, я использую Rails в качестве серверной части для этого приложения ember.

Проблема здесь в том, что всякий раз, когда я перетаскиваю продукт, SimpbroAdmin.Представление ProductDropTarget не обновляется. И похоже, что свойство привязанного контроллера «SimpbroAdmin.ProductsController.currentDragItem» (вычисляемое свойство) не обновляется, что вызывает проблему.

Основное различие между скрипкой и моей реализацией заключается в том, что я использую хранилище данных, а не жестко закодированный массив содержимого скрипки в формате JSON.

Это файлы:

application.js.coffee

 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"             
)
  

product.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')                                                              
});
  

Комментарии:

1. Я предполагаю, что вы объединяете свойства представления, контроллера и модели. Попробуйте изменить @set "isDragging", true , чтобы @set "controller.isDragging", true настроить это на скрипке или jsbin, чтобы мы могли взломать его для вас. 🙂

2. Кроме того, Ember (и действительно все неминифицированные JS) до смешного легко отлаживается в любом из браузеров big-3. Установите точку останова внутри вычисляемого свойства, а затем следуйте по пути вниз по стеку.

Ответ №1:

Этот код выглядит основанным на чем-то до Ember 1.0.

Есть много вещей, над которыми нужно поработать, я бы рекомендовал ознакомиться с руководствами Ember.

Вот несколько советов:

cacheable() больше не требуется для ваших вычисляемых свойств

Вы должны использовать get / set , а не getPath / setPath .

Вам следует избегать использования глобальных переменных и попробовать маршрутизатор ember.

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