-1

I have created a simple form and I am validating. The validation properly works but I m trying to call a method when the validation is done, but I get the following error:

ERROR TypeError: this.nextForm is not a function

My typescript code is the following:

onNavigate(direction) {
    // Fetch all the forms we want to apply custom Bootstrap validation styles to
    var forms = document.getElementsByClassName("needs-validation");
    // Loop over them and prevent submission
    var validation = Array.prototype.filter.call(forms, function(form) {
      form.addEventListener(
        "submit",
        function(event) {
          //Forward
          if (direction == "forward") {
            //Not correct
            if (form.checkValidity() === false) {
              event.preventDefault();
              event.stopPropagation();
              form.classList.add("was-validated");
            }
            //Corect
            else {
              form.classList.add("was-validated");
              this.nextForm();
            }
          }
        },
        false
      );
    });
  }

  nextForm() {
    this.router.navigate(["/id-application/welcome"]);
  }
bellotas
  • 1,663
  • 3
  • 20
  • 44
  • 1
    learn about "this" in javascript – enno.void Dec 13 '18 at 12:35
  • 1
    Using `function(form)`, your `this` refers to the `function(form)`'s this, which is not what you want. Either reference it before the function declaration, either use a lambda expression so that the component / parent `this` is kept inside the function declaration. Check "this" for reference: https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work – briosheje Dec 13 '18 at 12:36
  • You should use angular forms and rendering to solve this. Directly accessing the DOM makes little sense in your case. – kvetis Dec 13 '18 at 12:46

1 Answers1

4

Use the arrow functions instead of functions.

  var validation = Array.prototype.filter.call(forms,(form)=> { // use arrow function
      form.addEventListener(
        "submit",
        (event) => { // use arrow function
          //Forward
          if (direction == "forward") {
            //Not correct
            if (form.checkValidity() === false) {
              event.preventDefault();
              event.stopPropagation();
              form.classList.add("was-validated");
            }
            //Corect
            else {
              form.classList.add("was-validated");
              this.nextForm();
            }
          }
        },
        false
      );
    });
  }
Sachila Ranawaka
  • 28,742
  • 4
  • 48
  • 69
  • Property 'filter' does not exist on type 'HTMLCollectionOf' – bellotas Dec 13 '18 at 12:36
  • @Mario keep `Array.prototype.filter.call` as you have in your code, since HTML collections does not support `filter` natively. Using call, however, you can use filter on that. – briosheje Dec 13 '18 at 12:39
  • @briosheje Interesting. Didn't know that. Thanks for bringing that up – Sachila Ranawaka Dec 13 '18 at 12:42
  • 1
    @SachilaRanawaka further infos here: https://stackoverflow.com/questions/3871547/js-iterating-over-result-of-getelementsbyclassname-using-array-foreach . As for filter, it's the same for every other array prototype. Using call you can, however, work around the issue, since you are referencing an Iterable as the first argument, so it accepts it. – briosheje Dec 13 '18 at 12:44
  • This works. Thanks! I will set it up as correct as soon as i can – bellotas Dec 13 '18 at 12:46
  • @Mario you should still take a look at any "this" topic you find, otherwise you may fall to the same issue very soon. Not my business, of course, just for completeness. If you're using a framework like angular, being aware of what `this` is in every context is **mandatory**. – briosheje Dec 13 '18 at 12:47