angular-redux / form

Keep your Angular2+ form state in Redux
MIT License
41 stars 15 forks source link

Error while binding array #25

Open yonathan06 opened 7 years ago

yonathan06 commented 7 years ago

This is a...

What toolchain are you using for transpilation/bundling?

Environment

NodeJS Version: 6.10 Typescript Version: 2.3.0 Angular Version: 4.0.3 angular-redux/store version: 6.2.0 angular/cli version: 1.0.0-beta.32.3 OS: windows 10

Getting error Cannot read property 'arrivalTime' of undefined

The problematic areas are surrounded by comment ERROR HERE

my html:

<div class="form-panel">
  <div class="steps-panel">
    <div class="step" *ngFor="let step of steps; let i = index; let isLast = last" [ngClass]="{current: i + 1 == (addClientForm$ | async)?.currentPosition, pass: i + 1 < (addClientForm$ | async)?.currentPosition}">
      <div class="circle-holder">
        <div class="circle">
          <span *ngIf="i + 1 >= (addClientForm$ | async)?.currentPosition">{{i + 1}}</span>
          <md-icon *ngIf="i + 1 < (addClientForm$ | async)?.currentPosition">done</md-icon>
        </div>
        <div class="label">{{step}}</div>
      </div>
      <div *ngIf="!isLast" class="line"></div>
    </div>
  </div>
  <ng-container [ngSwitch]="(addClientForm$ | async)?.currentPosition">
    <form class="form" *ngSwitchCase="1" [connect]="['hqAddClientForm', 'clientDetails']">
      <div class="regular-input-holder">
        <div class="label">שם העסק</div>
        <input type="text" name="businessName" ngControl ngModel>
      </div>
      <div class="regular-input-holder">
        <div class="label">מספר העסק</div>
        <input type="text" name="businessNumber" ngControl ngModel>
      </div>
      <div class="regular-input-holder">
        <div class="label">כתובת</div>
        <input type="text" name="address" ngControl ngModel>
      </div>
      <div class="regular-input-holder">
        <div class="label">טלפון</div>
        <input type="text" name="phone" ngControl ngModel>
      </div>
      <div class="regular-input-holder">
        <div class="label">פקס</div>
        <input type="text" name="fax" ngControl ngModel>
      </div>
      <div class="save-and-continue">
        <button md-raised-button class="md-primary-button" (click)="saveContinue()">
          <md-icon>done</md-icon>שמור והמשך
        </button>
      </div>
    </form>
    <form class="form" *ngSwitchCase="2" [connect]="['hqAddClientForm', 'paymentDetails']">
      <div class="regular-input-holder">
        <div class="label">אופן תשלום</div>
        <input type="text" name="paymentMethod" ngControl ngModel>
      </div>
      <div class="regular-input-holder">
        <div class="label">אחוזי הנחה</div>
        <input type="text" name="discountPercentage" ngControl ngModel>
      </div>
      <div class="save-and-continue">
        <button md-raised-button class="md-primary-button" (click)="saveContinue()">
          <md-icon>done</md-icon>שמור והמשך
        </button>
      </div>
    </form>
    <ng-container *ngSwitchCase="3">
      <form class="form" [connect]="['hqAddClientForm', 'managers', 'tmp']">
        <div class="regular-input-holder">
          <div class="label">שם ושם משפחה</div>
          <input type="text" name="firstAndLastName" ngControl ngModel>
        </div>
        <div class="regular-input-holder">
          <div class="label">אימייל</div>
          <input type="email" name="email" ngControl ngModel>
        </div>
        <div class="regular-input-holder">
          <div class="label">נייד</div>
          <input type="phone" name="phone" ngControl ngModel>
        </div>
        <div class="save-and-continue">
          <button md-raised-button class="md-primary-button" (click)="addManager()">
            <md-icon>add</md-icon>הוספת מנהל
          </button>
        </div>
      </form>
      <div class="managers">
        <div class="manager" *ngFor="let manager of (addClientForm$ | async)?.managers?.managers">
          <div class="info">
            <div class="full-name">{{manager.firstAndLastName}}</div>
            <div class="phone-email">
              <span>{{manager.phone}}</span>
              <span>{{manager.email}}</span>
            </div>
          </div>
          <md-icon class="edit">edit</md-icon>
        </div>
      </div>
      <div class="save-and-continue">
        <button md-raised-button class="md-primary-button" (click)="saveContinue()">
          <md-icon>done</md-icon>שמור והמשך
        </button>
      </div>
    </ng-container>
    <div class="system-type form" *ngSwitchCase="4">
      <div class="switch-buttons">
        <div class="button-option" [ngClass]="{clicked: (addClientForm$ | async)?.clientSystemType?.type === 'shifts'}" (click)="toggleSystemType()">משמרות</div>
        <div class="button-option" [ngClass]="{clicked: (addClientForm$ | async)?.clientSystemType?.type === 'general'}" (click)="toggleSystemType()">כללי</div>
      </div>
      <form *ngIf="(addClientForm$ | async)?.clientSystemType?.type === 'general'" class="form" [connect]="['hqAddClientForm', 'clientSystemType', 'general']">
        <div class="regular-input-holder">
          <div class="label">סוג לוח</div>
          <input type="text" name="calendarType" ngControl ngModel>
        </div>
      </form>
      <form *ngIf="(addClientForm$ | async)?.clientSystemType?.type === 'shifts'" class="form" [connect]="['hqAddClientForm', 'clientSystemType', 'shiftsType']">
        <!-- ERROR HERE -->
        <ng-template connectArray let-index connectArrayOf="shifts">
          <div class="regular-input-holder" [ngModelGroup]="index">
            <div class="header">משמרת {{index + 1}}</div>
            <select ngControl ngModel name="arrivalTime">
              <option *ngFor="let num of times" [value]="num">{{num}}</option>
            </select>
            <select ngControl ngModel name="departureTime">
              <option *ngFor="let num of times" [value]="num">{{num}}</option>
            </select>
          </div>
        </ng-template>
       <!-- END ERROR HERE -->
      </form>
      <div class="save-and-continue">
        <button md-raised-button class="md-primary-button" (click)="saveContinue()">
          <md-icon>done</md-icon>שמור והמשך
        </button>
      </div>
    </div>
  </ng-container>
