The Problem
So I am trying to detect changes to an array passed in through an input in my component. Regardless of how many times I try to separate the two arrays, they always contain the same values.
What I've Tried
I've tried slice and Array.from and both produce the same result, two arrays with identical information regardless of the fact that one is not updated at all and is a separate array from the original.
The Caveat
The interesting part of this, is if I check that one array is an instance of the other with firstArray == secondArray I get false, whereas this returns true when not using slice or Array.from
The Component
import { Component, Input, DoCheck } from '@angular/core';
class Requirement {
title: string;
passes: boolean;
}
@Component({
selector: 'password-requirement-indicator',
templateUrl: './password-requirement-indicator.component.html',
styleUrls: [ './password-requirement-indicator.component.scss' ]
})
export class PasswordRequirementIndicator implements DoCheck {
// Current requirements
currentRequirements: Requirement[];
// Previous requirements
previousRequirements: Requirement[];
ngDoCheck(){
console.log(this.previousRequirements, this.currentRequirements);
if ( !this.previousRequirements ){
this.previousRequirements = Array.from(this.currentRequirements);
}
}
@Input() set requirements (requirements: Requirement[] ){
this.currentRequirements = Array.from(requirements);
}
}
The Parent (Implementing) Component
import { Component, OnInit, ViewChild } from '@angular/core';
@Component({
templateUrl: './index.component.html',
styleUrls: ['./index.component.css']
})
export class IndexComponent {
passes: boolean = false;
requirements: any[] = [
{
title: 'Has at least one special character',
passes: false
},
{
title: 'Has no spaces',
passes: false
},
{
title: 'Has at least 1 letter',
passes: false
},
{
title: 'Has at least 1 number',
passes: false
},
{
title: 'Has 8-10 total characters',
passes: false
},
{
title: 'Has no more than 3 of the same character in a row',
passes: false
}
]
// Updates the requirements as needed
updateRequirements: Function = (password: string) => {
// Update the special character requirement
this.requirements[0].passes = this.hasSpecialCharacter(password);
// Update the no spaces requirement
this.requirements[1].passes = this.hasNoSpaces(password);
// Update the one letter requirement
this.requirements[2].passes = this.hasOneLetter(password);
// Update the one number requirement
this.requirements[3].passes = this.hasOneNumber(password);
// Update the 8-10 character requirement
this.requirements[4].passes = this.isRightLength(password);
// Update the onenumber requirement
this.requirements[5].passes = this.hasNoRepeatCharacters(password);
// Check if all checks passed
let passes: boolean = true;
for ( var i =0, j=this.requirements.length; i<j; i++ ){
if ( !this.requirements[i].passes ) {
passes = false;
i=j;
}
}
this.passes = passes;
}
hasSpecialCharacter: Function = (password: string) => {
// Check for a match and return whether we found one or not
return password.match(/[\\!\@\#\$\%\^\&\*\(\)\{\}\"\<\>\?\/\:\;\'\-\=\|\[\]\,\.]/g) ? true : false;
}
hasNoSpaces: Function = (password: string) => {
// Check the password and return if we found spaces or not
return password.match(/\s/g) ? false : true;
}
hasOneLetter: Function = (password: string) => {
// Check the password and return if we found at least one letter
return password.match(/[a-zA-Z]/g) ? true : false;
}
hasOneNumber: Function = (password: string) => {
// Check the password and return if we found at least one number
return password.match(/[0-9]/g) ? true : false;
}
isRightLength: Function = (password: string) => {
// Check the password and return if it is between 8 and 10 characters
return typeof password === "string" && password.length >= 8 && password.length <= 10;
}
hasNoRepeatCharacters: Function = (password: string) => {
// Check the password and return if any characters are repeated more than three times
return password.match(/(.).*?\1\1\1/g) ? false : true;
}
}
Optional Reading
To get a little more in-depth the parent component is creating an initial array and passing this to the child component via an input: <component [requirements]="requirements"></component>.
It then updates this initial array without ever destroying it, meaning that a reference is created when passing this array into the component. Which is fine, this is how I need it to work for my uses.
However when I am trying to create a new array to store the old state for comparison to a new state using ngDoCheck, no matter what I do the previous requirements and current requirements array have the same values, even though they are created at different times and are verifiable as different arrays that are not instances of one another.
This is witchcraft.
The Solution
How can I create an array that maintains the previous values of the array before it was updated so that I can check if the values of any of the objects in the array have changed?
Writing the code to do this is not a problem for me, in fact I had it written out previously, but I need to be able to store the previous state in an array whose values do not update with the original input.