Home > Mobile >  Angular - Cannot read properties of undefined when subscribe to function
Angular - Cannot read properties of undefined when subscribe to function

Time:12-25

on my angular app i have a error on browser debug:

ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of undefined (reading 'fields')

Why I cannot access to fields property in this line?

this.pictureUrl = this.currentUser.version.fields.field[0].fieldValue.path;

this is my user model

export interface EzUser {
  mediaType: string;
  href: string;
  id: number;
  remoteID: string;
  contentType: ContentType;
  name: string;
  versions: ContentType;
  section: ContentType;
  mainLocation: ContentType;
  locations: ContentType;
  groups: ContentType;
  owner: ContentType;
  publishDate: Date;
  lastModificationDate: Date;
  mainLanguageCode: string;
  alwaysAvailable: boolean;
  version: Version;
  login: string;
  email: string;
  enabled: boolean;
  userGroups: ContentType;
  roles: ContentType;
}

export interface ContentType {
  mediaType: string;
  href: string;
}

export interface Version {
  mediaType: string;
  href: string;
  versionInfo: VersionInfo;
  fields: Fields;
  relations: Relations;
  thumbnail: Thumbnail;
}

export interface Fields {
  field: Field[];
}

export interface Field {
  id: number;
  fieldDefinitionIdentifier: string;
  languageCode: string;
  fieldTypeIdentifier: string;
  fieldValue: FieldValueClass;
}

export interface FieldValueClass {
  hasStoredLogin?: boolean;
  contentID?: number;
  login?: string;
  email?: string;
  passwordUpdatedAt?: number;
  enabled?: boolean;
  maxLogin?: number;
  plainPassword?: null;
  id?: string;
  path?: string;
  alternativeText?: string;
  fileName?: string;
  fileSize?: number;
  imageID?: string;
  uri?: string;
  inputURI?: null;
  width?: string;
  height?: string;
  additionalData?: any[];
  variations?: Variations;
}

export interface Variations {
  ezplatformAdminUIProfilePictureUserMenu: string;
  large: string;
  medium: string;
  reference: string;
  small: string;
  tiny: Href;
}

export interface Href {
  href: string;
}

export interface Relations {
  mediaType: string;
  href: string;
  relation: any[];
}

export interface Thumbnail {
  mediaType: string;
  resource: string;
  width: null;
  height: null;
  mimeType: string;
}

export interface VersionInfo {
  id: number;
  versionNo: number;
  status: string;
  modificationDate: Date;
  creator: ContentType;
  creationDate: Date;
  initialLanguageCode: string;
  languageCodes: string;
  versionTranslationInfo: VersionTranslationInfo;
  names: Names;
  content: ContentType;
}

export interface Names {
  value: Value[];
}

export interface Value {
  languageCode: string;
  text: string;
}

export interface VersionTranslationInfo {
  mediaType: string;
  language: Language[];
}

export interface Language {
  languageCode: string;
}

this is my data

