Doubt about working the frontend in SuiteCRM 8

What would be the correct way to create a new component or extend an existing one(in Angular), either to add new business logic or change the visual appearance of the component? I am currently working with SuiteCRM 8, and I have this question. I’ve seen the guide and videos that cover backend customization, but I can’t find anything about the frontend.

Currently, I have a particular need: I have created two custom fields in the Account module called “Cédula” and “Document Type”. I need the “Cédula” field to have different format validations based on the selected “Document Type” option, and I am not sure how to implement this validation in SuiteCRM.

I understand that if I make changes to the SuiteCRM frontend, since it is built with Angular, I would need to recompile. I’m not sure if I’m correct about this, and if so, whether recompiling the project is viable.

Check out this video:

Hello RSP,
Thank you for your response, but creating a custom module has nothing to do with my initial question.

Hi @hipolito

yes you need to rebuild the front-end after any changes.

You can read about that here:

2 Likes

Hi @pgr
Thank you very much for the guide. I would like to consult you about an implementation I am doing in the account module. I have created two custom fields: a text field and a radio button. I need the validation of the text field to vary depending on the option selected in the radio button. For example, if one option is selected, the field should accept numbers and letters; if another is selected, only letters, or the maximum length may vary. What would be the best way to implement this validation logic?

I think this implementation can be done in one of the following two ways.

  1. Writing code in angular (typescript) code in defaultExt folder. Extension folder code changes are upgrade safe & help keeping customization in separate folder. When rebuilt, only extension package is generated and if required, the package can be removed and configured not to be used in extension.php file.
    OR

  2. Writing code in php using process handler like one shown in ‘calculate field value using backend logic’

    Using process handler looks a feasible solution using a field logic something like

    'logic' => [
    'key' => 'updateValueBackend' 
    'params'=>[
		'fieldDepencies' => ['radiobuttonfield'],
		'process' => 'formatted-value',
		'actionOnFields' => ['radiobuttonfield' => ['operator' => 'not-empty']]
		]
Write your validation in 
    public function validate(Process $process): void
	{
		...
	}
3 Likes

Hi @Harshad
I implemented your solution and it works, but now I have a major challenge that I believe is related to SuiteCRM. I’ve seen in many examples from SuiteCRM documentation, and now that I’m implementing it in the validate() function, I have the following problem:

When I use throw new InvalidArgumentException(self::MSG_OPTIONS_NOT_FOUND);, no matter what label I send, it always returns the ERR_FIELD_LOGIC_BACKEND_CALCULATION label. I need to display the label sent through InvalidArgumentException to the user. I believe (and please correct me if I’m wrong) that this is an issue with SuiteCRM 8. I’m using version 8.7.0.

While reviewing the code, I see .ts and .mjs files that perform a validation which, if the value is null, displays that label. What I don’t understand is why this validation is present in so many files and why it always ignores the label sent through InvalidArgumentException. I need to be able to handle that label to indicate something more specific, rather than just the general label ERR_FIELD_LOGIC_BACKEND_CALCULATION, which says: “Error while trying to get the value.”

Additionally, I added alerts, but they are not being displayed either. I’m not sure if I need to do a rebuild for it to apply the changes I made in the .ts and .mjs files. If so, I would appreciate it if you could guide me on how to do that.

Thanks for the reply. I think you can try to trigger your validation logic check in ‘run’ method keeping only process handler validation in validate() method. The label should be in custom/include/language/en_us.lang.php in $app_strings array. Here is pseudo code that has validation logic in valid() method and being called in run in process handler class. If the method returns not true then show the error message and reload the view with current details.

if(!valid($record_data)){
		 $process->setStatus('error');
         $process->setMessages(['LBL_RECORD_NOT_FOUND']);
         $process->setData(['reload' => true]);
}

Thank you very much for your response. I already tried setting the status to “error” and “failure”, but it didn’t work. The setMessages does display the message in the GraphQL response, but the user still sees the ERR_FIELD_LOGIC_BACKEND_CALCULATION label in the red alert. I need to be able to configure the alert message shown to the end user. Attached is an image.

Is the success message displayed correctly if you set messages in setMessages for the valid data. It is displayed in green bg.

If it’s successful, no alert is displayed. An alert is only shown when the data attribute is not set or when the status is “error” or “failure,” which is what I understand from reviewing the code and matches the behavior I’ve observed in my tests.

I think that the negative messages are deliberately generalized to “action failed” as a security measure, to avoid giving away too much information to hackers “poking” the system in different ways to see how it breaks.

I worked on something like this is core code recently, and I know we made minor front-end changes to the way labels are displayed, but I don’t remember exactly what we changed. It’s possible that the next version (or the one after that one) has improvements in this…

Hi @Harshad @pgr
I found a solution: on the frontend side, I checked if there were any messages, iterated through them, and displayed them. I added that validation in the file core/app/core/src/lib/fields/field-logic/update-value-backend/update-value-backend.action.ts, and it worked correctly. Then I ran yarn build:core followed by yarn build, and it worked as expected. I am attaching the added code snippet.

However, now I have another problem: I want to achieve this from the extensions folder, which is the correct way to make customizations. What would be the correct path within the extensions folder? I was reading the SuiteCRM documentation, and from what I understand, this path I modified cannot be extended. Is that true, or am I mistaken?

  1. Enable the extension folder by setting 'enabled' => true, in the file at {ROOT}\extensions\defaultExt\config\extension.php
$extensions['defaultExt'] = [
    'remoteEntry' => '../extensions/defaultExt/remoteEntry.js',
    'remoteName' => 'defaultExt',
    'enabled' => true,
  1. Run php bin/console cache:clear from the command line at root path.

  2. Make your changes in typescript files.

  3. Run the yarn run build-dev:defaultExt --watch test the code changes in progress. Refresh the current page to verify the code change effects. Run 'yarn run build-dev:defaultExt' OR 'yarn run build:defaulExt' to include the extension package.

1 Like

Thank you very much for the step-by-step explanation. I understand that part, but my question is: can this path be customized from the extensions folder: core/app/core/src/lib/fields/field-logic/update-value-backend/update-value-backend.action.ts

what I have read says that this route cannot be extended, I don’t know if I am right.

I am not sure about the best efficient way to extend the existing actions or services. But the following works for me.

  1. Copy an action/service file from core to defaultExt folder in a folder (fields or records or services etc).
  2. Change the imports statements to import from ‘core’ and change the run method according to the required logic.
  3. Change the extension.module.ts to set the run method definition to the custom action run method which gets called when core action is to be called.
  4. Run yarn run build-dev:default --watch command to test the code changes.

Thank you very much for your response. I’m trying, but I still can’t get it to work. If possible, could you provide me with an example of how the folder structure should look within the extension folder to modify the following file: core/app/core/src/lib/fields/field-logic/update-value-backend/update-value-backend.action.ts? I would really appreciate it if you could.