https://xn----1-bedvffifm4g.xn--p1ai/news/%D0%BE%D1%82%D0%BA%D0%B0%D0%B7-%D0%BE%D1%82-%D0%BC%D0%BE%D0%B4%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85-%D0%BE%D0%BA%D0%BE%D0%BD-%D0%B2-1%D1%81-8-3/
Applicability This article discusses the asynchronous model for building business logic, which was added to the “1C:Enterprise” platform, edition 8.3. The information presented is relevant for current platform releases. Refusal to use modal windows in the 1C:Enterprise 8.3 platform During the development of a configuration on the 1C:Enterprise 8 platform, there is occasionally a need to pause program execution until the user makes a decision or performs certain actions. For example, when clicking a button to fill a tabular section, the user should be asked whether to clear the tabular section to prevent the loss of previously entered data. Such behavior can be ensured by the following code: &AtClient Procedure FillGoods(Command) Answer = Question(“The tabular section will be cleared. Continue?”, QuestionDialog.NoYes); If Answer = ReturnCodeDialog.Yes Then //filling algorithm EndIf; EndProcedure As a result of this code fragment, the execution of the program code will be paused, a question will be displayed on the screen, the application interface (except for the question dialog) will become unavailable, the system will wait for the user’s decision, and code execution will resume only after answering the question. Opening modal windows using the OpenModal() method also leads to code execution pause and interface locking. When working with a configuration in web-client mode through a browser, a new window – a pop-up window – will be opened in this case, which will block not only the current tab but also the entire browser interface, including other open windows and tabs. Pop-up windows on the Internet are often used for malicious distribution of unwanted advertising, so browsers contain functions to block pop-up windows. In this case, to work with 1C:Enterprise 8 configurations through a browser, you must disable pop-up blocking. Problems also arise when working on mobile devices. For example, modal windows are not supported on iPad. To solve these problems, blocking windows should be used instead of modal ones. Visually, it looks the same to the user: the window blocks the web-client interface. However, the blocking window is “drawn” on top of the main window, and only the current browser tab in which the configuration is open is blocked, allowing switching to other tabs, since browser modal windows are not used in this case. Thus, pop-up windows in the browser are not opened, and operation via the web-client on mobile devices is ensured. The root element of the configuration has a “Modal Mode Usage Mode” property, which determines whether modal windows can be opened in the configuration. If the “Use” option is selected, modal windows can be opened. If the “Do not use” option is selected, modal windows are not allowed. If an attempt is made to call a method that opens a modal window, the system displays an error message: With this value of the “Modal Mode Usage Mode” property, only blocking windows are allowed. If the “Use with warnings” option is selected, the following text is displayed in the messages window when modal windows are opened: This mode of operation can be used as an intermediate step when reworking the configuration to refuse the use of modal windows. The main difference between blocking windows and modal windows is that opening a blocking window does not pause code execution. Therefore, developers will have to rewrite the program code that uses modal windows, taking this feature into account. The code needs to be divided into two parts: opening the blocking window; processing the user’s choice. The code fragment presented at the beginning of the article should be rewritten as follows: &AtClient Procedure FillGoods(Command) Notification = New NotificationDescription(“FillGoodsQuestionCompletion”, ThisObject); QuestionText = “The tabular section will be cleared. Continue?”; ShowQuestion(Notification, QuestionText, QuestionDialog.NoYes); EndProcedure &AtClient Procedure FillGoodsQuestionCompletion(Result, AdditionalParameters) Export If Result = ReturnCodeDialog.Yes Then //filling algorithm EndIf; EndProcedure After executing the ShowQuestion() procedure, the system does not stop waiting for the user’s answer; code execution continues. The user will be able to make a choice only after the entire procedure completes. At this point, the export procedure FillGoodsQuestionCompletion() will be called. We passed its name to the constructor of the NotificationDescription object. The procedure that will be called after the choice is made can be located in the form module, command module, or a non-global common module. In the example considered, the called procedure is located in the managed form module, so we passed ThisObject to the parameter. Let’s consider calling a procedure located in a common module. To do this, add a new common module NotificationProcessing, set the “Client (managed application)” flag for it, and do not set the “Global” flag. Place the FillGoodsQuestionCompletion() procedure in this module. Then the fill command handler will look like this: &AtClient Procedure FillGoods(Command) Notification = New NotificationDescription(“FillGoodsQuestionCompletion”, NotificationProcessing); QuestionText = “The tabular section will be cleared. Continue?”; ShowQuestion(Notification, QuestionText, QuestionDialog.NoYes); EndProcedure After calling any method that opens a blocking window, the procedure must complete, and the code executed further should be placed in the procedure that will be called after the window closes. To pass context (auxiliary data, some parameters, variable values) from the procedure opening the modal window to the procedure called upon its closing, the third optional parameter of the NotificationDescription object constructor is provided – AdditionalParameters. This object (of any type) will be passed to the procedure described in NotificationDescription as the last parameter. Using the code fragment considered above, this can be done as follows: &AtClient Procedure FillGoods(Command) Parameter1 = 0; Parameter2 = 0; ParametersList = New Structure(“Parameter1, Parameter2”, Parameter1, Parameter2); Notification = New NotificationDescription(“FillGoodsQuestionCompletion”, ThisObject, ParametersList); ShowQuestion(Notification, “The tabular section will be cleared. Continue?”, QuestionDialog.NoYes); EndProcedure &AtClient Procedure FillGoodsQuestionCompletion(Result, AdditionalParameters) Export If Result = ReturnCodeDialog.Yes Then //analyze AdditionalParameters.Parameter1 //analyze AdditionalParameters.Parameter2 EndIf; EndProcedure If you need to pass only one value, you do not need to use a structure; you can assign this value to the AdditionalParameters parameter of the NotificationDescription object constructor. Let’s consider several examples of working with blocking windows. Task 1. Opening another form From a document form, upon clicking the “Open Parameters” button, you need to open a form where there are two checkboxes, Parameter1 and Parameter2, which the user must set. After closing the form, display the parameter values in the message line. Create a common form “ParametersForm”, on which we place the parameters Parameter1 and Parameter2, as well as the CloseForm command: The command handler looks like this: The command handler looks like this: &AtClient Procedure CloseForm(Command) ParametersList = New Structure(“Parameter1, Parameter2”, Parameter1, Parameter2); Close(ParametersList); EndProcedure For the form, set the WindowOpeningMode property to “Block entire interface”: On the document form, place the OpenParameters command, whose handler we describe as follows: &AtClient Procedure OpenParameters(Command) Notification = New NotificationDescription(“OpenParametersCompletion”, ThisObject); OpenForm(“CommonForm.ParametersForm”, , , , , , Notification); EndProcedure &AtClient Procedure OpenParametersCompletion(Result, AdditionalParameters) Export If TypeOf(Result) = Type(“Structure”) Then For Each KeyValue In Result Cycle Message = New UserMessage; Message.Text = “Key: ””” + KeyValue.Key + “””, value = ” + KeyValue.Value; Message.Notify(); EndCycle; EndIf; EndProcedure In user mode, running the configuration under the web-client, we get the following results: To enlarge, click on the image. The window opening mode can also be specified in the last parameter of the OpenForm procedure. &AtClient Procedure OpenParameters(Command) Notification = New NotificationDescription(“OpenParametersCompletion”, ThisObject); OpenForm(“CommonForm.ParametersForm”, , , , , , Notification, WindowOpeningMode.BlockEntireInterface); EndProcedure Task 2. Question when closing the form When closing the processing window, ask the user if they really want to close the window. This task can be solved using the following code, located in the form module of the processing: &AtClient Var NeedToCloseForm; &AtClient Procedure BeforeClosing(Refusal, StandardProcessing) If NOT NeedToCloseForm = True Then Refusal = True; Notification = New NotificationDescription(“BeforeClosingCompletion”, ThisObject); ShowQuestion(Notification, “Do you really want to close the window?”, QuestionDialog.NoYes); EndIf; EndProcedure &AtClient Procedure BeforeClosingCompletion(Result, AdditionalParameters) Export If Result = ReturnCodeDialog.Yes Then NeedToCloseForm = True; Close(); Else NeedToCloseForm = Undefined; EndIf; EndProcedure In the BeforeClosing procedure of the form, the user is asked a question, the Refusal flag is set to True, and form closing is canceled. After a positive answer to the question, the NeedToCloseForm variable is set to True, and the form closes again. Task 3. Entering a numeric value When clicking a button on the processing form, open the standard number input dialog. To do this, you need to use the ShowInputNumber() method instead of InputNumber(), which opens a blocking window instead of a modal one. &AtClient Procedure InputNumber(Command) Notification = New NotificationDescription(“InputNumberCompletion”, ThisObject); ShowInputNumber(Notification, 0, “Enter quantity”, 15, 3); EndProcedure &AtClient Procedure InputNumberCompletion(Result, AdditionalParameters) Export If NOT Result = Undefined Then Message = New UserMessage; Message.Text = “You entered quantity ” + Result; Message.Notify(); EndIf; EndProcedure After closing the number input window, the procedure will be called, to the first parameter of which the entered number or the value Undefined will be passed if the user refused to enter. Task 4. Color selection When clicking a button on the processing form, the user specifies the required color using the standard color selection dialog. Set this color for the background of the pressed button. Add the ColorSelection command to the form with the following handler: &AtClient Procedure ColorSelection(Command) ColorDialog = New ColorDialog; Notification = New NotificationDescription(“ColorSelectionCompletion”, ThisObject); ColorDialog.Show(Notification); EndProcedure &AtClient Procedure ColorSelectionCompletion(Result, AdditionalParameters) Export If NOT Result = Undefined Then Elements.ColorSelection.BackgroundColor = Result; EndIf; EndProcedure For ColorDialog objects (as well as StandardPeriodEditingDialog, FormatStringConstructor, ScheduledJobScheduleDialog, FontDialog), the Show() method opens a blocking window. After the window closes, the procedure will be called, to the first parameter of which the selected value (color, font, etc.) or the value Undefined will be passed if the user refused to select. Note that the FileDialog object does not have a Show() method, unlike color or font selection dialogs, since the implementation of these dialogs is significantly different. To use the file selection dialog in the web-client, you must first connect the file processing extension. Dialogs implemented via the file processing extension do not create such operational problems as browser modal windows, so opening blocking windows for the FileDialog object was not implemented. In conclusion, note that starting from release 8.3.10, support for modal windows in the web-client has been discontinued. In this case, if a modal method is called in the configuration, an exception is generated. Also, support for the “Separate Windows” interface mode has been discontinued in the web-client. Moreover, in both thin and web clients, it is now impossible to open a form in a separate window (when working in the “Tabs” interface mode). Such radical steps allowed abandoning the interface mode that is no longer supported by all modern browsers. What practical conclusion can be drawn from this information? The conclusion is quite simple – if for some reason your configuration still has modal calls, then in these places in the web-client, a window with an error message will be displayed. I want to warn against trying to “google” a quick solution to this problem, as the majority of advice boils down to this recipe: in the configurator at the configuration level, set the “Modal Mode Usage Mode” property to “Use”. Naturally, at the moment, this will not work simply because modern browsers themselves no longer support modal calls. And you have only two ways to solve the problem described above: Update the platform to release 8.3.10+ (8.3.11), set the configuration property “Compatibility Mode” to “Do not use”, and rewrite code fragments using modal methods to the asynchronous model of building business logic. Recommend your clients to use outdated browsers where modal calls were still supported (Mozilla Firefox version 37 and below, Chrome below version 37, etc.). By the way, starting from release 8.3.11, Microsoft Internet Explorer versions 8 and 9 are no longer supported. We have dealt with web browsers in the context of modality, now it is time to clarify the situation with other clients. Starting from version 8.3.5, the “Modal Mode Usage Mode” property in thin and thick clients is taken into account only if the /EnableCheckModal command-line parameter is specified. This parameter is automatically added to the command line only when launching the application from the configurator. If this parameter is not specified, exceptions are not generated and corresponding warnings are not displayed. That is, in practice, when using the thick and thin clients, there is no radical change in operation when using modal mode – modal calls will work as they did before, without issuing any warnings, as in the web-client. To put all the dots on the “i”, let’s note that starting from edition 8.3.9, the thick client ignores the configuration property “Mode of using synchronous calls of platform extensions and external components”, while corresponding synchronous methods work without generating exceptions and displaying warnings. This ignored property was added in edition 8.3.5 to support asynchronous work with external components, cryptography, and file processing extensions in the Google Chrome web browser. It is clear that this has nothing to do with the thick client, and therefore the “quiet” ignoring of this property simply excluded extra checks for the use of synchronous methods when using the configuration. By the way! Due to the fact that the platform is confidently moving towards the web, starting from version 8.3.8, developers introduced certain restrictions on program code related to the logic of closing a form or application, executed in thick and thin clients. Be sure to read our article, which details this nuance. In addition, in the course “Professional development of interfaces and forms in 1C:Enterprise 8.3”, there is a chapter dedicated to the refusal of modality, and you can gain a lot of useful and relevant information on this topic. Colleagues, there are two things that can be read endlessly: the VKontakte feed and the list of changes in the next platform release, so let’s draw final conclusions ;) In the process of considering examples that allow transitioning from elements of the synchronous model to the asynchronous one, you probably already noticed that, in general, the amount of program code has increased. The more code, the higher the complexity of its further maintenance and debugging. Moreover, the amount of code will increase even more if we use a larger number of dialogs during development. Therefore, in the process of developing application solutions oriented for work in the web-client, you need to remember the paradigm of operation that is currently used in modern web applications. Therefore, if your configuration has many interactive dialogs with the user, displaying warnings, it makes sense to review this functionality in favor of some other approaches to organizing interaction with the user.