</div>

The rest of the forms are working fine

here is my interface:

export interface HQAddClientForm {
    currentPosition: number,
    clientDetails: {
        businessName: string,
        businessNumber: number,
        // belongsTo: string,
        // businessType: string,
        address: string,
        phone: string,
        fax: string,
    },
    paymentDetails: {
        paymentMethod: string,
        discountPercentage: number
    },
    managers: {
        tmp: HQClientManager,
        managers: HQClientManager[]
    },
    clientSystemType: {
        type: 'general' | 'shifts',
        generalType: {
            calendarType: string
        },
               // --- ERROR HERE ---
        shiftsType: {
            numberOfShifts: number,
            shifts: {
                arrivalTime: string,
                departureTime: string
            }[]
        }
               // --- END ERROR HERE ---
    },
    routes: {
        tmp: HQClientRoute,
        routes: HQClientRoute[]
    }
}

export interface HQClientManager {
    firstAndLastName: string,
    email: string,
    phone: string
}

export interface HQClientRoute {
    origin: string[],
    destination: string[],
    totalKM: number,
    permanentDriver: {
        driverKey: string,
        name: string
    },
    priceExpiritionDate: string,
    driverPayment: {
        amount: number,
        incluedTax: boolean
    },
    totalPayment: {
        amount: number,
        incluedTax: boolean
    }
}

export const initHQAddClientForm: HQAddClientForm = {
    currentPosition: 1,
    clientDetails: {
        businessName: null,
        businessNumber: null,
        // belongsTo: null,
        // businessType: null,
        address: null,
        phone: null,
        fax: null,
    },
    paymentDetails: {
        paymentMethod: null,
        discountPercentage: null
    },
    managers: {
        tmp: {
            firstAndLastName: null,
            email: null,
            phone: null
        },
        managers: []
    },
    clientSystemType: {
        type: 'shifts',
        generalType: {
            calendarType: null
        },
               // --- ERROR HERE ---
        shiftsType: {
            numberOfShifts: null,
            shifts: [{
                arrivalTime: null,
                departureTime: null
            }]
        }
               // --- END ERROR HERE ---
    },
    routes: {
        tmp: {
            origin: [],
            destination: [],
            totalKM: 0,
            permanentDriver: {
                driverKey: null,
                name: null
            },
            priceExpiritionDate: null,
            driverPayment: {
                amount: 0,
                incluedTax: null
            },
            totalPayment: {
                amount: 0,
                incluedTax: null
            }
        },
        routes: []
    }
}

this is the stack trace:

core.es5.js:1084 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'arrivalTime' of undefined
TypeError: Cannot read property 'arrivalTime' of undefined
    at http://localhost:4200/vendor.bundle.js:30431:22
    at http://localhost:4200/vendor.bundle.js:30356:66
    at Array.forEach (native)
    at FormGroup._forEachChild (http://localhost:4200/vendor.bundle.js:30356:36)
    at FormGroup._checkAllValuesPresent (http://localhost:4200/vendor.bundle.js:30430:14)
    at FormGroup.setValue (http://localhost:4200/vendor.bundle.js:30237:14)
    at http://localhost:4200/vendor.bundle.js:30936:18
    at ZoneDelegate.invoke (http://localhost:4200/vendor.bundle.js:156556:26)
    at Object.onInvoke (http://localhost:4200/vendor.bundle.js:8978:37)
    at ZoneDelegate.invoke (http://localhost:4200/vendor.bundle.js:156555:32)
    at http://localhost:4200/vendor.bundle.js:30431:22
    at http://localhost:4200/vendor.bundle.js:30356:66
    at Array.forEach (native)
    at FormGroup._forEachChild (http://localhost:4200/vendor.bundle.js:30356:36)
    at FormGroup._checkAllValuesPresent (http://localhost:4200/vendor.bundle.js:30430:14)
    at FormGroup.setValue (http://localhost:4200/vendor.bundle.js:30237:14)
    at http://localhost:4200/vendor.bundle.js:30936:18
    at ZoneDelegate.invoke (http://localhost:4200/vendor.bundle.js:156556:26)
    at Object.onInvoke (http://localhost:4200/vendor.bundle.js:8978:37)
    at ZoneDelegate.invoke (http://localhost:4200/vendor.bundle.js:156555:32)
    at resolvePromise (http://localhost:4200/vendor.bundle.js:156934:31)
    at http://localhost:4200/vendor.bundle.js:156985:17
    at ZoneDelegate.invokeTask (http://localhost:4200/vendor.bundle.js:156589:31)
    at Object.onInvokeTask (http://localhost:4200/vendor.bundle.js:8969:37)
    at ZoneDelegate.invokeTask (http://localhost:4200/vendor.bundle.js:156588:36)
    at Zone.runTask (http://localhost:4200/vendor.bundle.js:156356:47)
    at drainMicroTaskQueue (http://localhost:4200/vendor.bundle.js:156749:35)
    at <anonymous>

Thought

When I change the value in the problematic