{
    "_media-type": "application/vnd.ez.api.User json",
    "_href": "/api/ezp/v2/user/users/14",
    "_id": 14,
    "_remoteId": "1bb4fe25487f05527efa8bfd394cecc7",
    "ContentType": {
        "_media-type": "application/vnd.ez.api.ContentType json",
        "_href": "/api/ezp/v2/content/types/4"
    },
    "name": "Administrator User",
    "Versions": {
        "_media-type": "application/vnd.ez.api.VersionList json",
        "_href": "/api/ezp/v2/content/objects/14/versions"
    },
    "Section": {
        "_media-type": "application/vnd.ez.api.Section json",
        "_href": "/api/ezp/v2/content/sections/2"
    },
    "MainLocation": {
        "_media-type": "application/vnd.ez.api.Location json",
        "_href": "/api/ezp/v2/content/locations/1/5/13/15"
    },
    "Locations": {
        "_media-type": "application/vnd.ez.api.LocationList json",
        "_href": "/api/ezp/v2/content/objects/14/locations"
    },
    "Groups": {
        "_media-type": "application/vnd.ez.api.UserGroupRefList json",
        "_href": "/api/ezp/v2/user/users/14/groups"
    },
    "Owner": {
        "_media-type": "application/vnd.ez.api.User json",
        "_href": "/api/ezp/v2/user/users/14"
    },
    "publishDate": "2002-10-06T16:13:50 00:00",
    "lastModificationDate": "2021-12-21T17:23:49 00:00",
    "mainLanguageCode": "eng-GB",
    "alwaysAvailable": true,
    "Version": {
        "_media-type": "application/vnd.ez.api.Version json",
        "_href": "/api/ezp/v2/content/objects/14/versions/5",
        "VersionInfo": {
            "id": 517,
            "versionNo": 5,
            "status": "PUBLISHED",
            "modificationDate": "2021-12-21T17:23:49 00:00",
            "Creator": {
                "_media-type": "application/vnd.ez.api.User json",
                "_href": "/api/ezp/v2/user/users/14"
            },
            "creationDate": "2021-12-21T17:23:48 00:00",
            "initialLanguageCode": "eng-GB",
            "languageCodes": "eng-GB",
            "VersionTranslationInfo": {
                "_media-type": "application/vnd.ez.api.VersionTranslationInfo json",
                "Language": [{
                    "languageCode": "eng-GB"
                }]
            },
            "names": {
                "value": [{
                    "_languageCode": "eng-GB",
                    "#text": "Administrator User"
                }]
            },
            "Content": {
                "_media-type": "application/vnd.ez.api.ContentInfo json",
                "_href": "/api/ezp/v2/content/objects/14"
            }
        },
        "Fields": {
            "field": [{
                "id": 28,
                "fieldDefinitionIdentifier": "first_name",
                "languageCode": "eng-GB",
                "fieldTypeIdentifier": "ezstring",
                "fieldValue": "Administrator"
            }, {
                "id": 29,
                "fieldDefinitionIdentifier": "last_name",
                "languageCode": "eng-GB",
                "fieldTypeIdentifier": "ezstring",
                "fieldValue": "User"
            }, {
                "id": 30,
                "fieldDefinitionIdentifier": "user_account",
                "languageCode": "eng-GB",
                "fieldTypeIdentifier": "ezuser",
                "fieldValue": {
                    "hasStoredLogin": true,
                    "contentId": 14,
                    "login": "admin",
                    "email": "[email protected]",
                    "passwordUpdatedAt": 1640107428,
                    "enabled": true,
                    "maxLogin": 10,
                    "plainPassword": null
                }
            }, {
                "id": 178,
                "fieldDefinitionIdentifier": "signature",
                "languageCode": "eng-GB",
                "fieldTypeIdentifier": "eztext",
                "fieldValue": "Mega boss"
            }, {
                "id": 180,
                "fieldDefinitionIdentifier": "image",
                "languageCode": "eng-GB",
                "fieldTypeIdentifier": "ezimage",
                "fieldValue": {
                    "id": "0/8/1/0/180-5-eng-GB/avatar_19.jpg",
                    "path": "/0/8/1/0/180-5-eng-GB/avatar_19.jpg",
                    "alternativeText": "",
                    "fileName": "avatar_19.jpg",
                    "fileSize": 50787,
                    "imageId": "14-180-5",
                    "uri": "/var/site/storage/images/0/8/1/0/180-5-eng-GB/avatar_19.jpg",
                    "inputUri": null,
                    "width": "480",
                    "height": "580",
                    "additionalData": [],
                    "variations": {
                        "ezplatform_admin_ui_profile_picture_user_menu": {
                            "href": "/api/ezp/v2/content/binary/images/14-180-5/variations/ezplatform_admin_ui_profile_picture_user_menu"
                        },
                        "large": {
                            "href": "/api/ezp/v2/content/binary/images/14-180-5/variations/large"
                        },
                        "medium": {
                            "href": "/api/ezp/v2/content/binary/images/14-180-5/variations/medium"
                        },
                        "reference": {
                            "href": "/api/ezp/v2/content/binary/images/14-180-5/variations/reference"
                        },
                        "small": {
                            "href": "/api/ezp/v2/content/binary/images/14-180-5/variations/small"
                        },
                        "tiny": {
                            "href": "/api/ezp/v2/content/binary/images/14-180-5/variations/tiny"
                        }
                    }
                }
            }]
        },
        "Relations": {
            "_media-type": "application/vnd.ez.api.RelationList json",
            "_href": "/api/ezp/v2/content/objects/14/versions/5/relations",
            "Relation": []
        },
        "Thumbnail": {
            "_media-type": "application/vnd.ez.api.Thumbnail json",
            "resource": "/bundles/ezplatformadminui/img/ez-icons.svg#user",
            "width": null,
            "height": null,
            "mimeType": "image/svg xml"
        }
    },
    "login": "admin",
    "email": "[email protected]",
    "enabled": true,
    "UserGroups": {
        "_media-type": "application/vnd.ez.api.UserGroupList json",
        "_href": "/api/ezp/v2/user/users/14/groups"
    },
    "Roles": {
        "_media-type": "application/vnd.ez.api.RoleAssignmentList json",
        "_href": "/api/ezp/v2/user/users/14/roles"
    }
}

my component

import { Component, OnInit } from '@angular/core';
import { User } from 'src/app/_models';
import { EzUser } from 'src/app/_models/ezuser';
import { AuthenticationService } from 'src/app/_services';

import { UserblockService } from './userblock.service';

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

    currentUser: EzUser;
    error = '';
    pictureUrl: string;
    user: User = {
      id: 1,
      nome: 'ippo',
      cognome: 'adad',
      tipo: {id: 1, name: 'dsad'}
    };

    constructor(public userblockService: UserblockService, private authenticationService: AuthenticationService) {

        this.authenticationService.currentUser.subscribe(x => this.currentUser = x);
        this.pictureUrl = this.currentUser.version.fields.field[0].fieldValue.path;
    }

    ngOnInit() {}

    userBlockIsVisible(): boolean{
        return this.userblockService.getVisibility();
    }
}

