Eisa Adil
Eisa Adil

Reputation: 1733

Access outer variable inside Angular Promise then() function

Good evening everyone. I'd like to know how I can access an outer variable inside the then() of Promise in Angular 2/4's typescript. I am trying to accomplish dynamic form validation to check username availability through a Rest API.

Here userService.isUsernameAvailable(userName) returns a promise which works perfectly. The only thing I want an answer to is, how can I change those i values on then() and catch().

static usernameAvailabilityValidator(userService: UserService) {
      let i = 1; //outer variable
      userService.isUsernameAvailable(userName).then((res) => {
        i = 2;
      }).catch((res) => {
        i = 3;
      });
      console.log("i is "+ i); // should output 2 or 3
  }

IRRELEVANT BELOW

Below is not relevant to this question: I'm adding code below to provide context to what I'm try to achieve. You don't have to read it and it doesn't add to my question.

My objective is to return a function that returns null or a JSON object for the validator, because that's how validators work in Angular 2.

static usernameAvailabilityValidator(userService: UserService) {
    return (control: FormControl) : any =>{
      let userName: string = control.value;
      console.log("current username"+userName);
      let i = 1;
      let response:{} = null; //here response is similar to i
      userService.isUsernameAvailable(userName).then((res) => {
        i++;
        if (res.status == 1) {
          response = null;
        }
        else {
          response = {'usernameInUse': 1};
        }

      }).catch((res) => {
        response = null;
      });
      console.log("i"+i);
      return response; // response is returned to the outside function
    }
  }

Thank you everyone in advance.

Upvotes: 1

Views: 914

Answers (2)

Rahul Singh
Rahul Singh

Reputation: 19622

You need to Implement Async Validators for the same

eg -

validate(c:AbstractControl) {
    return new Promise(resolve =>
      this.accountService.getUserNames(c.value).subscribe(res => {
        if (res == true) {
            resolve(null);
        }
        else {
            resolve({validateEmailTaken: {valid: false}});
        }
    }));
  }

You can Find more on Validators on this Reactive & TemplateDriven

Upvotes: 0

Stephan
Stephan

Reputation: 2115

isUsernameAvailable returns a Promise because it can't return a value immediately after being called (because it for example waits for a network request). Therefore your console.log("i"+i); and return response; gets called way ahead of your then callback and before the variables got modified. For that reason your usernameAvailabilityValidator can't immediately return a value, you could instead return the Promise or use TypeScript's async/await feature (https://basarat.gitbooks.io/typescript/content/docs/async-await.html).

Upvotes: 0

Related Questions