#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.