Kerim092
Kerim092

Reputation: 1497

Angular - array.push() refreshes page

This function should push certain numbers to an array that I'm gonna display on view.

@Component({
  selector: 'app-task2',
  templateUrl: './task2.component.html',
  styleUrls: ['./task2.component.css']
})
export class Task2Component implements OnInit {

  array: [number];
  input;

  constructor() {}
  ngOnInit() {}
}

Everything works just fine, but as soon as I include "this.array.push(i)" it keeps refreshing my page on submit (call of this function on submit). I delete it, everything works just fine, it iterates the right way, finds numbers and everything that it should do. Even if i make array inside of function and push to it, it works fine, but when i use it as an class "atribute" and use "this" as reference it doesnt work (starts refreshing).

onSubmit() {

  for(var i=2; i<=this.input; i++) {
    if(this.input % i == 0) {
      this.input /= i;
      this.array.push(i);
      return this.onSubmit(); //does same even without this
    }
  }
  this.input = "";
}

Upvotes: 1

Views: 2017

Answers (2)

Manoj Reddy Mettu
Manoj Reddy Mettu

Reputation: 149

I know it looks weird, but the trick is very simple.

Just initialize the array and the reloading problem goes away.

array: number[] = [];

I just faced this problem with my code and this trick solved the issue.

Upvotes: 1

ProfDFrancis
ProfDFrancis

Reputation: 9421

Create the new array in a separate variable, and then write it into this.array in a single step

Only the javascript is currently displayed in your question, so I am taking a guess at what the template contains. I am assuming your code is designed to factorise a number?

I suspect the cause for the multiple refreshes is that your template is programmed to display this.array whenever it updates. If you are typing in a number with many factors, you will see many refreshes.

Am I right in saying that when you put in a prime number, you get just a single refresh, i.e. correct behaviour? If so then you could fix it by doing all the pushing on a separate variable, and then copying that separate variable into this.array. For example:

onSubmit() {
  let nextArray = [];
  for(var i=2; i<=this.input; i++) {
    if(this.input % i == 0) {
      this.input /= i;
      nextArray.push(i);
      // Remove this line: return this.onSubmit(); 
    }
  }
  this.array = nextArray;
  this.input = "";
}

You can save on iterations by only going up to the square root of this.input

When factorising N, once you have looked as far as (and including) sqrt(N), there is no need to look at the other numbers between sqrt(N) and N: they can't be factors. So you can modify the first line of your loop. Squaring is quicker than square-rooting, so you can test for i*i<=this.input for speed instead of i<=Math.sqrt(this.input). You just have to remember to push the final value of this.input if it is not 1, as this will be the largest factor.

onSubmit() {
  let nextArray = [];
  for(var i=2; i*i<=this.input; i++) {
    if(this.input % i == 0) {
      this.input /= i;
      nextArray.push(i);
    }
  }
  if (this.input !==1){
    nextArray.push(this.input);
  }
  this.array = nextArray;
  this.input = "";
}

Look out for repeated factors

I suspect your current code would not correctly factorise a number which had the same factor present multiple times. For example, it tests only once for whether a number is divisible by 5. So if this.input was 250, which is 2*5*5*5, it would output 2, 5, 25.

To counteract this, you could do the incrementing of i to happen only if you have not found a factor. So that when you find a factor, the next cycle of the for will test the same factor, and subsequent cycles will keep testing the same factor, until it is no longer a factor.

onSubmit() {
  let nextArray = [];
  for(var i=2; i<=this.input;) {
    if(this.input % i == 0) {
      this.input /= i;
      nextArray.push(i);
    } else {
        i++;
    }
  }
  this.array = nextArray;
  this.input = "";
}

Upvotes: 0

Related Questions