I'm currently working on a custom field type, more specifically on the template content associated with it. Maybe it's best to first show you what I have, what I get, and what I expected to see instead.
custom/Espo/Custom/Resources/metadata/fields/contactDetails.json
client/custom/src/views/fields/contact-details.js
What I see:
const raw = this.model.get(this.name) || '{}';
The data doesn't seem to be availble in some cases, so that raw is initiated to {}.
So I guess my question is: What is the best place to call model.get()?
custom/Espo/Custom/Resources/metadata/fields/contactDetails.json
Code:
{
"params": [],
"view": "custom:views/fields/contact-details"
}
Code:
define(['views/fields/base'], (BaseFieldView) => {
return class extends BaseFieldView {
type = 'contactDetails';
editTemplateContent = `
<div>
<input type="text" class="form-control" data-field="contact-name" value="{{name}}" placeholder="{{contactNamePlaceholder}}" /><br>
<input type="text" class="form-control" data-field="contact-phone" value="{{phone}}" placeholder="{{contactPhonePlaceholder}}" /><br>
<input type="email" class="form-control" data-field="contact-email" value="{{email}}" placeholder="{{contactEmailPlaceholer}}" />
</div>
`;
detailTemplateContent = `
<div>
<strong>Name:</strong> {{name}}<br>
<strong>Phone:</strong> <a href="tel:{{phone}}">{{phone}}</a><br>
<strong>Email:</strong> <a href="mailto:{{email}}">{{email}}</a>
</div>
`;
listTemplateContent = `
{{name}} <{{email}}> {{phone}}
`;
data() {
const formData = this.formData || { name: '', phone: '', email: '' };
return {
...formData,
contactNamePlaceholder: this.placeholderName,
contactPhonePlaceholder: this.placeholderPhone,
contactEmailPlaceholer: this.placeholderEmail,
};
}
setup() {
// Calling the parent `setup` method, can be omitted.
super.setup();
const raw = this.model.get(this.name) || '{}';
console.log(raw);
try {
const parsed = JSON.parse(raw);
this.formData = {
name: parsed.name || '',
phone: parsed.phone || '',
email: parsed.email || ''
};
} catch (e) {
this.formData = { name: '', phone: '', email: '' };
}
// Add translations to be used in the template
this.placeholderName = this.translate('contactDetailsName', "labels", "Fields");
this.placeholderPhone = this.translate('contactDetailsPhone', "labels", "Fields");
this.placeholderEmail = this.translate('contactDetailsEmail', "labels", "Fields");
}
fetch() {
const contactData = {
name: this.$el.find('[data-field="contact-name"]').val().trim(),
phone: this.$el.find('[data-field="contact-phone"]').val().trim(),
email: this.$el.find('[data-field="contact-email"]').val().trim()
};
return {
[this.name]: JSON.stringify(contactData)
};
}
};
});
- When I create a field with this type and add it to the entity layout, it does show with the expected placeholders. So, this part of the template data works fine.
- When I save the form, the information on the detail page is shown correctly. So, here the data values for name, phone, and email work fine.
- When I refresh the page and I click on the newly created entry, THE FIRST TIME the template data for name, phone, and email are not available.
- When I go back and click on the newly created entry again, it works just fine.
const raw = this.model.get(this.name) || '{}';
The data doesn't seem to be availble in some cases, so that raw is initiated to {}.
So I guess my question is: What is the best place to call model.get()?

Comment