CodePudding user response:

the field fields is read on undefined meaning your currentUser is undefined, indeed, you are never setting the value of currentUser before the constructor, I guess your code should be

this.authenticationService.currentUser.subscribe(x => {
   this.currentUser = x
   this.pictureUrl = this.currentUser.version.fields.field[0].fieldValue.path;
});

and you should check after if the picture url is set

CodePudding user response:

this.currentUser.version is undefined, caused by an extremely common mistake in asynchronous programming.

constructor(public userblockService: UserblockService, private authenticationService: AuthenticationService) {
    this.authenticationService.currentUser.subscribe(x => this.currentUser = x);
    this.pictureUrl = this.currentUser.version.fields.field[0].fieldValue.path;
}

this.pictureUrl depends on the assignment from the observable immediately before it, but since that is an asynchronous function, it does not wait for it to complete before continuing to assign this.pictureUrl.

You need to assign it within the observable, commonly I do this in the oncomplete handler, though it can be on the onnext handler as well. oncomplete is only invoked if there was no error.

constructor(public userblockService: UserblockService, private authenticationService: AuthenticationService) {
    this.authenticationService.currentUser.subscribe(
        user => this.currentUser = user,
        error => console.error,
        _ => this.pictureUrl = this.currentUser.version.fields.field[0].fieldValue.path
    );
}

You should also consider doing this in the Angular lifecycle hook ngOnInit() and not the constructor.

CodePudding user response:

this is AuthenticationService

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { Router } from '@angular/router';
import { EzUser } from '../_models/ezuser';
import { EzSession } from '../_models/ezsession';
import { User } from '../_models';

@Injectable({ providedIn: 'root' })
export class AuthenticationService {

    private currentUserSubject: BehaviorSubject<EzUser>;
    public currentUser: Observable<EzUser>;

    private currentSessionSubject: BehaviorSubject<EzSession>;
    public currentSession: Observable<EzSession>;

    constructor(private http: HttpClient, private router: Router) {

        this.currentUserSubject = new BehaviorSubject<EzUser>(JSON.parse(sessionStorage.getItem('ezuser')));
        this.currentUser = this.currentUserSubject.asObservable();

        this.currentSessionSubject = new BehaviorSubject<EzSession>(JSON.parse(sessionStorage.getItem('ezsession')));
        this.currentSession = this.currentSessionSubject.asObservable();
    }

    public get currentSessionValue(): EzSession {
      return this.currentSessionSubject.value;
    }

    public get currentUserValue(): any {
      return this.currentUserSubject.value;
    }

    login(username: string, pass: string): Observable<EzUser> {

      const headers = {
        headers: new HttpHeaders({
          Accept: 'application/vnd.ez.api.Session json',
          'Content-Type': 'application/vnd.ez.api.SessionInput json',
        })
      };

      const body = {
        SessionInput: {
          login: username,
          password: pass
        }
      };

      return this.http.post<EzSession>(`${environment.apiUrl}/user/sessions`, body, headers).pipe(
        map(result => {
              // store user details and basic auth credentials in local storage to keep user logged in between page refreshes
              // session.authdata = window.btoa(username   ':'   pass);
              // sessionStorage.setItem('currentUser', JSON.stringify(session));
              result.authdata = window.btoa(username   ':'   pass);
              sessionStorage.setItem('ezsession', JSON.stringify(result));
              this.currentSessionSubject.next(result);
              return result;
        }),
        mergeMap((x) => {

          const ezsession =  JSON.parse(sessionStorage.getItem('ezsession'));
          const headers2 = {
            headers: new HttpHeaders({
              'Content-Type': ezsession.Session['_media-type'],
              Accept: ezsession.Session.User['_media-type']
            })
          };

          return this.http.get<any>(`${ezsession.Session.User['_href']}`, headers2).pipe(map(result => {
            debugger
            sessionStorage.setItem('ezuser', JSON.stringify(result.User));
            this.currentUserSubject.next(result);
            return result.User;
          }));
        })
      );
    }

    logout(): Observable<any[]> {
      const ezsession =  JSON.parse(sessionStorage.getItem('ezsession'));
      const headers = {
        headers: new HttpHeaders({
          Cookie: ezsession.Session.name   '='   ezsession.Session.identifier,
          'X-CSRF-Token': ezsession.Session.csrfToken
        })
      };

      return this.http.delete<any>(`${environment.apiUrl}/user/sessions/${ezsession.Session.identifier}`, headers).pipe(
        map(result => {
          sessionStorage.removeItem('ezsession');
          sessionStorage.removeItem('ezuser');
          this.currentSessionSubject.next(null);
          this.currentUserSubject.next(null);
          return result;
        })
      );
   }

}
  • Related