У меня есть форма, позволяющая мне создать запрос на разрешение, заполнив различные поля.
Чтобы отобразить разрешение, я использую метод patchValue для обновления информации о форме.
Моя проблема заключается в том, что когда я не добавляю вложение, все поля остаются пустыми, и наоборот, если я добавляю все поля заполнены их значениями. Я не знаю, что вызывает такое поведение, тем более что при проверке сетевых запросов информация загружается. У кого-нибудь есть повод для отладки? Вот мой код:
/**
* Attachment & FileAttachment Model
**/
export class WorkPermitFileAttachment {
public ID: number;
public FileAttachment: FileAttachment = new FileAttachment();
public Tags = '';
constructor(partial?: Partial<WorkPermitFileAttachment>) {
Object.assign(this, partial);
this.FileAttachment.createFileObject();
}
public static createFromFlat(partial?: Partial<any>) {
const myWorkPermitFileAttachment = new WorkPermitFileAttachment();
if (partial) {
myWorkPermitFileAttachment.Tags = partial.Tags;
myWorkPermitFileAttachment.ID = partial.ID;
delete partial.Tags;
Object.assign(myWorkPermitFileAttachment.FileAttachment, partial);
myWorkPermitFileAttachment.FileAttachment.createFileObject();
}
return myWorkPermitFileAttachment;
}
public static flattenToPOJO(partial?: Partial<WorkPermitFileAttachment>) {
const plainObject = {
...partial,
...partial.FileAttachment,
};
delete plainObject.FileAttachment;
delete plainObject.FileObject;
return plainObject;
}
}
export class FileAttachment {
public ID: number;
public Data: string;
public Name: string;
public Size: number;
public Type: string;
public FileObject: File = null;
constructor(partial?: Partial<FileAttachment>) {
Object.assign(this, partial);
this.createFileObject();
}
public static createFromFile(file: File): Observable<FileAttachment> {
return FileAttachment.fileToBase64(file).pipe(
map(base64File => {
return new FileAttachment({
Data: FileAttachment.base64ToK2File(file.name, base64File),
Name: file.name,
Size: file.size,
Type: file.type,
});
})
);
}
protected static base64ToK2File(fileName, base64File) {
const [_, fileEncoded] = base64File.split('base64,');
return `<file><name>${fileName}</name><content>${fileEncoded}</content></file>`;
}
public static fileToBase64(file: File) {
return from(new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
}));
}
public static b64toBlob(base64, contentType = '', sliceSize = 512): Blob {
const [all, base64String] = base64.match(/<content>(.*)<\/content>/);
const byteCharacters = atob(base64String);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return new Blob(byteArrays, { type: contentType });
}
public createFileObject() {
if (this.Data && this.Name) {
this.FileObject = new File([this.toBlob()], this.Name);
}
}
public getDataBase64() {
const [all, base64String] = this.Data.match(/<content>(.*)<\/content>/);
return `data:${this.Type};base64,${base64String}`;
}
public getFileAttachmentLink() {
return this.getDataBase64();
}
public getImageSrc() {
return this.getDataBase64();
}
public isImage() {
return [
'image/jpeg',
'image/png',
'image/gif',
'image/svg+xml',
].includes(this.Type);
}
private toBlob(): Blob {
return FileAttachment.b64toBlob(this.Data, this.Type);
}
}
/**
* Request Model
**/
export class WorkPermitRequest {
ID: number = null;
RelatedWorkPermitRequestID: number = null;
Reference: string = null;
IsUrgent: Boolean = false;
IsMOEApprobationRequested: Boolean = false;
AuthorUserName: string = null;
AuthorUserDisplayName: string = null;
IsTrackConsigned: Boolean = false;
IsEquipementConsigned: Boolean = false;
EquipmentToConsign: string = null;
IsEquipementShutDown: Boolean = false;
EquipmentToShutDown: string = null;
IsCoWorkingPossible: Boolean = true;
IsTunnelPathUsed: Boolean = false;
IsTrainNeeded: Boolean = false;
IsEscortRequested: Boolean = false;
IsZtconKeptPowered: Boolean = false;
IsTrackPlateformAccessible: Boolean = false;
IsTraficFreezed: Boolean = false;
FreezedTraficReason: string = null;
WorkDescriptionArea: string = null;
@Association({
mapping: 'OneToMany', mappedBy: 'WorkPermitRequestID', service: WorkPermitFileAttachmentService
})
FileAttachments: WorkPermitFileAttachment[] = [];
InterventionStartDate: Date = new Date();
InterventionEndDate: Date = new Date();
IsOutOfDock: Boolean = false;
IsWithinTheDockLimits: Boolean = false;
IsWorkOnTheTrack: Boolean = false;
IsEquipementConsignationRequired: Boolean = false;
IsPreventionPlanNeeded: Boolean = false;
ComplementaryMesure: string = null;
PreventionPlanRef: string = null;
WorkRepresentativeName: string = null;
WorkRepresentativePhoneNumber: string = null;
WorkRepresentativeMail: string = null;
WorkRepresentativeCompanyID: number = null;
QMRSComment: string = null;
MaintenanceComment: string = null;
ExploitationComment: string = null;
OtherComment: string = null;
LastReworkComment: string = null;
PlannedWorkComment: string = null;
Step = 'CREATION';
Status: string = null;
CreatedByUserName: string = null;
CreatedByDisplayName: string = null;
CreatedAt: Date = null;
ModifiedByUserName: string = null;
ModifiedByDisplayName: string = null;
ModifiedAt: Date = null;
constructor(partials?: Partial<any> | null) {
if (partials) {
Object.keys(partials).forEach((key) => (partials[key] == null) && delete partials[key]); // remove null property
}
Object.assign(this, partials);
}
public isExtendable() {
return this.getDaysBetweenToday(this.InterventionEndDate) <= MAX_EXTEND_DELAY;
}
private toDate(property: string): Date {
return new Date(property);
}
private getDaysBetweenToday(date: Date) {
date = new Date(date);
const MS_IN_DAY = 1000 * 60 * 60 * 24;
// Define the work permit request end date
const end = new Date(
date.getFullYear(),
date.getMonth(),
date.getDate(),
);
// Define the boundary date
const now = new Date();
const boundary = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate(),
);
return (boundary.getTime() - end.getTime()) / MS_IN_DAY;
}
}
/**
* Request Component
**/
export class WorkPermitRequestComponent implements OnInit, OnDestroy {
public pickObjectProperties(object, properties) {
const newObject = {};
properties.forEach(property => newObject[property] = object[property]);
return newObject;
}
public getGlobalForm(workPermitRequest, isInitForm) {
const mapping = this.getMapping();
return Object.keys(mapping).reduce((object, key) => {
if (Array.isArray(mapping[key])) {
object[key] = isInitForm ? this.fb.group(this.pickObjectProperties(workPermitRequest, mapping[key])) : this.pickObjectProperties(workPermitRequest, mapping[key]);
} else {
object[key] = isInitForm ? this.fb.array([]) : workPermitRequest[key].map(wpFileAttachment => new WorkPermitFileAttachment(wpFileAttachment));
}
return object;
}, {});
}
private read(): void {
const workPermitRequest: WorkPermitRequest = this.route.snapshot.data['workPermitRequest'];
if (!workPermitRequest) {
return;
}
if (workPermitRequest.LastReworkComment.length !== null && workPermitRequest.Step === 'REWORK') {
this.snackBar.open('Les modifications suivantes sont nécessaire: ' + workPermitRequest.LastReworkComment, 'Ok', {
duration: 5000
});
}
const workPermitFormValue = this.getGlobalForm(workPermitRequest, false);
this.workPermitRequest = workPermitRequest;
workPermitRequest.FileAttachments.forEach(file => {
(this.globalForm.get('FileAttachments') as FormArray).push(this.fb.group(new WorkPermitFileAttachment()));
});
this.globalForm.patchValue(workPermitFormValue);
this.globalForm.get('workDesignation.InterventionStartDate').setValue(new Date(this.workPermitRequest.InterventionStartDate));
this.globalForm.get('workDesignation.InterventionEndDate').setValue(new Date(this.workPermitRequest.InterventionEndDate));
}
}
/**
* Attachment Component
**/
export class AttachmentsComponent implements OnInit {
@Input() form: FormGroup;
@Input() smartBRE: SmartBRE;
public isDisabled = false;
constructor(
private _formBuilder: FormBuilder,
) { }
ngOnInit() {
this.attachmentList.valueChanges.subscribe(value => {
this.isDisabled = this.form.get('FileAttachments').disabled;
});
this.isDisabled = this.form.get('FileAttachments').disabled;
}
get attachmentList(): FormArray {
return this.form.get('FileAttachments') as FormArray;
}
addAttachment() {
this.attachmentList.push(
this._formBuilder.group(new WorkPermitFileAttachment())
);
}
removeAttachment(index) {
this.attachmentList.removeAt(index);
}
}
/**
* Request Service
**/
export class WorkPermitRequestService extends DataAccessService<WorkPermitRequest> {
private workPermitRequestWorkflow: string = this.CONFIG.get()['workflowID']['workPermitRequest'];
private workPermitRequestResource: string = this.CONFIG.get()['SMOSystemName']['workPermitRequest'];
constructor(
injector: Injector,
private wfService: WorkflowService,
private associationMapperService: AssociationMapperService,
private taskService: TaskService,
) {
super(injector, 'workPermitRequest', WorkPermitRequest);
}
public getAll(): Observable<Array<WorkPermitRequest>> {
return this.smoService
.list<WorkPermitRequest>(this.resource).pipe(
map(workPermitRequests => workPermitRequests.map(
workPermitRequest => new WorkPermitRequest(workPermitRequest))
)
);
}
public getWorkPermitRequest(id: number, includes?: string[]): Observable<WorkPermitRequest> {
return this.associationMapperService.get((this as any), id, includes);
}
public newRequest(workPermitRequest: WorkPermitRequest): Observable<WorkPermitRequest> {
return this.saveRequest(workPermitRequest).pipe(
mergeMap(workPermitRequestUpdated => this.wfService.startBusinessWorkflowInstance(
this.workPermitRequestWorkflow,
workPermitRequestUpdated.ID
))
);
}
public saveRequest(workPermitRequest: WorkPermitRequest): Observable<WorkPermitRequest> {
return this.associationMapperService.save((this as any), workPermitRequest);
}
}
/**
* Attachment Service
**/
export class WorkPermitFileAttachmentService extends DataAccessService<WorkPermitFileAttachment> {
constructor(injector: Injector) {
super(injector, 'workPermitFileAttachment'); // must call super()
}
public save(item: WorkPermitFileAttachment): Observable<WorkPermitFileAttachment> {
return this.smoService.save<WorkPermitFileAttachment>(this.resource, item['ID'], WorkPermitFileAttachment.flattenToPOJO(item),);
}
public list(filters?: any): Observable<Array<WorkPermitFileAttachment>> {
return this.smoService.list<WorkPermitFileAttachment>(this.resource, filters).pipe(
map(fileAttachments => fileAttachments.map(file => WorkPermitFileAttachment.createFromFlat(file))),
);
}
}