Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I require a field to be mandatory on a NAV page?

Tags:

dynamics-nav

It seems that the underlying nature of NAV is to resist requiring the populating of a field to be mandatory. In the case of our business logic, certain fields must be populated in order for the data to be valid. For example, a customer record must have at least a name and phone number. I've searched a number of places but have not found a suitable solution. So how can this be accomplished?

like image 960
Doug J. Huras Avatar asked Dec 19 '12 15:12

Doug J. Huras


People also ask

How do you make a field mandatory in dynamics?

To do this, I simply right-click on the field and select Personalisation from the menu. As the following screenshot shows, I can now tick the Required option. As shown below, the field is now mandatory (red and marked with an asterisks) when editing the record.

Which field is used to make the field mandatory?

You can make a field mandatory while creating or editing any entity's field under Admin Settings. Making a field required, mandates the user to enter a value while saving a record. This feature is available for Lead, Contact, Account and Deal fields.


1 Answers

After struggling to find a succinct way to require certain fields on a card to be populated, I have come up with the following and it (so far) is working for me. I started to sense that NAV was not meant to have mandatory fields, but I need them for our business logic. Anyways, here we go...

Step One: - We have a codeunit for various validation logic, in which I've added the function to read a custom table listing the tables and their fields that are mandatory. This function takes the table number, key field, and a "create mode". It returns a text "completion status" value. I find the table for the record I am validating. I loop through the mandatory fields, if the field is not populated, I add it to a list of incomplete fields. If the list of incomplete fields is empty, the completion status is "done". If the list of incomplete fields is populated, a message is displayed indicating the missing fields and allows the user an option to cancel the create of a new record or to stay on the (new or existing) record and enter the missing data, and the completion status is set to "delete" to cancel a create, or "return" to stay on the record. Logic follows:

CheckMadatoryFields(TableNumber : Integer;KeyField : Code[10];CreateMode : Boolean)   Completion Status : Text[30]

// Read the 'LockoutFields' table to find the manditory fields for the table passed in.
LockoutFields.RESET;
LockoutFields.SETRANGE("Table No.", TableNumber);
LockoutFields.SETFILTER("Filter ID", 'MANDITORY_FIELD');

// Get a record reference for the table passed in
RecRef.OPEN(TableNumber);
RecRef.SETVIEW('WHERE("No." = FILTER(' + KeyField + '))');

// Set this to done, i.e. data is complete (don't delete by mistake).
CompletionStatus := 'done';

IF RecRef.FINDFIRST THEN BEGIN

// Check the record's manditory field(s) listed in the 'LockoutFields' table to see if they're blank.
  IF LockoutFields.FINDSET THEN BEGIN
    REPEAT
    FldRef := RecRef.FIELD(LockoutFields."Field No.");

    IF FORMAT(FldRef.VALUE) = '' THEN
      FldList := FldList + ' - ' + FldRef.CAPTION + '\';

  UNTIL LockoutFields.NEXT = 0;

END;

IF FldList <> '' THEN BEGIN
  // If creating the record, add the 'Cancel Create' message, otherwise don't.
  IF CreateMode THEN
    DeleteRecord := CONFIRM(Text_ManditoryField + '\' + FldList + '\' + Text_CancelCreate, FALSE)
  ELSE BEGIN
    DeleteRecord := FALSE;
    MESSAGE(Text_ManditoryField + '\' + FldList, FALSE);
  END;

  // Return a 'delete' status when deleting, or a 'return' status to stay on the record.
  IF DeleteRecord THEN
    CompletionStatus := 'delete'
  ELSE
    CompletionStatus := 'return';
  END;
END;

RecRef.CLOSE;`

Step 2: - On the card you want to check for mandatory fields, in my case the Customer card, I added a function to call the validation function in the codeunit described above. I also added logic to the OnQueryClosePage trigger to call my local function. This all worked fine, as the user could not close the Customer card without completing the mandatory fields or cancelling the create of the customer, except if the user were to use Ctrl+PgUp or Ctrl+PgDn, which took them off the record. The trick was putting the the correct logic in the OnNextRecord trigger so that the validation was executed and the Ctrl+PgUp or Ctrl+PgDn still functioned (note: I found this bit somewhere on mibuso, many thanks!). Logic follows:

OnNextRecord(...)
IF CheckManditoryFields = TRUE THEN BEGIN
  Customer := Rec;
  CurrentSteps := Customer.NEXT(Steps);
  IF CurrentSteps <> 0 THEN
    Rec := Customer;
  EXIT(CurrentSteps);
END;

OnQueryClosePage(...)
EXIT(CheckManditoryFields);

CheckMandatoryFields() ExitValue : Boolean
// Check for manditory fields on this table.  If there are missing manditory
// fields, the user can cancel this create, in which case, a 'TRUE' value is
// returned and we'll delete this record.

ExitValue := TRUE;

IF Rec."No." <> '' THEN BEGIN  // This is blank if user quits immediately after page starts.
  CompletionStatus := HHValidation.CheckManditoryFields(18,Rec."No.",CreateMode);

  IF (CompletionStatus = 'delete')
  AND (CreateMode = TRUE) THEN  // User cancelled create (not edit), delete the record and exit.
    Rec.DELETE(TRUE)
  ELSE
    IF CompletionStatus = 'done' THEN  // User completed manditory fields, OK to exit.
      ExitValue := TRUE
    ELSE
      ExitValue := FALSE;  //User did not complete manditory fields and wants to return and add them.
END;

I think that's about it. The details of the custom table are really up to how you want to code it. The validation code unit can be what you want it to be. Using a table allows the mandatory fields to added or removed without changing any logic, and this "generic" validation logic could be put on any page. The key is the two triggers on the card and having a common validation routine to call.

like image 138
Doug J. Huras Avatar answered Nov 12 '22 14:11

Doug J. Huras