Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
178 views
in Technique[技术] by (71.8m points)

typescript - Var assignment before executing function - Angular

I'm trying to make a popup menu in Angular. I've got the parent (misvecinos) and child components (vecino-menu). I've designed it so whenever I click in a div (with info about an object Vecino), all data is assigned to vecinoMenu (which is a base Vecino when the component is initialized). Once that vecinoMenu has new data from the Vecino clicked, it is sent to the child component via @Input, where there is a form where I want to get the vecinoMenu data and make one of the inputs already checked (eg. if the Vecino clicked had id=4, when it's sent to vecino-menu, the radio input with value =4 should be checked).

This is the code that implements what I've described:

Misvecinos.component.ts:

vecinoMenu : Vecino = {
nombre: "",
vecino_id: 0,
usuario_id: 0
};

@ViewChild(VecinoMenuComponent) menu : VecinoMenuComponent;


abreMenu(event, vecino : Vecino){
let coord = this.obtenPosicion(event);

if(vecino == null){
  this.vecinoMenu = {
    nombre: "",
    vecino_id: 0,
    usuario_id: 0
  }
  this.menu.abreMenu(event, coord);

}else{
  if(this.vecinoMenu != null && this.vecinoMenu.vecino_id == vecino.vecino_id && this.menu.visibility == "visible"){
    this.menu.cierraMenu();
  }else{
    //this.vecinoMenu = vecino;

    // setTimeout(() => {
    //   this.menu.abreMenu(event, coord);
    // }, 3000);

    this.iniciaDatos(vecino).then(() => {
      console.log("dsps de asignar vecino");
      console.log(this.vecinoMenu);

      this.menu.abreMenu(event, coord);
    });
  }
 }
}

iniciaDatos(vecino : Vecino) : Promise<Vecino> {
let promise = new Promise<Vecino>((resolve, reject) => {
  this.vecinoMenu = vecino;
  if(this.vecinoMenu == vecino){
    resolve(this.vecinoMenu);
  }else{
    reject();
  }

});
return promise;
}

( Ignore obtenPosicion() and cierraMenu() )

Here there are a couple things to grasp:

  • If the vecino sent when calling the function is null that means that I'm going to create one, but in order to avoid nullpointers, I set vecinoMenu to a new one (in case that the user already modified vecinoMenu by clicking in another Vecino before trying to create one). After the vecino is set, I open the menu (I'm guessing this part should have the same problem but I'm currently trying to debug it using the next section)
  • Inside the first else, there is a few lines just to close the menu when clicked twice in the same Vecino, and if that's not the case, I set vecinoMenu with the value from Vecino and open the menu afterwards. If I do it like: this.vecinoMenu = vecino;this.menu.abreMenu(event, coord); when the menu is opened (next file), the value that the child component gets from the parent is the base one. Then I tried using setTimeout() to check if the problem was a matter of time and indeed it is. If I do it like the commented part, it works, but setTimeout() is a horrible solution, so I tried with promises. I made a function called iniciaDatos() which basically does this.vecinoMenu = vecino as a promise (or at least that's the intention, I'm still learning the whole Promise thing) in order to use .then() afterwards, but this way I'm getting the same result as if I did nothing and the value that the child component gets it's the base one.

Vecino-menu.component.ts:

  @Input("vecinoMenu") vecino : Vecino;

constructor(private _builder : FormBuilder) {
// if(this.vecino.vecino_id == 0){
  this.vecinoForm = this._builder.group({
    id: [1, Validators.required]
  });
// }else{
//   this.vecinoForm = this._builder.group({
//     id: [2, Validators.required]
//   });
// }

}

abreMenu(e : MouseEvent, coord : Array<number>){
this.visibility = "visible";
console.log(this.vecino);

this.x = coord[0]+"%";
this.y = coord[1]+"%";
e.stopPropagation();
}

Two points here:

  • The section commented in the constructor is a test for selecting the default check input, if I uncomment that, I will get the following error: ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'vecino_id' of undefined, but I'm guessing that is just because it's getting the wrong value from the input
  • Check the console.log in abreMenu where gets the value of vecino (vecinoMenu) after the menu is open)

I placed some console.logs and so far, when the vecinoMenu is setted in the parent (either with iniciaDatos() or manually like the comment) it has the correct value, but when the menu opens and checks the value sent through the @Input, it has the base value (unless I use setTimeout in which case works).

Since the problem apparently it's caused by the abreMenu() function executing before the new vecinoMenu is setted, is there any way where I can execute the function after vecinoMenu has setted correctly?

question from:https://stackoverflow.com/questions/65871619/var-assignment-before-executing-function-angular

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...