Reputation: 55273
I have an array of objects:
elements: [
{
id: '1',
dataX: 0,
dataY: 0
},
{
id: '2',
dataX: 189,
dataY: 189
}
]
They are used in the template like this:
// This is inside a repeat loop:
<a class="btn"
id="{{ id }}"
data-x="{{ dataX }}"
data-y="{{ dataY }}"
style="transform: translate({{ dataX }}px, {{ dataY}}px);">
</a>
Final output:
<a class="btn" id="2" data-x="189" data-y="189" style="transform: translate(189px, 189px); width: 144px; height: 36px;"></a>
I have code that changes the value of data-x
and data-y
and the transform
property, so the anchor tags can be dragged.
At the end of that function I have a few lines that change the array elements
itself:
const target = event.target
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy
// the code that makes the anchor tags move
// the code that modifies the array itself
this.elements.map(item => {
if (item.id === target.id) {
item.dataX = x
item.dataY = y
}
})
It works. However, the width and height properties are wiped out:
<a class="btn" id="2" data-x="189" data-y="189" style="transform: translate(189px, 189px);"></a>
Why is this and how to prevent it?
NOTE: this.elements
is a reactive element. Meaning that if it data changes the element is re-rendered in the template.
EDIT (full JavaScript code. I'm using Interact.js):
ready () {
interact('#plane > *')
.draggable({
snap: {
targets: [
interact.createSnapGrid({ x: this.baseUnit, y: this.baseUnit })
],
range: Infinity,
relativePoints: [ { x: 0, y: 0 } ]
},
restrict: {
restriction: 'parent',
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},
onmove: (event) => {
const target = event.target
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)'
// update the positon attributes
target.setAttribute('data-x', x)
target.setAttribute('data-y', y)
this.elements.map(item => {
if (item.id === target.id) {
console.log(item)
item.dataX = x
item.dataY = y
}
})
}
})
.resizable({
snap: {
targets: [
interact.createSnapGrid({ x: this.baseUnit, y: this.baseUnit })
],
range: Infinity,
relativePoints: [ { x: 0, y: 0 } ]
},
edges: { left: true, right: true, bottom: true, top: true },
onmove: (event) => {
const target = event.target
let x = (parseFloat(target.getAttribute('data-x')) || 0)
let y = (parseFloat(target.getAttribute('data-y')) || 0)
// update the element's style
target.style.width = event.rect.width + 'px'
target.style.height = event.rect.height + 'px'
// translate when resizing from top or left edges
x += event.deltaRect.left
y += event.deltaRect.top
target.setAttribute('data-width', event.rect.width)
target.setAttribute('data-height', event.rect.height)
target.textContent = Math.round(event.rect.width) + '×' + Math.round(event.rect.height)
}
})
},
Upvotes: 3
Views: 234
Reputation: 1194
Here is my wild guess at what is happening in the face of some missing pieces...
You probably have some kind of binding setup so that when the array changes (as mutated by the map
call) it re-renders the template; I'm assuming that.
The original template (pre map
call) contains width
and height
values in the style
attribute but is not clear where these come from. What is clear is that they are not included in your re-computation.
Therefore, my guess is they are being overridden by the map
call because it re-writes the entire style
attribute with ONLY the transform
.
Add the width
and height
values back onto the dynamically rendered value for the style
attribute and you'll be okay.
EDIT: With the full code posted basically everything I said is true except with the added flavor of competing onmove events. (I believe)
What I think is happening is your first onmove event is firing and setting the width
and height
and then the second one fires and overwrites the style
with transform
. Fixing this is a matter of changing up the logic a bit so your event handlers are not fighting each other.
Upvotes: 2