Lorine
Lorine

Reputation: 129

How to call two methods @click on a button but execute one method after the other

I want to be able to call two different methods on a single button click, but I want the methods to run one after the other. Indeed, I have my first method which creates multiple instances of a component and the second one is going to move these instances on my screen. I didn't find a solution to create the instances and move them in a single method so I want to do it that way.

I tried by calling the two methods like this : @click="method1(); method2();" but the two methods are executed at the same time.

So these are the methods I am dealing with:

 modifyLayer(){
    console.log(this.selectedLayer)
    this.modifyingLayer = this.selectedLayer
    var donnéesCouche = this.couche.find(element => element.id == this.modifyingLayer)
    this.emplacement=[]
    this.emplacement = donnéesCouche.listePositions
    
  },

  moveLayer(){
    for (var element in this.emplacement){
      var toMove=document.getElementById(this.emplacement[element].id)
      for (var element in this.emplacement){
        toMove.top=this.emplacement[element].x
        toMove.left=this.emplacement[element].y
      }
    }
  },

this.emplacement corresponds to a list of objects like this: {id: ....; x: "...px"; y: "...px"} and in my HTML, I create instances of my component with a v-for each element in this.emplacement

Could you help me find a solution, either to call the two methods one after the other or to be able to create instances and move them within the same method?

Thank you for your help!

Upvotes: 1

Views: 666

Answers (3)

Michal Levý
Michal Levý

Reputation: 37763

I want to be able to call two different methods on a single button click, but I want the methods to run one after the other

Well, the handler as @click="method1(); method2();" indeed runs the methods one after another (1st returns before 2nd starts)

I have my first method which creates multiple instances of a component and the second one is going to move these instances on my screen.

This is little bit unfortunate wording. Your fist method does not create any components directly. It just assigns some data into emplacement data member and this emplacement property is used in the template to render some components...

So your problem is not that those methods are not executed one after another (they are), problem is that Vue is using async update queue to update the DOM

So when the modifyLayer() finishes executing, DOM elements for the emplacement does not exist yet. The solution is to postpone the moveLayer() execution using the $nextTick() method

So instead of @click="method1(); method2();" handler, create a method:

@click="handleClick"

methods: {
  handleClick() {
   this.modifyLayer()
   this.$nextTick(this.moveLayer)
  }
}

Note: even tho I do not understand why you rendering 1st and moving later instead of rendering everything in one go at correct possition. Something like document.getElementById is not needed in Vue in most cases....

Upvotes: 1

Justine Foulquier
Justine Foulquier

Reputation: 13

Can't you do something like that : @click="methods()"

And then declare :

async methods{
await this.methods1()
this.methods2()
}

Upvotes: 0

Yash Maheshwari
Yash Maheshwari

Reputation: 2412

You can simply call the second method from the first one, and call the first method on button click. @click="modifyLayer()"

 modifyLayer(){
    console.log(this.selectedLayer)
    this.modifyingLayer = this.selectedLayer
    var donnéesCouche = this.couche.find(element => element.id == this.modifyingLayer)
    this.emplacement=[]
    this.emplacement = donnéesCouche.listePositions
    this.moveLayer();   // calling the second method from the first
  },

  moveLayer(){
    for (var element in this.emplacement){
      var toMove=document.getElementById(this.emplacement[element].id)
      for (var element in this.emplacement){
        toMove.top=this.emplacement[element].x
        toMove.left=this.emplacement[element].y
      }
    }

Upvotes: 0

Related Questions