MisterniceGuy
MisterniceGuy

Reputation: 1786

Problem with TS2339 Property xxx does not exist on type Observable

It seems part of my problem is the way stuff is loaded. As i call the createForm function in my constructor it trys to access the this.paswdProfile.numbers and other variables which are part of the ngOnInit and are not avail yet so it fails. if i move the form to the ngOnInit it complains about no FormGroup etc. So how can i ensure that the form fields are created after the passwdProfile has data ?

import {IBucket} from '../../../../models/bucket';
import { Component, OnInit, Inject, Output, EventEmitter } from '@angular/core';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { AdminService  } from '../../../../services/admin.service';
import { MAT_DIALOG_DATA,  MatDialog, MatDialogRef  } from '@angular/material';
import { Observable } from 'rxjs';
import { CouchbaseLookupService} from '../../../../services/couchbase-lookup.service';
import { takeWhile } from 'rxjs/operators';
import { ToasterService} from 'angular2-toaster';
import { CustomValidators } from './custom-validators';
import { IPasswordProfile } from '../../../../models/admin'



@Component({
  selector: 'app-password',
  templateUrl: './password.component.html',
  styleUrls: ['./password.component.scss']
})
export class PasswordComponent implements OnInit {
    public passwordForm: FormGroup;
    alive = true;

    paswdProfile$: Observable<IPasswordProfile>
    paswdProfile: IPasswordProfile

    constructor(@Inject(MAT_DIALOG_DATA) public data: any, private dialogRef: MatDialogRef<PasswordComponent>,
    private adminService: AdminService, private route: ActivatedRoute, private cbLookupService: CouchbaseLookupService,
    private router: Router, private dialog: MatDialog, private toasterService: ToasterService, private fb: FormBuilder) {
this.passwordForm = this.createPasswordForm()
     }



ngOnInit() {
    this.paswdProfile$ = this.adminService.getPasswordProfile("8084ea42-633e-4c28-bc7a-372aa58a4d1c")
    this.paswdProfile$.subscribe(res => {this.paswdProfile = res[0]})
    console.log(this.paswdProfile)
}

createPasswordForm(): FormGroup {
    return this.fb.group(
      {
        oldPassword : [ null, Validators.compose([Validators.required])],
        newPassword: [
          null,
          Validators.compose([
            Validators.required,
            // check whether the entered password has a number
            CustomValidators.patternValidator(/\d/g, this.paswdProfile.numbers , {
              hasNumber: true
            }),
            // check whether the entered password has upper case letter
            CustomValidators.patternValidator(/[A-Z]/g, this.paswdProfile.upperCase, {
              hasCapitalCase: true
            }),
            // check whether the entered password has a lower case letter
            CustomValidators.patternValidator(/[a-z]/g, this.paswdProfile.lowerCase,  {
              hasSmallCase: true
            }),
            // check whether the entered password has a special character
            CustomValidators.patternValidator(
              /[ !@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/g, this.paswdProfile.specialChar ,
              {
                hasSpecialCharacters: true
              }
            ),
            Validators.minLength(this.paswdProfile.minChar)
          ])
        ],
        confirmPassword: [null, Validators.compose([Validators.required])]
      },
      {
        // check whether our password and confirm password match
        validator: CustomValidators.passwordMatchValidator
      }
    );
  }


}

Upvotes: 1

Views: 2070

Answers (2)

ForrestLyman
ForrestLyman

Reputation: 1652

In order to access an observable value you need to use the https://angular.io/api/common/AsyncPipe if you are using the value in the template.

If you want to access it in the .ts file you need to subscribe to it and wait for it to resolve like:

this.paswdProfile$.subscribe(profile => {
    const numbers = profile.numbers;
});

Upvotes: 0

You don't get a reference to the object. You get a reference to the Observable. You need to subscribe to the Observable and store the result. This is done asynchronously.

this.adminService.getPasswordProfile("8084ea42-633e-4c28-bc7a-372aa58a4d1c")
    .subscribe(profile => this.paswdProfile$ = profile);

Upvotes: 2

Related Questions