Avoiding modal windows
We will use the example from the previous section (picking materials and services for a goods receipt tabular section) to explain how to avoid modal windows in the user interface.
In new configurations modal windows are not allowed by default. This is defined by the Modality usage mode configuration property.
Before you proceed to the practical examples, we will explain why this interface mode is recommended.
As a rule, applications for desktop computers use modal windows. 1C:Enterprise is no exception. Modal windows are handy in scenarios where user input is required for further execution of an algorithm. Such windows block the entire applied solution interface and pause the script execution until they are closed.
But 1C:Enterprise is no longer a desktop-only application, it eventually acquired a web client and mobile device support, which introduced some issues related to modal windows.
In order to display modal windows properly, desktop browsers require specific setup, while mobile browsers do not support modal windows at all.
This is why a special interface mode that does not use modal windows is implemented in 1C:Enterprise. In this mode a window that should normally be modal is displayed within the parent window area and blocks the entire interface. From the user perspective it looks exactly like a modal window because a user cannot perform any other operations until they close the window.
But it does not work this way from the developer perspective. That "blocking window" does not pause the script execution. This means that an algorithm that was previously implemented as a solid script fragment must be divided into two parts: one part is executed before opening the window and the other one is executed when the window is closed.
To inform the platform which script should be executed once the window is closed, the name of the procedure to be executed is passed to the window.
The following example demonstrates how it works. While it is obviously artificial and not suitable for commercial solutions, it prepares you for understanding the second example.
Requesting user input in a form command
Suppose that you need to request a user confirmation before picking materials and services for a goods receipt tabular section.
Requesting user input in an event handler
Let us implement a more complex example where user input is requested in an event handler. Suppose that you need a user confirmation before adding materials to a goods receipt tabular section, and a single confirmation is required for each document.
Just like the previous example, this one does not fit any commercial solution. Still, both examples perfectly illustrate the general approach to avoiding modal windows, which is described earlier in this section.
The new procedure will include single picking with multiple selection available.
- In the GoodsReceipt document form, open the Pick command property palette and then, in the Action field, select the Pick procedure.
- Update the Pick command handler as shown in listing 26.8.
Listing 26.8. Pick button click handler
&AtClient Procedure Pick (Command) FormParameters = New Structure ("MultipleChoice", True); OpenForm("Catalog.MaterialsAndServices.ChoiceForm", FormParameters, Items.Materials); EndProcedure
- Add a blocking confirmation dialog box to the ChoiceProcessing handler of the Materials table (listing 26.9).
Listing 26.9. ChoiceProcessing event handler of the Materials table with a confirmation dialog box
&AtClient Procedure MaterialChoiceProcessing(Item, SelectedValue, StandardProcessing) If AnswerBeforeAdd <> True Then StandardProcessing = False; Notification = New NotifyDescription("AddCompletion", ThisObject, SelectedValue); ShowQueryBox(Notification, "Do you want to add materials to the tabular section?", QuestionDialogMode.YesNo); Else For Each SelectedItem In SelectedValue Do NewRow = Object.Materials.Add(); NewRow.Material = SelectedItem; EndDo; EndIf; EndProcedureThe AnswerBeforeAdd variable is used to determine whether a user answered the question.
If a user has not answered the question, the procedure cancels the standard processing and displays the blocking confirmation dialog box. If a user answered the question earlier, the list of materials is added to the tabular section without any confirmations.
If the AnswerBeforeAdd variable value is not true, the procedure creates a NotifyDescription object. The first parameter of the object constructor is the name of the notification handler procedure, which is executed once the user input is received. The second parameter is the name of the module where the procedure is located (in this example it is the form module). And the third optional parameter contains an array of selected material values (SelectedValue).
Then a nonmodal method ShowQueryBox() displays the confirmation dialog box. The method accepts the NotifyDescription object as a parameter. This object points to the exported module procedure (AddCompletion) that is executed once a user makes a selection in the blocking dialog box.
The MaterialsList parameter of the AddCompletion procedure contains the array of selected material values. The Result parameter contains the user input. If the user answer is Yes, the procedure sets AnswerBeforeAdd to True and then adds the selected materials to the document tabular section.
- Add the procedure shown in listing 26.10 to the form module.
Listing 26.10. AddCompletion() notification handler procedure
&AtClient Procedure AddCompletion(Result, MaterialsList) Export If Result = DialogReturnCode.Yes Then AnswerBeforeAdd = True; For Each selectedItem In MaterialsList Do NewRow = Object.Materials.Add(); NewRow.Material = SelectedItem; EndDo; EndIf; EndProcedureNote that once a user confirms that they want to add materials to the document, the confirmation is never requested again because the value of the AnswerBeforeAdd variable is set to True.
The last thing to do is declare that variable.
- Add the script from listing 26.11 to the beginning of the form module.
Listing 26.11. Variable declaration in a form module
&AtClient Var AnswerBeforeAdd;
In Designer mode
Let us implement the confirmation window.
- Open the configuration property palette and look at the Modality usage mode property (fig. 26.3).
Fig. 26.3. Modality usage mode configuration property
It has the default value "Do not use", which is the recommended mode.
An attempt to open a modal window in this mode returns an error.
To avoid this error, let us use the nonmodal method ShowQueryBox() instead of the modal method DoQueryBox() in the Pick command handler.
For each modal method, the platform has a matching nonmodal method that does not block script execution and does not use a modal window. Nonmodal methods do not cause any web application issues. They have the following specifics:
- Method names begin with Show or Begin. Examples: ShowQueryBox() instead of DoQueryBox(), BeginPutFile instead of PutFile, and so on.
- The first parameter is a NotifyDescription object that points to the module procedure to be executed once the user input is received.
- There is no return value. Istead, the user input is passed to the module procedure described by the NotifyDescription object.
- Add the script shown in listing 26.7 to the GoodsReceipt document form module.
Listing 26.7. Pick button click handler with a confirmation dialog box
&AtClient Procedure PickConfirmation(Command) Notification = New NotifyDescription("PickCompletion", ThisObject); ShowQueryBox(Notification, "Do you want to pick materials and services?", QuestionDialogMode.YesNo); EndProcedure &AtClient Procedure PickCompletion(Result, Parameters) Export If Result = DialogReturnCode.Yes Then FormParameters = New Structure ("MultipleChoice", True); OpenForm("Catalog.MaterialsAndServices.ChoiceForm", FormParameters, Items.Materials); EndIf EndProcedureThe PickConfirmation procedure first creates a NotifyDescription object. The first parameter of the object constructor is the name of the notification handler procedure, which is executed once the user input is received. The second parameter is the name of the module where the procedure is located.
A notification handler procedure can be stored in a managed form module, in a nonglobal common client module, or in a command module. In this example the procedure is located in the module of this form, which is described by the ThisObject reference.
Then a nonmodal method ShowQueryBox() is executed. It displays the confirmation dialog box. The method accepts the NotifyDescription object as a parameter. This object points to the module procedure (PickCompletion) that is executed once a user makes a selection in the blocking dialog box.
A notification handler procedure must be declared as an export procedure (using the Export keyword). The Result parameter contains the user answer. If the user answer is Yes, the procedure opens the materials and services list for picking.
Let us replace the old Pick command handler with a new one.
- In the Pick command property palette, in the Action field, select the PickConfirmation procedure (fig. 26.4).
Fig. 26.4. Specifying the action for the Pick command
In 1C:Enterprise mode
Let us test the changes.
- Start 1C:Enterprise in the debug mode.
- In the Inventory section, open the list of goods receipts and start creating a new one.
- In the command bar, click the Pick button.
This opens the confirmation dialog box. The dialog box blocks the interface but does not block the applied solution execution. You can only proceed to picking materials and services when you confirm that you want to perform this operation.
In 1C:Enterprise mode
Let us test the changes.
- Start 1C:Enterprise in the debug mode.
You can see that the application behavior is almost identical to the previous example, with the following differences: first, the confirmation is requested after the materials are selected, and second, the confirmation is only requested once.
Note. To check whether your configuration includes any modal methods, in Designer, on the Configuration menu, click Check configuration and select the Search for methods that open modal windows check box.