Hi all,
The add fields extension page is currently empty. Does anyone has the sample code showing how to add a custom field? I would like to add a file upload field.
Thank!
Hi all,
The add fields extension page is currently empty. Does anyone has the sample code showing how to add a custom field? I would like to add a file upload field.
Thank!
This is my solution.
Assumption:
Initially, I followed the instructions provided to create the FE extension as described in here
I created a fields folder
This is my detail component
// lmfile.component.html
<a href="/suitecrm/#/documents/record/{{ this.record.attributes[this.field.definition.id_name] }}">{{field.value}}</a>
// lmfile.component.ts
import {Component} from '@angular/core';
import {BaseFieldComponent} from 'core';
import {DataTypeFormatter} from 'core';
import {FieldLogicManager} from 'core';
@Component({
selector: 'scrm-lmfile-detail',
templateUrl: './lmfile.component.html',
styleUrls: []
})
export class LmFileDetailFieldComponent extends BaseFieldComponent {
constructor(protected typeFormatter: DataTypeFormatter, protected logic: FieldLogicManager) {
super(typeFormatter, logic);
}
}
// lmfile.module.ts
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {LmFileDetailFieldComponent} from './lmfile.component';
import {FormsModule} from '@angular/forms';
@NgModule({
declarations: [LmFileDetailFieldComponent],
exports: [LmFileDetailFieldComponent],
imports: [
CommonModule,
FormsModule
]
})
export class LmFileDetailFieldModule {
}
This is my edit component
// lmfile.component.html
<input type="file" style="display: none;"
(change)="onFileSelected($event)" #fileUpload>
<div class="file-upload">
<button color="primary" (click)="fileUpload.click()">
Upload File
</button>
<a href="/suitecrm/#/documents/record/{{ this.record.attributes[this.field.definition.id_name] }}">{{ this.field.value || "No file uploaded yet." }}</a>
</div>
lmfile.component.ts
import {Component, OnDestroy, OnInit} from '@angular/core';
import { Location } from '@angular/common';
import {HttpClient} from '@angular/common/http';
import {BaseFieldComponent} from 'core';
import {DataTypeFormatter} from 'core';
import {FieldLogicManager} from 'core';
interface Document
{
module: string;
record: string;
isDuplicate: string;
action: string;
return_module: string;
return_action: string;
return_id: string;
module_tab: string;
contact_role: string;
relate_to: string;
relate_id: string;
offset: string;
old_id: string;
contract_id: string;
deleteAttachment: string;
filename: string;
doc_id: string;
doc_url: string;
filename_old_doctype: string;
filename_escaped: string;
filename_remoteName: string;
status_id: string;
revision: string;
template_type: string;
is_template: string;
exp_date: string;
category_id: string;
subcategory_id: string;
description: string;
related_document_name: string;
related_doc_id: string;
assigned_user_name?: string;
assigned_user_id?: string;
active_date?: string;
}
@Component({
selector: 'scrm-lmfile-edit',
templateUrl: './lmfile.component.html',
styleUrls: []
})
export class LmFileEditFieldComponent extends BaseFieldComponent implements OnInit, OnDestroy {
constructor(protected typeFormatter: DataTypeFormatter, protected logic: FieldLogicManager, private http: HttpClient, private location: Location) {
super(typeFormatter, logic);
}
ngOnInit(): void {
super.ngOnInit();
this.subscribeValueChanges();
}
ngOnDestroy(): void {
this.unsubscribeAll();
}
onFileSelected($event: any) {
const file: File = $event.target.files[0];
if (file) {
this.field.value = file.name;
const formData = new FormData();
const document: Document = {
module: 'Documents',
record: '',
isDuplicate: 'false',
action: 'Save',
return_action: 'DetailView',
return_module: 'Documents',
return_id: '',
module_tab: '',
contact_role: '',
relate_to: 'Documents',
relate_id: '',
offset: '1',
old_id: '',
contract_id: '',
deleteAttachment: '0',
filename: '',
doc_id: '',
doc_url: '',
filename_old_doctype: 'Sugar',
filename_escaped: '',
filename_remoteName: '',
status_id: 'Active',
revision: '1',
template_type: '',
is_template: '0',
exp_date: '',
category_id: '',
subcategory_id: '',
description: '',
related_document_name: '',
related_doc_id: '',
};
for (const key in document) {
formData.append(`${key}`, `${document[key]}`);
}
formData.append('filename_file', file);
formData.append('document_name', file.name);
const root = window.location.href.replace(this.location.path(), '').replace('?#', '');
this.http.post(root + "legacy/index.php", formData, {observe: 'response', responseType: 'text'})
.subscribe(resp => {
const parameters = new URLSearchParams(new URL(resp.url).search);
this.parent.attributes[this.field.name.replace('_c', '_id_c')] = parameters.get('record')?? '';
});
}
}
}
// lmfile.module.ts
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {LmFileEditFieldComponent} from './lmfile.component';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
@NgModule({
declarations: [LmFileEditFieldComponent],
exports: [LmFileEditFieldComponent],
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule
]
})
export class LmFileEditFieldModule {
}
I also have to register my new custom field in extension.module.ts
import {FieldRegistry} from 'core';
import {LmFileEditFieldModule} from '../fields/lmfile/templates/edit/lmfile.module';
import {LmFileDetailFieldModule} from '../fields/lmfile/templates/detail/lmfile.module';
import {LmFileEditFieldComponent} from '../fields/lmfile/templates/edit/lmfile.component';
import {LmFileDetailFieldComponent} from '../fields/lmfile/templates/detail/lmfile.component';
@NgModule({
declarations: [],
imports: [
CommonModule,
LmFileEditFieldModule,
LmFileDetailFieldModule
],
})
export class ExtensionModule {
constructor(protected fieldRegistry: FieldRegistry) {
// Refer to baseViewFieldsMap in core/app/core/src/lib/fields/base-fields.manifest.ts
// mode can be detail, edit, list, filter
fieldRegistry.register('default', 'lmfile', 'edit', LmFileEditFieldComponent);
fieldRegistry.register('default', 'lmfile', 'detail', LmFileDetailFieldComponent);
}
init(): void {
}
}