nunop
nunop

Reputation: 2207

Draggable with Vue.js, not being able to return to original position

I'm attempting to have an element's draggable functionality depend on a click event. I'm using jquery-ui's draggable method (within a vue.js instance).

In my Vue instance I have these two data properties: isVisible and a isDraggable. They assume a truthy or falsy value each time the user clicks a button. On my methods object I have the following:

methods: {
    toggleBox: function() {
        this.IsVisible = !this.IsVisible;
        this.isDraggable = !this.isDraggable;
    }
}

I'm using the destroy method in order to have the targeted element return to its original position (documentation here). However, I am not getting the intended result, as can be seen in the jsfiddle below. The following is one of many (unsuccessful) attemtps to tackle this issue:

ready: function() {
    this.$nextTick(function() {
        if (this.isDraggable == true) {
            $('.box').draggable({
                containment: "window"
            })
        } else if (this.isDraggable == false) {
            $('.box').draggable(
                "destroy"
            )
        }
    })
}

Jsfiddle here. I wonder what I'm doing wrong here? Any hint appreciated.

Upvotes: 1

Views: 1925

Answers (2)

nunop
nunop

Reputation: 2207

Adding to @Yass's answer above, if instead of hard-coding the offset's top position of the element .box , you wanted to calculate it, here's one way to do it (which is useful in those cases where the browser's window changes size for instance):

toggleBox: function() {

    this.IsVisible = !this.IsVisible;
    this.isDraggable = !this.isDraggable;


    var body = document.body.getBoundingClientRect();
    var element = document.querySelector('.box').getBoundingClientRect();

    var topPos = body.height - element.height;

    if (this.isDraggable) {
       $('.box').draggable({
          containment: "window"
       })
    }
    else if (!this.isDraggable) {
       $('.box').offset({ 
           top: this.topPos, 
           left: 8});
    }
}

Upvotes: 0

Yass
Yass

Reputation: 2668

The ready function only gets called once, during initialization of the vm element. Whenever you click on the "toggle" button, there's nothing that tells the nextTick method to execute. I'm not at all familiar with the vue api, so there probably will be a way to do what you want using the nextTick method.

Given my lack of knowledge regarding the api, I came up with a solution that seemed the most straightforward for your requirements i.e. updating the toggleBox method to check the isDraggable property and resetting the position of the box according to its value.

If you introduce other elements, you'd need to implement a solution that takes into account all of the default positions and re-apply them when you click the "toggle" button.

toggleBox: function() {
  this.IsVisible = !this.IsVisible;
  this.isDraggable = !this.isDraggable;
  if (this.isDraggable) {
    $('.box').draggable({
      containment: "window"
    })
  } else if (!this.isDraggable) {
    $('.box').offset({ top: 8, left: 8});
  }
}

Fiddle example

Upvotes: 1

Related Questions